From dea767bfe91ba408b09e4f9bcd503dd2150276a7 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 6 Apr 2014 18:55:34 +0000 Subject: Steam: server polling, status changing, messaging git-svn-id: http://svn.miranda-ng.org/main/trunk@8873 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Steam/Steam_12.vcxproj | 2 + protocols/Steam/Steam_12.vcxproj.filters | 6 ++ protocols/Steam/src/Steam/message.h | 100 +++++++++++++++++++++++ protocols/Steam/src/Steam/poll.h | 61 ++++++++------ protocols/Steam/src/Steam/steam.h | 1 + protocols/Steam/src/steam.h | 2 +- protocols/Steam/src/steam_account.cpp | 69 ++++++++++++++++ protocols/Steam/src/steam_contacts.cpp | 27 ++++++- protocols/Steam/src/steam_dialogs.cpp | 131 ++++++++----------------------- protocols/Steam/src/steam_messages.cpp | 47 +++++++++++ protocols/Steam/src/steam_proto.cpp | 35 ++++++--- protocols/Steam/src/steam_proto.h | 19 +++++ protocols/Steam/src/steam_thread.cpp | 104 +++++++++++++++++------- 13 files changed, 438 insertions(+), 166 deletions(-) create mode 100644 protocols/Steam/src/Steam/message.h create mode 100644 protocols/Steam/src/steam_messages.cpp (limited to 'protocols') diff --git a/protocols/Steam/Steam_12.vcxproj b/protocols/Steam/Steam_12.vcxproj index 27e8bf8acf..19c0828fe6 100644 --- a/protocols/Steam/Steam_12.vcxproj +++ b/protocols/Steam/Steam_12.vcxproj @@ -199,6 +199,7 @@ + @@ -211,6 +212,7 @@ + Create diff --git a/protocols/Steam/Steam_12.vcxproj.filters b/protocols/Steam/Steam_12.vcxproj.filters index 0dc0ba34af..5c30306822 100644 --- a/protocols/Steam/Steam_12.vcxproj.filters +++ b/protocols/Steam/Steam_12.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + @@ -80,6 +83,9 @@ Header Files\Steam + + Header Files\Steam + diff --git a/protocols/Steam/src/Steam/message.h b/protocols/Steam/src/Steam/message.h new file mode 100644 index 0000000000..d5059c4833 --- /dev/null +++ b/protocols/Steam/src/Steam/message.h @@ -0,0 +1,100 @@ +#ifndef _STEAM_MESSAGE_H_ +#define _STEAM_MESSAGE_H_ + +namespace SteamWebApi +{ + class MessageApi : public BaseApi + { + public: + class SendResult : public Result + { + friend MessageApi; + + private: + DWORD timestamp; + + public: + SendResult() : timestamp(0) { } + + const DWORD GetTimestamp() const { return timestamp; } + }; + + static void SendStatus(HANDLE hConnection, const char *token, const char *sessionId, int state, SendResult *sendResult) + { + sendResult->success = false; + + CMStringA data; + data.AppendFormat("access_token=%s", token); + data.AppendFormat("&umqid=%s", sessionId); + data.AppendFormat("&persona_state=%u", state); + data.Append("&type=personastate"); + + HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Message/v0001"); + request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + request.SetData(data.GetBuffer(), data.GetLength()); + + mir_ptr response(request.Send()); + if (!response || response->resultCode != HTTP_STATUS_OK) + return; + + sendResult->success = true; + } + + static void SendMessage(HANDLE hConnection, const char *token, const char *sessionId, const char *steamId, const char *text, SendResult *sendResult) + { + sendResult->success = false; + + CMStringA data; + data.AppendFormat("access_token=%s", token); + data.AppendFormat("&umqid=%s", sessionId); + data.AppendFormat("&steamid_dst=%s", steamId); + data.Append("&type=saytext"); + data.AppendFormat("&text=%s", ptrA(mir_urlEncode(text))); + + HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Message/v0001"); + request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + request.SetData(data.GetBuffer(), data.GetLength()); + + mir_ptr response(request.Send()); + if (!response || response->resultCode != HTTP_STATUS_OK) + return; + + JSONNODE *root = json_parse(response->pData), *node; + + node = json_get(root, "error"); + ptrW error(json_as_string(node)); + + if (lstrcmp(error, L"OK")) + return; + + node = json_get(root, "utc_timestamp"); + sendResult->timestamp = atol(ptrA(mir_u2a(json_as_string(node)))); + + sendResult->success = true; + } + + static void SendTyping(HANDLE hConnection, const char *token, const char *sessionId, const char *steamId, SendResult *sendResult) + { + sendResult->success = false; + + CMStringA data; + data.AppendFormat("access_token=%s", token); + data.AppendFormat("&umqid=%s", sessionId); + data.AppendFormat("&steamid_dst=%s", steamId); + data.Append("&type=typing"); + + HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Message/v0001"); + request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + request.SetData(data.GetBuffer(), data.GetLength()); + + mir_ptr response(request.Send()); + if (!response || response->resultCode != HTTP_STATUS_OK) + return; + + sendResult->success = true; + } + }; +} + + +#endif //_STEAM_MESSAGE_H_ \ No newline at end of file diff --git a/protocols/Steam/src/Steam/poll.h b/protocols/Steam/src/Steam/poll.h index c99bfecf0b..a8e7c76306 100644 --- a/protocols/Steam/src/Steam/poll.h +++ b/protocols/Steam/src/Steam/poll.h @@ -1,5 +1,5 @@ -#ifndef _STEAM_POOL_H_ -#define _STEAM_POOL_H_ +#ifndef _STEAM_POLL_H_ +#define _STEAM_POLL_H_ namespace SteamWebApi { @@ -8,10 +8,11 @@ namespace SteamWebApi public: enum POOL_TYPE { - UNKNOWN = 0, - MESSAGE = 1, - TYPING = 2, - STATE = 3, + UNKNOWN, + MESSAGE, + MYMESSAGE, + TYPING, + STATE, //POOL_TYPE_RELATIONSHIP = 4 }; @@ -23,7 +24,6 @@ namespace SteamWebApi std::string steamId; DWORD timestamp; POOL_TYPE type; - bool send; public: PoolItem() : timestamp(0), type(POOL_TYPE::UNKNOWN) { } @@ -31,12 +31,11 @@ namespace SteamWebApi const char *GetSteamId() const { return steamId.c_str(); } const DWORD GetTimestamp() const { return timestamp; } POOL_TYPE GetType() const { return type; } - bool IsSend() const { return send; } }; - class Typing : PoolItem { friend PollApi; }; + class Typing : public PoolItem { friend PollApi; }; - class Message : PoolItem + class Message : public PoolItem { friend PollApi; @@ -47,7 +46,7 @@ namespace SteamWebApi const wchar_t *GetText() const { return text.c_str(); } }; - class State : PoolItem + class State : public PoolItem { friend PollApi; @@ -65,13 +64,15 @@ namespace SteamWebApi friend PollApi; private: + bool need_relogin; UINT32 messageId; std::vector items; public: - PollResult() : messageId(0) { } + PollResult() : messageId(0), need_relogin(false) { } UINT32 GetMessageId() const { return messageId; } + int IsNeedRelogin() const { return need_relogin; } int GetItemCount() const { return items.size(); } const PoolItem * operator[](int idx) const { return items.at(idx); } }; @@ -84,12 +85,12 @@ namespace SteamWebApi data.AppendFormat("access_token=%s", token); data.AppendFormat("&umqid=%s", sessionId); data.AppendFormat("&message=%i", messageId); - //data.Append("§imeout=30"); + //data.Append("§imeout=90"); HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Poll/v0001"); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.SetData(data.GetBuffer(), data.GetLength()); - request.timeout = 35000; + request.timeout = 90000; mir_ptr response(request.Send()); if (!response || response->resultCode != HTTP_STATUS_OK) @@ -98,16 +99,20 @@ namespace SteamWebApi JSONNODE *root = json_parse(response->pData), *node, *child; node = json_get(root, "error"); ptrW error(json_as_string(node)); - /*if (!lstrcmpi(error, L"Not Logged On")) + + if (!lstrcmpi(error, L"Not Logged On")) { + pollResult->need_relogin = true; + pollResult->success = true; + return; } - else */ - /*if (!lstrcmpi(error, L"Timeout")) + else + if (!lstrcmpi(error, L"Timeout")) { pollResult->messageId = messageId; pollResult->success = true; return; - }*/ + } else if (lstrcmpi(error, L"OK")) return; @@ -128,20 +133,24 @@ namespace SteamWebApi node = json_get(child, "type"); ptrW type(json_as_string(node)); - if (!lstrcmpi(type, L"saytext") || !lstrcmpi(type, L"emote")) + if (!lstrcmpi(type, L"saytext") || !lstrcmpi(type, L"emote") || + !lstrcmpi(type, L"my_saytext") || !lstrcmpi(type, L"my_emote")) { Message *message = new Message(); - message->type = POOL_TYPE::MESSAGE; + + if (_tcsstr(type, L"my_") == NULL) + message->type = POOL_TYPE::MESSAGE; + else + message->type = POOL_TYPE::MYMESSAGE; node = json_get(child, "text"); if (node != NULL) message->text = json_as_string(node); + node = json_get(child, "utc_timestamp"); + message->timestamp = atol(ptrA(mir_u2a(json_as_string(node)))); + item = message; } - /*if (!lstrcmpi(type, L"my_saytext") || !lstrcmpi(type, L"my_emote")) - { - poll->type = POOL_TYPE::MESSAGE; - }*/ else if(!lstrcmpi(type, L"typing")) { item = new Typing(); @@ -155,7 +164,7 @@ namespace SteamWebApi node = json_get(child, "persona_state"); if (node != NULL) state->status = json_as_int(node); - node = json_get(child, "personaname"); + node = json_get(child, "persona_name"); if (node != NULL) state->nickname = json_as_string(node); item = state; @@ -189,4 +198,4 @@ namespace SteamWebApi } -#endif //_STEAM_POOL_H_ \ No newline at end of file +#endif //_STEAM_POLL_H_ \ No newline at end of file diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h index fc23594dca..54acf01ab8 100644 --- a/protocols/Steam/src/Steam/steam.h +++ b/protocols/Steam/src/Steam/steam.h @@ -35,5 +35,6 @@ namespace SteamWebApi #include "Steam\friend_list.h" #include "Steam\friend.h" #include "Steam\poll.h" +#include "Steam\message.h" #endif //_STEAM_H_ \ No newline at end of file diff --git a/protocols/Steam/src/steam.h b/protocols/Steam/src/steam.h index 796689f4df..376491066f 100644 --- a/protocols/Steam/src/steam.h +++ b/protocols/Steam/src/steam.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp index a08926cff3..768bfc4914 100644 --- a/protocols/Steam/src/steam_account.cpp +++ b/protocols/Steam/src/steam_account.cpp @@ -1,10 +1,79 @@ #include "common.h" +WORD CSteamProto::SteamToMirandaStatus(int state) +{ + switch (state) + { + case 0: //Offline + return ID_STATUS_OFFLINE; + case 2: //Busy + return ID_STATUS_DND; + case 3: //Away + return ID_STATUS_AWAY; + /*case 4: //Snoozing + prim = PURPLE_STATUS_EXTENDED_AWAY; + break; + case 5: //Looking to trade + return "trade"; + case 6: //Looking to play + return "play";*/ + //case 1: //Online + default: + return ID_STATUS_ONLINE; + } +} + +int CSteamProto::MirandaToSteamState(int status) +{ + switch (status) + { + case ID_STATUS_ONLINE: + return 1; //Online + case ID_STATUS_DND: + return 2; //Busy + case ID_STATUS_AWAY: + return 3; //Away + /*case 4: //Snoozing + prim = PURPLE_STATUS_EXTENDED_AWAY; + break; + case 5: //Looking to trade + return "trade"; + case 6: //Looking to play + return "play";*/ + //case 1: //Online + default: + return ID_STATUS_OFFLINE; + } +} + bool CSteamProto::IsOnline() { return m_iStatus > ID_STATUS_OFFLINE; } +void CSteamProto::SetServerStatusThread(void *arg) +{ + WORD status = *((WORD*)arg); + + ptrA token(getStringA("TokenSecret")); + ptrA sessionId(getStringA("SessionID")); + + int state = CSteamProto::MirandaToSteamState(status); + + // change status + if (m_iStatus == state) + return; + + int oldStatus = m_iStatus; + m_iStatus = state; + + SteamWebApi::MessageApi::SendResult sendResult; + SteamWebApi::MessageApi::SendStatus(m_hNetlibUser, token, sessionId, state, &sendResult); + + if (sendResult.IsSuccess()) + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); +} + void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResult) { ptrW username(getWStringA("Username")); diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp index ab95bf4649..9e01da2e33 100644 --- a/protocols/Steam/src/steam_contacts.cpp +++ b/protocols/Steam/src/steam_contacts.cpp @@ -1,5 +1,23 @@ #include "common.h" +void CSteamProto::SetContactStatus(MCONTACT hContact, WORD status) +{ + WORD oldStatus = getWord(hContact, "Status", ID_STATUS_OFFLINE); + if (oldStatus != status) + setWord(hContact, "Status", status); +} + +void CSteamProto::SetAllContactsStatus(WORD status) +{ + for (MCONTACT hContact = db_find_first(this->m_szModuleName); hContact; hContact = db_find_next(hContact, this->m_szModuleName)) + { + if (this->isChatRoom(hContact)) + continue; + //if (this->IsContactOnline(hContact)) + setWord(hContact, "Status", status); + } +} + MCONTACT CSteamProto::FindContact(const char *steamId) { MCONTACT hContact = NULL; @@ -26,10 +44,11 @@ MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Friend &contact) hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)this->m_szModuleName); - this->setString(hContact, "SteamID", contact.GetSteamId()); - this->setWString(hContact, "Nick", contact.GetNickname()); - this->setString(hContact, "Homepage", contact.GetHomepage()); - this->setDword(hContact, "LastEventDateTS", contact.GetLastEvent()); + setString(hContact, "SteamID", contact.GetSteamId()); + setWString(hContact, "Nick", contact.GetNickname()); + setString(hContact, "Homepage", contact.GetHomepage()); + setDword(hContact, "LastEventDateTS", contact.GetLastEvent()); + db_set_ws(hContact, "CList", "MyHandle", contact.GetNickname()); DBVARIANT dbv; if (!getWString("DefaultGroup", &dbv)) diff --git a/protocols/Steam/src/steam_dialogs.cpp b/protocols/Steam/src/steam_dialogs.cpp index c98f3c1eda..d7ec5c1f77 100644 --- a/protocols/Steam/src/steam_dialogs.cpp +++ b/protocols/Steam/src/steam_dialogs.cpp @@ -1,11 +1,7 @@ #include "common.h" -//#include -//#pragma comment(lib, "GdiPlus.lib") INT_PTR CALLBACK CSteamProto::GuardProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - //HDC hdc; - //HBITMAP hBitmap, cBitmap; GuardParam *guard = (GuardParam*)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) @@ -58,8 +54,6 @@ INT_PTR CALLBACK CSteamProto::GuardProc(HWND hwnd, UINT message, WPARAM wParam, INT_PTR CALLBACK CSteamProto::CaptchaProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - //HDC hdc; - //HBITMAP hBitmap, cBitmap; CaptchaParam *captcha = (CaptchaParam*)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) @@ -69,38 +63,6 @@ INT_PTR CALLBACK CSteamProto::CaptchaProc(HWND hwnd, UINT message, WPARAM wParam { captcha = (CaptchaParam*)lParam; SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); - - //HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, captcha->size); - //LPVOID pImage = GlobalLock(hMem); - //memcpy(pImage, captcha->data, captcha->size); - //GlobalUnlock(hMem); - - //IStream* pStream = NULL; - //if (CreateStreamOnHGlobal(hMem, FALSE, &pStream) == S_OK) - //{ - // HANDLE hBmp = CreateBitmap(260, 40, 1, 24, captcha->data); - // //Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromStream(pStream); - // SendDlgItemMessage(hwnd, IDC_CAPTCHA, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)pBitmap); - // delete pBitmap; - // pStream->Release(); - //} - - //HANDLE hBmp = CreateBitmap(260, 40, 1, 24, captcha->data); - - /*tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)captcha->data; - tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(captcha->data + sizeof(tagBITMAPFILEHEADER)); - RGBQUAD rgb = *(RGBQUAD*)(captcha->data + sizeof(tagBITMAPFILEHEADER) + sizeof(tagBITMAPINFOHEADER)); - - BITMAPINFO bi; - bi.bmiColors[0] = rgb; - bi.bmiHeader = bih; - - char* pPixels = ((char*)captcha->data + bfh.bfOffBits); - - char* ppvBits; - hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&ppvBits, NULL, 0); - SetDIBits(NULL, hBitmap, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS); - GetObject(hBitmap, sizeof(BITMAP), &cBitmap);*/ } return TRUE; @@ -108,68 +70,43 @@ INT_PTR CALLBACK CSteamProto::CaptchaProc(HWND hwnd, UINT message, WPARAM wParam EndDialog(hwnd, 0); break; - //case WM_PAINT: - // { - // PAINTSTRUCT ps; - // HDC hdc = BeginPaint(hwnd, &ps); - // HBITMAP hBitmap = CreateBitmap(260, 40, 1, 24, captcha->data); - // if(hBitmap != 0) - // { - // HDC hdcMem = CreateCompatibleDC(hdc); - // SelectObject(hdcMem, hBitmap); - // BitBlt(hdc, 10, 10, 260, 40, hdcMem, 0, 0, SRCCOPY); - // DeleteDC(hdcMem); - // } - // EndPaint(hwnd, &ps); - // } - // return 0; - - //case WM_DRAWITEM: - // { - // LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; - - // if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_CAPTCHA) - // { - // FI_INTERFACE *fei = 0; - - // FIBITMAP *fb = fei->FI_CreateDIBFromHBITMAP(hbm); - // FIBITMAP *fbResized = fei->FI_Rescale(fb, newWidth, newHeight, FILTER_BICUBIC); - // HBITMAP hbmResized = fei->FI_CreateHBITMAPFromDIB(fbResized); - // fei->FI_Unload(fb); - // fei->FI_Unload(fbResized); - - // HBITMAP hbmTempOld; - // HDC hdcTemp = CreateCompatibleDC(r->hTargetDC); - // hbmTempOld = (HBITMAP)SelectObject(hdcTemp, hbmResized); - - // GdiAlphaBlend( - // r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, - // hdcTemp, 0, 0, newWidth, newHeight, bf); - - // SelectObject(hdcTemp, hbmTempOld); - // DeleteObject(hbmResized); - // DeleteDC(hdcTemp); - - // /*AVATARDRAWREQUEST avdrq = {0}; - // avdrq.cbSize = sizeof(avdrq); - // avdrq.hTargetDC = dis->hDC; - // avdrq.dwFlags |= AVDRQ_PROTOPICT; - // avdrq.szProto = g_selectedProto; - // GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw); - // CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq);*/ - // } - // return TRUE; - // } - //case WM_PAINT: // { + // /*FI_INTERFACE *fei = 0; + + // INT_PTR result = CALLSERVICE_NOTFOUND; + // if (ServiceExists(MS_IMG_GETINTERFACE)) + // result = CallService(MS_IMG_GETINTERFACE, FI_IF_VERSION, (LPARAM)&fei); + + // if (fei == NULL || result != S_OK) { + // MessageBox(0, TranslateT("Fatal error, image services not found. Avatar services will be disabled."), TranslateT("Avatar Service"), MB_OK); + // return 0; + // }*/ + // PAINTSTRUCT ps; - // HDC hdc = BeginPaint(hwnd, &ps); - // //260x40 - // Image image(L"Image.png"); - // // Draw the original source image. - // Graphics graphics(hdc); - // graphics.DrawImage(&image, 10, 10); + // HDC hDC = BeginPaint(hwnd, &ps); + + // //FreeImage_Initialise(); + // + // /*FIMEMORY *stream = FreeImage_OpenMemory(captcha->data, captcha->size); + // FIBITMAP *dib = FreeImage_LoadFromMemory(FIF_PNG, stream, PNG_DEFAULT); + // FreeImage_CloseMemory(stream); + + // SetStretchBltMode(hDC, COLORONCOLOR); + // StretchDIBits( + // hDC, + // 0, 0, + // 206, 40, + // 0, 0, + // FreeImage_GetWidth(dib), FreeImage_GetHeight(dib), + // FreeImage_GetBits(dib), + // FreeImage_GetInfo(dib), + // DIB_RGB_COLORS, SRCCOPY); + + // FreeImage_Unload(dib);*/ + + // //FreeImage_DeInitialise(); + // EndPaint(hwnd, &ps); // } // return 0; diff --git a/protocols/Steam/src/steam_messages.cpp b/protocols/Steam/src/steam_messages.cpp new file mode 100644 index 0000000000..20496bc039 --- /dev/null +++ b/protocols/Steam/src/steam_messages.cpp @@ -0,0 +1,47 @@ +#include "common.h" + +void CSteamProto::SendMessageThread(void *arg) +{ + SendMessageParam *param = (SendMessageParam*)arg; + + ptrA token(getStringA("TokenSecret")); + ptrA sessionId(getStringA("SessionID")); + ptrA steamId(getStringA(param->hContact, "SteamID")); + + SteamWebApi::MessageApi::SendResult sendResult; + SteamWebApi::MessageApi::SendMessage(m_hNetlibUser, token, sessionId, steamId, param->text, &sendResult); + + ProtoBroadcastAck( + param->hContact, + ACKTYPE_MESSAGE, + sendResult.IsSuccess() ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, + param->hMessage, 0); + + if (sendResult.IsSuccess()) + { + DBEVENTINFO dbei = { sizeof(dbei) }; + dbei.szModule = this->m_szModuleName; + dbei.timestamp = sendResult.GetTimestamp(); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = strlen(param->text); + dbei.pBlob = (BYTE*)param->text; + dbei.flags = DBEF_UTF | DBEF_SENT; + + db_event_add(param->hContact, &dbei); + } + + //mir_free((void*)param->text); + mir_free(param); +} + +void CSteamProto::SendTypingThread(void *arg) +{ + MCONTACT hContact = (MCONTACT)arg; + + ptrA token(getStringA("TokenSecret")); + ptrA sessionId(getStringA("SessionID")); + ptrA steamId(getStringA(hContact, "SteamID")); + + SteamWebApi::MessageApi::SendResult sendResult; + SteamWebApi::MessageApi::SendTyping(m_hNetlibUser, token, sessionId, steamId, &sendResult); +} \ No newline at end of file diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index 97a11c8d62..7b5b808339 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -1,7 +1,8 @@ #include "common.h" CSteamProto::CSteamProto(const char* protoName, const TCHAR* userName) : - PROTO(protoName, userName) + PROTO(protoName, userName), + hMessageProcess(1) { CreateProtoService(PS_CREATEACCMGRUI, &CSteamProto::OnAccountManagerInit); @@ -133,7 +134,15 @@ int __cdecl CSteamProto::RecvFile(MCONTACT hContact, PROTORECVFILET* pre) int __cdecl CSteamProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre) { - return 0; + 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); } int __cdecl CSteamProto::RecvUrl(MCONTACT hContact, PROTORECVEVENT *) { return 0; } @@ -150,7 +159,16 @@ HANDLE __cdecl CSteamProto::SendFile(MCONTACT hContact, const TCHAR *szDescripti int __cdecl CSteamProto::SendMsg(MCONTACT hContact, int flags, const char *msg) { - return 0; + UINT hMessage = InterlockedIncrement(&hMessageProcess); + + SendMessageParam *param = (SendMessageParam*)mir_calloc(sizeof(SendMessageParam)); + param->hContact = hContact; + param->text = mir_utf8encode(msg); + param->hMessage = (HANDLE)hMessage; + + ForkThread(&CSteamProto::SendMessageThread, param); + + return hMessage; } int __cdecl CSteamProto::SendUrl(MCONTACT hContact, int flags, const char *url) { return 0; } @@ -168,7 +186,6 @@ int CSteamProto::SetStatus(int new_status) if (new_status == ID_STATUS_OFFLINE) { m_bTerminated = true; - ForkThread(&CSteamProto::LogOutThread, NULL); m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; @@ -176,8 +193,8 @@ int CSteamProto::SetStatus(int new_status) if (!Miranda_Terminated()) { - /*this->SetAllContactStatus(ID_STATUS_OFFLINE); - this->CloseAllChatSessions();*/ + SetAllContactsStatus(ID_STATUS_OFFLINE); + //this->CloseAllChatSessions(); } return 0; @@ -191,11 +208,11 @@ int CSteamProto::SetStatus(int new_status) } else { - /*if (IsOnline()) + if (IsOnline()) { - SetServerStatus(new_status); + ForkThread(&CSteamProto::SetServerStatusThread, &new_status); return 0; - }*/ + } ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 853654fd37..e3cc2ea3d2 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -14,6 +14,13 @@ struct CaptchaParam char text[10]; }; +struct SendMessageParam +{ + MCONTACT hContact; + HANDLE hMessage; + const char *text; +}; + class CSteamProto : public PROTO { public: @@ -75,6 +82,7 @@ public: protected: bool m_bTerminated; HANDLE m_hPollingThread; + ULONG hMessageProcess; CRITICAL_SECTION contact_search_lock; // instances @@ -86,15 +94,26 @@ protected: void __cdecl PollingThread(void*); // account + static WORD SteamToMirandaStatus(int state); + static int MirandaToSteamState(int status); + bool IsOnline(); void Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResult); void __cdecl LogInThread(void*); void __cdecl LogOutThread(void*); + void __cdecl SetServerStatusThread(void*); // contacts + void SetContactStatus(MCONTACT hContact, WORD status); + void SetAllContactsStatus(WORD status); + MCONTACT FindContact(const char *steamId); MCONTACT AddContact(const SteamWebApi::FriendApi::Friend &contact); + // messages + void __cdecl SendMessageThread(void*); + void __cdecl SendTypingThread(void*); + //events int OnModulesLoaded(WPARAM, LPARAM); int OnPreShutdown(WPARAM, LPARAM); diff --git a/protocols/Steam/src/steam_thread.cpp b/protocols/Steam/src/steam_thread.cpp index d1c6d8a3c0..4bb62c23d7 100644 --- a/protocols/Steam/src/steam_thread.cpp +++ b/protocols/Steam/src/steam_thread.cpp @@ -1,37 +1,24 @@ #include "common.h" -int SteamToMirandaStatus(int state) -{ - switch (state) - { - case 0: //Offline - return ID_STATUS_OFFLINE; - case 2: //Busy - return ID_STATUS_DND; - case 3: //Away - return ID_STATUS_AWAY; - /*case 4: //Snoozing - prim = PURPLE_STATUS_EXTENDED_AWAY; - break; - case 5: //Looking to trade - return "trade"; - case 6: //Looking to play - return "play";*/ - //case 1: //Online - default: - return ID_STATUS_ONLINE; - } -} - - -int CSteamProto::PollStatus(const char *sessionId, const char *steamId, UINT32 messageId) +int CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 messageId) { SteamWebApi::PollApi::PollResult pollResult; - SteamWebApi::PollApi::PollStatus(m_hNetlibUser, sessionId, steamId, messageId, &pollResult); + SteamWebApi::PollApi::PollStatus(m_hNetlibUser, token, sessionId, messageId, &pollResult); if (!pollResult.IsSuccess()) return 0; + if (pollResult.IsNeedRelogin()) + { + SteamWebApi::LoginApi::LoginResult loginResult; + SteamWebApi::LoginApi::Logon(m_hNetlibUser, token, &loginResult); + + if (!loginResult.IsSuccess()) + return 0; + + return messageId; + } + for (int i = 0; i < pollResult.GetItemCount(); i++) { switch (pollResult[i]->GetType()) @@ -41,14 +28,73 @@ int CSteamProto::PollStatus(const char *sessionId, const char *steamId, UINT32 m case SteamWebApi::PollApi::POOL_TYPE::MESSAGE: { - const wchar_t *text = ((SteamWebApi::PollApi::Message*)pollResult[i])->GetText(); + SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)pollResult[i]; + + MCONTACT hContact = FindContact(message->GetSteamId()); + if (hContact) + { + const wchar_t *text = message->GetText(); + + PROTORECVEVENT recv = { 0 }; + recv.flags = PREF_UTF; + recv.timestamp = message->GetTimestamp(); + recv.szMessage = mir_utf8encodeW(text); + + ProtoChainRecvMsg(hContact, &recv); + } + } + break; + + case SteamWebApi::PollApi::POOL_TYPE::MYMESSAGE: + { + SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)pollResult[i]; + + MCONTACT hContact = FindContact(message->GetSteamId()); + if (hContact) + { + 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); + } } break; case SteamWebApi::PollApi::POOL_TYPE::STATE: { - int status = ((SteamWebApi::PollApi::State*)pollResult[i])->GetStatus(); - const wchar_t *nickname = ((SteamWebApi::PollApi::State*)pollResult[i])->GetNickname(); + SteamWebApi::PollApi::State *state = (SteamWebApi::PollApi::State*)pollResult[i]; + + WORD status = CSteamProto::SteamToMirandaStatus(state->GetStatus()); + const char *cSteamId = state->GetSteamId(); + const wchar_t *nickname = state->GetNickname(); + + ptrA steamId(getStringA("SteamID")); + if (!lstrcmpA(steamId, cSteamId)) + { + const wchar_t *oldNickname = getWStringA("Nick"); + if (lstrcmp(oldNickname, nickname)) + setWString("Nick", nickname); + SetStatus(status); + + } + else + { + MCONTACT hContact = FindContact(cSteamId); + if (hContact) + { + const wchar_t *oldNickname = getWStringA(hContact, "Nick"); + if (lstrcmp(oldNickname, nickname)) + setWString(hContact, "Nick", nickname); + SetContactStatus(hContact, status); + } + } } break; } -- cgit v1.2.3