diff options
author | George Hazan <ghazan@miranda.im> | 2018-12-24 23:18:05 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-12-24 23:18:05 +0300 |
commit | 3a83739020479978041031e566b5269fbef5de9f (patch) | |
tree | f945a1dabe2445eb5b9a5c715f708f460f176c85 | |
parent | 6e439e6cab64aaefc5220facac6df88cccef6cf7 (diff) |
Icq10:
- now we can send messages & sort dups out;
- code reorganizing
-rw-r--r-- | protocols/Icq10/src/http.cpp | 18 | ||||
-rw-r--r-- | protocols/Icq10/src/http.h | 2 | ||||
-rw-r--r-- | protocols/Icq10/src/proto.cpp | 22 | ||||
-rw-r--r-- | protocols/Icq10/src/proto.h | 20 | ||||
-rw-r--r-- | protocols/Icq10/src/server.cpp | 43 |
5 files changed, 84 insertions, 21 deletions
diff --git a/protocols/Icq10/src/http.cpp b/protocols/Icq10/src/http.cpp index 15835d7052..c7a183fa3c 100644 --- a/protocols/Icq10/src/http.cpp +++ b/protocols/Icq10/src/http.cpp @@ -44,7 +44,7 @@ void __cdecl CIcqProto::ServerThread(void*) m_szSessionKey = getMStringA("SessionKey"); if (m_szAToken.IsEmpty() || m_szSessionKey.IsEmpty()) { auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "https://api.login.icq.net/auth/clientLogin", &CIcqProto::OnCheckPassword); - pReq << CHAR_PARAM("clientName", "Miranda NG") << CHAR_PARAM("clientVersion", mirVer) << CHAR_PARAM("devId", "ic1nmMjqg7Yu-0hL") + pReq << CHAR_PARAM("clientName", "Miranda NG") << CHAR_PARAM("clientVersion", mirVer) << CHAR_PARAM("devId", ICQ_APP_ID) << CHAR_PARAM("f", "json") << CHAR_PARAM("tokenType", "longTerm") << INT_PARAM("s", uin) << CHAR_PARAM("pwd", szPassword); pReq->flags |= NLHRF_NODUMPSEND; Push(pReq); @@ -98,7 +98,14 @@ AsyncHttpRequest::AsyncHttpRequest(IcqConnection conn, int iType, const char *sz requestType = iType; m_szUrl = szUrl; m_pFunc = pFunc; - UuidCreate(&m_reqId); + + GUID packetId; + UuidCreate(&packetId); + + RPC_CSTR szId; + UuidToStringA(&packetId, &szId); + strncpy_s(m_reqId, (char*)szId, _TRUNCATE); + RpcStringFreeA(&szId); if (iType == REQUEST_POST) { AddHeader("Content-Type", "application/x-www-form-urlencoded"); @@ -129,9 +136,7 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) pReq->nlc = m_ConnPool[pReq->m_conn]; } - RPC_CSTR szId; - UuidToStringA(&pReq->m_reqId, &szId); - debugLogA("Executing request %s:\n%s", (char*)szId, pReq->szUrl); + debugLogA("Executing request %s:\n%s", pReq->m_reqId, pReq->szUrl); NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq); if (reply != nullptr) { @@ -144,7 +149,7 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) Netlib_FreeHttpRequest(reply); } else { - debugLogA("Request %s failed", (char*)szId); + debugLogA("Request %s failed", pReq->m_reqId); if (pReq->m_conn != CONN_NONE) { if (IsStatusConnecting(m_iStatus)) @@ -153,7 +158,6 @@ void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) } } - RpcStringFreeA(&szId); delete pReq; } diff --git a/protocols/Icq10/src/http.h b/protocols/Icq10/src/http.h index 574ed55130..374836ad7c 100644 --- a/protocols/Icq10/src/http.h +++ b/protocols/Icq10/src/http.h @@ -9,7 +9,7 @@ enum IcqConnection struct AsyncHttpRequest : public MTHttpRequest<CIcqProto> { IcqConnection m_conn; - GUID m_reqId; + char m_reqId[50]; AsyncHttpRequest(IcqConnection, int type, const char *szUrl, MTHttpRequestHandler pFunc = nullptr); }; diff --git a/protocols/Icq10/src/proto.cpp b/protocols/Icq10/src/proto.cpp index 2bf99132f6..89a9cd8006 100644 --- a/protocols/Icq10/src/proto.cpp +++ b/protocols/Icq10/src/proto.cpp @@ -36,6 +36,7 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) : PROTO<CIcqProto>(aProtoName, aUserName), m_arHttpQueue(10), + m_arOwnIds(1), m_arCache(20, NumericKeySortT), m_evRequestsQueue(CreateEvent(nullptr, FALSE, FALSE, nullptr)) { @@ -57,8 +58,6 @@ CIcqProto::CIcqProto(const char* aProtoName, const wchar_t* aUserName) : CIcqProto::~CIcqProto() { - m_arCache.destroy(); - m_arHttpQueue.destroy(); ::CloseHandle(m_evRequestsQueue); } @@ -176,7 +175,7 @@ INT_PTR CIcqProto::GetCaps(int type, MCONTACT hContact) PF2_FREECHAT | PF2_INVISIBLE; case PFLAGNUM_4: - nReturn = PF4_SUPPORTIDLE | PF4_IMSENDOFFLINE | PF4_INFOSETTINGSVC | PF4_SUPPORTTYPING | PF4_AVATARS; + nReturn = PF4_SUPPORTIDLE | PF4_IMSENDOFFLINE | PF4_INFOSETTINGSVC | PF4_SUPPORTTYPING | PF4_AVATARS | PF4_SERVERMSGID; break; case PFLAGNUM_5: @@ -260,9 +259,22 @@ HANDLE CIcqProto::SendFile(MCONTACT hContact, const wchar_t* szDescription, wcha //////////////////////////////////////////////////////////////////////////////////////// // PS_SendMessage - sends a message -int CIcqProto::SendMsg(MCONTACT hContact, int, const char* pszSrc) +int CIcqProto::SendMsg(MCONTACT hContact, int, const char *pszSrc) { - return NULL; + DWORD dwUin = getDword(hContact, "UIN"); + if (dwUin == 0) + return 0; + + int id = InterlockedIncrement(&m_msgId); + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/im/sendIM", &CIcqProto::OnSendMessage); + pReq->pUserInfo = new IcqOwnMessage(hContact, id, pReq->m_reqId); + + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("aimsid", m_aimsid) << CHAR_PARAM("f", "json") << CHAR_PARAM("k", ICQ_APP_ID) + << CHAR_PARAM("mentions", "") << CHAR_PARAM("message", pszSrc) << CHAR_PARAM("nonce", pReq->m_reqId) << CHAR_PARAM("offlineIM", "true") + << INT_PARAM("t", dwUin) << INT_PARAM("ts", time(0)); + + Push(pReq); + return id; } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/protocols/Icq10/src/proto.h b/protocols/Icq10/src/proto.h index 3239d4b7a1..8bf9cbfb91 100644 --- a/protocols/Icq10/src/proto.h +++ b/protocols/Icq10/src/proto.h @@ -33,6 +33,9 @@ #include "m_system.h" #include "m_protoint.h" +#define ICQ_API_SERVER "https://api.icq.net" +#define ICQ_APP_ID "ic1nmMjqg7Yu-0hL" + struct IcqCacheItem { IcqCacheItem(DWORD _uin, MCONTACT _contact) : @@ -45,6 +48,19 @@ struct IcqCacheItem bool m_bInList = false; }; +struct IcqOwnMessage +{ + IcqOwnMessage(MCONTACT _hContact, int _msgid, const char *guid) + : m_hContact(_hContact), m_msgid(_msgid) + { + strncpy_s(m_guid, guid, _TRUNCATE); + } + + MCONTACT m_hContact; + int m_msgid; + char m_guid[50]; +}; + class CIcqProto : public PROTO<CIcqProto> { bool m_bOnline = false, m_bTerminated = false; @@ -58,6 +74,7 @@ class CIcqProto : public PROTO<CIcqProto> void OnCheckPassword(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnFetchEvents(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnSendMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnStartSession(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void ProcessBuddyList(const JSONNode&); @@ -72,6 +89,9 @@ class CIcqProto : public PROTO<CIcqProto> CMStringA m_szAToken; CMStringA m_fetchBaseURL; CMStringA m_aimsid; + LONG m_msgId = 1; + + OBJLIST<IcqOwnMessage> m_arOwnIds; ////////////////////////////////////////////////////////////////////////////////////// // http queue diff --git a/protocols/Icq10/src/server.cpp b/protocols/Icq10/src/server.cpp index 3743e983a1..e8cf0b0d48 100644 --- a/protocols/Icq10/src/server.cpp +++ b/protocols/Icq10/src/server.cpp @@ -95,16 +95,13 @@ void CIcqProto::StartSession() int ts = time(0); CMStringA nonce(FORMAT, "%d-2", ts); - auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "https://api.icq.net/aim/startSession", &CIcqProto::OnStartSession); - - RPC_CSTR szId; - UuidToStringA(&pReq->m_reqId, &szId); + auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, ICQ_API_SERVER "/aim/startSession", &CIcqProto::OnStartSession); pReq << CHAR_PARAM("a", m_szAToken) << INT_PARAM("activeTimeout", 180) << CHAR_PARAM("assertCaps", CAPS) << INT_PARAM("buildNumber", __BUILD_NUM) << CHAR_PARAM("deviceId", szDeviceId) << CHAR_PARAM("events", EVENTS) << CHAR_PARAM("f", "json") << CHAR_PARAM("imf", "plain") << CHAR_PARAM("inactiveView", "offline") << CHAR_PARAM("includePresenceFields", FIELDS) << CHAR_PARAM("invisible", "false") - << CHAR_PARAM("k", "ic1nmMjqg7Yu-0hL") << INT_PARAM("mobile", 0) << CHAR_PARAM("nonce", nonce) << CHAR_PARAM("r", (char*)szId) + << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("mobile", 0) << CHAR_PARAM("nonce", nonce) << CHAR_PARAM("r", pReq->m_reqId) << INT_PARAM("rawMsg", 0) << INT_PARAM("sessionTimeout", 7776000) << INT_PARAM("ts", ts) << CHAR_PARAM("view", "online"); CMStringA hashData(FORMAT, "POST&%s&%s", ptrA(mir_urlEncode(pReq->m_szUrl)), ptrA(mir_urlEncode(pReq->m_szParam))); @@ -114,7 +111,6 @@ void CIcqProto::StartSession() pReq << CHAR_PARAM("sig_sha256", ptrA(mir_base64_encode(hashOut, sizeof(hashOut)))); Push(pReq); - RpcStringFreeA(&szId); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -206,6 +202,23 @@ void CIcqProto::OnReceiveAvatar(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pRe else ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, HANDLE(&ai), 0); } +void CIcqProto::OnSendMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +{ + IcqOwnMessage *ownMsg = (IcqOwnMessage*)pReq->pUserInfo; + + JsonReply root(pReply); + if (root.error() != 200) { + ProtoBroadcastAck(ownMsg->m_hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)ownMsg->m_msgid, 0); + delete ownMsg; + return; + } + + JSONNode &data = root.data(); + CMStringA msgId(data["msgId"].as_mstring()); + strncpy_s(ownMsg->m_guid, msgId, _TRUNCATE); + m_arOwnIds.insert(ownMsg); +} + ///////////////////////////////////////////////////////////////////////////////////////// void CIcqProto::ProcessBuddyList(const JSONNode &ev) @@ -298,8 +311,22 @@ void CIcqProto::ProcessHistData(const JSONNode &ev) if (type != "text") continue; + // ignore duplicates MEVENT hDbEvent = db_event_getById(m_szModuleName, msgId); - if (hDbEvent == 0) { + if (hDbEvent != 0) + continue; + + // skip own messages, just set the server msgid + bool bSkipped = false; + CMStringA reqId(it["reqId"].as_mstring()); + for (auto &ownMsg : m_arOwnIds) + if (!mir_strcmp(reqId, ownMsg->m_guid)) { + bSkipped = true; + ProtoBroadcastAck(ownMsg->m_hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)ownMsg->m_msgid, (LPARAM)msgId.c_str()); + break; + } + + if (!bSkipped) { bool bIsOutgoing = it["outgoing"].as_bool(); ptrA szUtf(mir_utf8encodeW(it["text"].as_mstring())); @@ -386,4 +413,4 @@ void __cdecl CIcqProto::PollThread(void*) debugLogA("Polling thread ended"); m_hPollThread = nullptr; -}
\ No newline at end of file +} |