diff options
-rw-r--r-- | protocols/Icq10/src/proto.cpp | 5 | ||||
-rw-r--r-- | protocols/Icq10/src/proto.h | 10 | ||||
-rw-r--r-- | protocols/Icq10/src/server.cpp | 106 | ||||
-rw-r--r-- | protocols/Icq10/src/utils.cpp | 72 |
4 files changed, 152 insertions, 41 deletions
diff --git a/protocols/Icq10/src/proto.cpp b/protocols/Icq10/src/proto.cpp index 8e46820d6f..95ac9478da 100644 --- a/protocols/Icq10/src/proto.cpp +++ b/protocols/Icq10/src/proto.cpp @@ -39,6 +39,11 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) : m_arCache(20, NumericKeySortT), m_evRequestsQueue(CreateEvent(nullptr, FALSE, FALSE, nullptr)) { + CreateProtoService(PS_GETAVATARINFO, &CIcqProto::GetAvatarInfo); + CreateProtoService(PS_GETMYAVATAR, &CIcqProto::GetAvatar); + CreateProtoService(PS_GETAVATARCAPS, &CIcqProto::GetAvatarCaps); + CreateProtoService(PS_SETMYAVATAR, &CIcqProto::SetAvatar); + CMStringW descr(FORMAT, TranslateT("%s server connection"), m_tszUserName); NETLIBUSER nlu = {}; diff --git a/protocols/Icq10/src/proto.h b/protocols/Icq10/src/proto.h index a3a354feb3..41b816067b 100644 --- a/protocols/Icq10/src/proto.h +++ b/protocols/Icq10/src/proto.h @@ -59,7 +59,9 @@ class CIcqProto : public PROTO<CIcqProto> void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnStartSession(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void ProcessBuddyList(const JSONNode&); void ProcessEvent(const JSONNode&); + void ProcessMyInfo(const JSONNode&); HNETLIBCONN m_ConnPool[CONN_LAST]; CMStringA m_szSessionKey; @@ -95,6 +97,14 @@ class CIcqProto : public PROTO<CIcqProto> void __cdecl ServerThread(void*); ////////////////////////////////////////////////////////////////////////////////////// + // services + + INT_PTR __cdecl GetAvatar(WPARAM, LPARAM); + INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM); + INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM); + INT_PTR __cdecl SetAvatar(WPARAM, LPARAM); + + ////////////////////////////////////////////////////////////////////////////////////// // PROTO_INTERFACE MCONTACT AddToList( int flags, PROTOSEARCHRESULT *psr) override; diff --git a/protocols/Icq10/src/server.cpp b/protocols/Icq10/src/server.cpp index b95ab64b14..bde7ef3319 100644 --- a/protocols/Icq10/src/server.cpp +++ b/protocols/Icq10/src/server.cpp @@ -209,60 +209,84 @@ void CIcqProto::OnReceiveAvatar(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pRe ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::ProcessEvent(const JSONNode &ev) +void CIcqProto::ProcessBuddyList(const JSONNode &ev) { - CMStringW szType = ev["type"].as_mstring(); - if (szType == L"buddylist") { - for (auto &it : ev["eventData"]["groups"]) { - CMStringW szGroup = it["name"].as_mstring(); - Clist_GroupCreate(0, szGroup); - - for (auto &buddy : it["buddies"]) { - DWORD dwUin = _wtol(buddy["aimId"].as_mstring()); - MCONTACT hContact = FindContactByUIN(dwUin); - if (hContact == 0) { - hContact = db_add_contact(); - Proto_AddToContact(hContact, m_szModuleName); - setDword(hContact, "UIN", dwUin); - { - mir_cslock l(m_csCache); - m_arCache.insert(new IcqCacheItem(dwUin, hContact)); - } + for (auto &it : ev["groups"]) { + CMStringW szGroup = it["name"].as_mstring(); + Clist_GroupCreate(0, szGroup); + + for (auto &buddy : it["buddies"]) { + DWORD dwUin = _wtol(buddy["aimId"].as_mstring()); + MCONTACT hContact = FindContactByUIN(dwUin); + if (hContact == 0) { + hContact = db_add_contact(); + Proto_AddToContact(hContact, m_szModuleName); + setDword(hContact, "UIN", dwUin); + { + mir_cslock l(m_csCache); + m_arCache.insert(new IcqCacheItem(dwUin, hContact)); } + } - CMStringW wszNick(buddy["friendly"].as_mstring()); - if (!wszNick.IsEmpty()) - setWString(hContact, "Nick", wszNick); - - setDword(hContact, "Status", StatusFromString(buddy["state"].as_mstring())); + CMStringW wszNick(buddy["friendly"].as_mstring()); + if (!wszNick.IsEmpty()) + setWString(hContact, "Nick", wszNick); - int lastLogin = buddy["lastseen"].as_int(); - if (lastLogin) - setDword(hContact, "LoginTS", lastLogin); + setDword(hContact, "Status", StatusFromString(buddy["state"].as_mstring())); - CMStringW wszStatus(buddy["statusMsg"].as_mstring()); - if (wszStatus.IsEmpty()) - db_unset(hContact, "CList", "StatusMsg"); - else - db_set_ws(hContact, "CList", "StatusMsg", wszStatus); + int lastLogin = buddy["lastseen"].as_int(); + if (lastLogin) + setDword(hContact, "LoginTS", lastLogin); - CMStringW wszIconId(buddy["iconId"].as_mstring()); - CMStringW oldIconID(getMStringW(hContact, "IconId")); - if (wszIconId != oldIconID) { - setWString(hContact, "IconId", wszIconId); + CMStringW wszStatus(buddy["statusMsg"].as_mstring()); + if (wszStatus.IsEmpty()) + db_unset(hContact, "CList", "StatusMsg"); + else + db_set_ws(hContact, "CList", "StatusMsg", wszStatus); - CMStringA szUrl(buddy["buddyIcon"].as_mstring()); - auto *p = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, szUrl, &CIcqProto::OnReceiveAvatar); - p->pUserInfo = (void*)hContact; - Push(p); - } + CMStringW wszIconId(buddy["iconId"].as_mstring()); + CMStringW oldIconID(getMStringW(hContact, "IconId")); + if (wszIconId != oldIconID) { + setWString(hContact, "IconId", wszIconId); - db_set_ws(hContact, "CList", "Group", szGroup); + CMStringA szUrl(buddy["buddyIcon"].as_mstring()); + auto *p = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, szUrl, &CIcqProto::OnReceiveAvatar); + p->pUserInfo = (void*)hContact; + Push(p); } + + db_set_ws(hContact, "CList", "Group", szGroup); } } } +void CIcqProto::ProcessEvent(const JSONNode &ev) +{ + const JSONNode &pData = ev["eventData"]; + CMStringW szType = ev["type"].as_mstring(); + if (szType == L"buddylist") + ProcessBuddyList(pData); + else if (szType == L"myInfo") + ProcessMyInfo(pData); + +} + +void CIcqProto::ProcessMyInfo(const JSONNode &ev) +{ + CMStringW wszNick(ev["friendly"].as_mstring()); + if (!wszNick.IsEmpty()) + setWString("Nick", wszNick); + + CMStringW wszIconId(ev["iconId"].as_mstring()); + CMStringW oldIconID(getMStringW("IconId")); + if (wszIconId != oldIconID) { + setWString("IconId", wszIconId); + + CMStringA szUrl(ev["buddyIcon"].as_mstring()); + Push(new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, szUrl, &CIcqProto::OnReceiveAvatar)); + } +} + void CIcqProto::OnFetchEvents(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) { JsonReply root(pReply); diff --git a/protocols/Icq10/src/utils.cpp b/protocols/Icq10/src/utils.cpp index 2dec6c800c..0ed21af36c 100644 --- a/protocols/Icq10/src/utils.cpp +++ b/protocols/Icq10/src/utils.cpp @@ -34,6 +34,9 @@ MCONTACT CIcqProto::FindContactByUIN(DWORD dwUin) return (p) ? p->m_hContact : 0; } +///////////////////////////////////////////////////////////////////////////////////////// +// Avatars + void CIcqProto::GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cbLen) { int tPathLen = mir_snwprintf(pszDest, cbLen, L"%s\\%S", VARSW(L"%miranda_avatarcache%"), m_szModuleName); @@ -49,6 +52,75 @@ void CIcqProto::GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cb mir_snwprintf(pszDest + tPathLen, MAX_PATH - tPathLen, L"%s%s", wszFileName.c_str(), szFileType); } +INT_PTR __cdecl CIcqProto::GetAvatar(WPARAM wParam, LPARAM lParam) +{ + wchar_t *buf = (wchar_t*)wParam; + int size = (int)lParam; + if (buf == nullptr || size <= 0) + return -1; + + GetAvatarFileName(0, buf, size); + return 0; +} + +INT_PTR __cdecl CIcqProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) { + case AF_MAXSIZE: + ((POINT*)lParam)->x = -1; + ((POINT*)lParam)->y = -1; + return 0; + + case AF_MAXFILESIZE: + return 0; + + case AF_PROPORTION: + return PIP_NONE; + + case AF_FORMATSUPPORTED: // nobody + return 1; + + case AF_DELAYAFTERFAIL: + return 10 * 60 * 1000; + + case AF_DONTNEEDDELAYS: // We need delays because of larger friend lists + return 0; + + case AF_ENABLED: + case AF_FETCHIFPROTONOTVISIBLE: + case AF_FETCHIFCONTACTOFFLINE: + return 1; + } + return 0; +} + +INT_PTR __cdecl CIcqProto::GetAvatarInfo(WPARAM, LPARAM lParam) +{ + PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam; + + ptrW szIconId(getWStringA(pai->hContact, "IconId")); + if (szIconId == nullptr) { + debugLogA("No avatar"); + return GAIR_NOAVATAR; + } + + GetAvatarFileName(pai->hContact, pai->filename, _countof(pai->filename)); + pai->format = getByte(pai->hContact, "AvatarType", 0); + + if (::_waccess(pai->filename, 0) == 0) + return GAIR_SUCCESS; + + debugLogA("No avatar"); + return GAIR_NOAVATAR; +} + +INT_PTR __cdecl CIcqProto::SetAvatar(WPARAM, LPARAM) +{ + return 1; // TODO +} + +///////////////////////////////////////////////////////////////////////////////////////// + int StatusFromString(const CMStringW &wszStatus) { if (wszStatus == "online") |