diff options
-rw-r--r-- | protocols/VKontakte/src/misc.cpp | 21 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk.h | 5 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.cpp | 7 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 13 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_queue.cpp | 29 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_thread.cpp | 126 |
6 files changed, 176 insertions, 25 deletions
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index a59a4a16b4..6470a303ad 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -38,6 +38,27 @@ void CVkProto::SetAllContactStatuses(int iStatus) }
}
+HANDLE CVkProto::FindUser(LPCSTR pUserid, bool bCreate)
+{
+ for (HANDLE hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ ptrA dbUserid(getStringA(hContact, "ID"));
+ if (dbUserid == NULL)
+ continue;
+
+ if ( !strcmp(dbUserid, pUserid))
+ return hContact;
+ }
+
+ if (!bCreate)
+ return NULL;
+
+ HANDLE hNewContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hNewContact, (LPARAM)m_szModuleName);
+ setString(hNewContact, "ID", pUserid);
+ db_set_ts(hNewContact, "CList", "Group", m_defaultGroup);
+ return hNewContact;
+}
+
int CVkProto::SetServerStatus(int iStatus)
{
return 0;
diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h index d6a9a0f9d0..8b979cd8cf 100644 --- a/protocols/VKontakte/src/vk.h +++ b/protocols/VKontakte/src/vk.h @@ -20,7 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define VK_API_URL "api.vk.com"
#define VK_REDIRECT_URL "http://" VK_API_URL "/blank.html"
-typedef NETLIBHTTPHEADER HttpParam;
+struct HttpParam
+{
+ LPCSTR szName, szValue;
+};
extern HINSTANCE hInst;
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index d2e213e998..a93c84d647 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -38,6 +38,13 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) : mir_sntprintf(descr, SIZEOF(descr), _T("%%miranda_avatarcache%%\\%s"), m_tszUserName);
hAvatarFolder = FoldersRegisterCustomPathT(LPGEN("Avatars"), m_szModuleName, descr, m_tszUserName);
+ m_defaultGroup = getTStringA("ProtoGroup");
+ if (m_defaultGroup == NULL)
+ m_defaultGroup = mir_tstrdup( TranslateT("VKontakte"));
+ Clist_CreateGroup(NULL, m_defaultGroup);
+
+ db_set_resident(m_szModuleName, "Status");
+
// Set all contacts offline -- in case we crashed
SetAllContactStatuses(ID_STATUS_OFFLINE);
}
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index c8ee1a21cb..71a9eecf1c 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -89,6 +89,12 @@ struct CVkProto : public PROTO<CVkProto> TCHAR* GetUserStoredPassword(void);
+ void RetrieveUserInfo(LPCSTR szUserId);
+ void OnReceiveUserInfo(NETLIBHTTPREQUEST*);
+
+ void RetrieveFriends();
+ void OnReceiveFriends(NETLIBHTTPREQUEST*);
+
__forceinline bool IsOnline() const { return m_bOnline; }
private:
@@ -113,7 +119,7 @@ private: void InitQueue();
void UninitQueue();
void ExecuteRequest(AsyncHttpRequest*);
- bool PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams = 0, NETLIBHTTPHEADER *pParams = 0, int iTimeout = 10000);
+ bool PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams = 0, HttpParam *pParams = 0, int iTimeout = 10000);
bool PushAsyncHttpRequest(AsyncHttpRequest*, int iTimeout = 10000);
int SetupConnection(void);
void __cdecl WorkerThread(void*);
@@ -125,6 +131,8 @@ private: void OnLoggedOut();
void ShutdownSession();
+ HANDLE FindUser(LPCSTR userid, bool bCreate = false);
+
void SetAllContactStatuses(int status);
int SetServerStatus(int);
@@ -132,5 +140,6 @@ private: HANDLE m_hNetlibUser, m_hNetlibConn;
HANDLE hAvatarFolder;
- ptrA m_szAccessToken;
+ ptrA m_szAccessToken, m_myUserId;
+ ptrT m_defaultGroup;
};
diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index be8c8868eb..47a146ffa9 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -60,7 +60,7 @@ void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) /////////////////////////////////////////////////////////////////////////////////////////
-bool CVkProto::PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams, NETLIBHTTPHEADER *pParams, int iTimeout)
+bool CVkProto::PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams, HttpParam *pParams, int iTimeout)
{
if ( !SetupConnection())
return false;
@@ -124,27 +124,22 @@ void CVkProto::WorkerThread(void*) }
while(true) {
- DWORD dwRet = WaitForSingleObject(m_evRequestsQueue, 1000);
- if (dwRet == WAIT_TIMEOUT) {
- // check expiration;
- continue;
- }
-
- if (dwRet != WAIT_OBJECT_0)
- continue;
-
+ WaitForSingleObject(m_evRequestsQueue, 1000);
if (m_bTerminated)
break;
AsyncHttpRequest *pReq;
- { mir_cslock lck(m_csRequestsQueue);
- if (m_arRequestsQueue.getCount() == 0)
- continue;
-
- pReq = m_arRequestsQueue[0];
- m_arRequestsQueue.remove(0);
+ while(true) {
+ {
+ mir_cslock lck(m_csRequestsQueue);
+ if (m_arRequestsQueue.getCount() == 0)
+ break;
+
+ pReq = m_arRequestsQueue[0];
+ m_arRequestsQueue.remove(0);
+ }
+ ExecuteRequest(pReq);
}
- ExecuteRequest(pReq);
}
OnLoggedOut();
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 18b10add99..92b0f4ce76 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -45,6 +45,8 @@ void CVkProto::OnLoggedIn() HttpParam param = { "access_token", m_szAccessToken };
PushAsyncHttpRequest(REQUEST_GET, "/method/getUserInfoEx.json", true, &CVkProto::OnReceiveMyInfo, 1, ¶m);
+
+ SetAllContactStatuses(ID_STATUS_OFFLINE);
}
void CVkProto::OnLoggedOut()
@@ -143,12 +145,13 @@ LBL_NoForm: void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply)
{
+ Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveMyInfo %d", reply->resultCode);
if (reply->resultCode != 200) {
ConnectionFailed(LOGINERR_WRONGPASSWORD);
return;
}
- JSONNODE *pRoot = json_parse(reply->pData);
+ JSONROOT pRoot(reply->pData);
if ( !CheckJsonResult(pRoot))
return;
@@ -159,8 +162,11 @@ void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply) for (size_t i = 0; i < json_size(pResponse); i++) {
JSONNODE *it = json_at(pResponse, i);
LPCSTR id = json_name(it);
- if ( !_stricmp(id, "user_id"))
- setTString("ID", ptrT( json_as_string(it)));
+ if ( !_stricmp(id, "user_id")) {
+ ptrT userid( json_as_string(it));
+ m_myUserId = mir_t2a(userid);
+ setTString("ID", userid);
+ }
else if ( !_stricmp(id, "user_name"))
setTString("Nick", ptrT( json_as_string(it)));
else if ( !_stricmp(id, "user_sex"))
@@ -168,13 +174,123 @@ void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply) else if ( !_stricmp(id, "user_bdate")) {
ptrT date( json_as_string(it));
int d, m, y;
- if ( _tscanf(date, _T("%d.%d.%d"), &d, &m, &y) == 3) {
+ if ( _stscanf(date, _T("%d.%d.%d"), &d, &m, &y) == 3) {
setByte("BirthDay", d);
setByte("BirthMonth", m);
- setByte("BirthYear", y);
+ setWord("BirthYear", y);
}
}
else if ( !_stricmp(id, "user_photo"))
setTString("Photo", ptrT( json_as_string(it)));
}
+
+ RetrieveUserInfo(m_myUserId);
+ RetrieveFriends();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CVkProto::RetrieveUserInfo(LPCSTR szUserId)
+{
+ HttpParam params[] = {
+ { "fields", "uid,first_name,last_name,photo,sex,bdate,city,relation" },
+ { "uids", szUserId },
+ { "access_token", m_szAccessToken }
+ };
+ PushAsyncHttpRequest(REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo, SIZEOF(params), params);
+}
+
+void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply)
+{
+ Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveUserInfo %d", reply->resultCode);
+ if (reply->resultCode != 200)
+ return;
+
+ JSONROOT pRoot(reply->pData);
+ if ( !CheckJsonResult(pRoot))
+ return;
+
+ JSONNODE *pResponse = json_get(pRoot, "response");
+ if (pResponse == NULL)
+ return;
+
+ HANDLE hContact;
+ for (size_t i = 0; i < json_size(pResponse); i++) {
+ JSONNODE *it = json_at(pResponse, i);
+ LPCSTR id = json_name(it);
+ if ( !_stricmp(id, "user_id")) {
+ ptrA userid( _T2A( json_as_string(it)));
+ if ( !lstrcmpA(userid, m_myUserId))
+ hContact = NULL;
+ else if ((hContact = FindUser(userid, false)) == NULL)
+ return;
+ }
+ else if ( !_stricmp(id, "user_name"))
+ setTString(hContact, "Nick", ptrT( json_as_string(it)));
+ else if ( !_stricmp(id, "user_sex"))
+ setByte(hContact, "Gender", json_as_int(it) == 2 ? 'M' : 'F');
+ else if ( !_stricmp(id, "user_bdate")) {
+ ptrT date( json_as_string(it));
+ int d, m, y;
+ if ( _stscanf(date, _T("%d.%d.%d"), &d, &m, &y) == 3) {
+ setByte(hContact, "BirthDay", d);
+ setByte(hContact, "BirthMonth", m);
+ setWord(hContact, "BirthYear", y);
+ }
+ }
+ else if ( !_stricmp(id, "user_photo"))
+ setTString(hContact, "Photo", ptrT( json_as_string(it)));
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CVkProto::RetrieveFriends()
+{
+ Netlib_Logf(m_hNetlibUser, "CVkProto::RetrieveFriends");
+
+ HttpParam params[] = {
+ { "fields", "uid,first_name,last_name,photo,contacts" },
+ { "count", "1000" },
+ { "access_token", m_szAccessToken }
+ };
+ PushAsyncHttpRequest(REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends, SIZEOF(params), params);
+}
+
+void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply)
+{
+ Netlib_Logf(m_hNetlibUser, "CVkProto::OnReceiveFriends %d", reply->resultCode);
+ if (reply->resultCode != 200)
+ return;
+
+ JSONROOT pRoot(reply->pData);
+ if ( !CheckJsonResult(pRoot))
+ return;
+
+ JSONNODE *pResponse = json_get(pRoot, "response"), *pInfo;
+ if (pResponse == NULL)
+ return;
+
+ for (int i=0; (pInfo = json_at(pResponse, i)) != NULL; i++) {
+ ptrT szValue( json_as_string( json_get(pInfo, "uid")));
+ if (szValue == NULL)
+ continue;
+
+ HANDLE hContact = FindUser(_T2A(szValue), true);
+ szValue = json_as_string( json_get(pInfo, "first_name"));
+ if (szValue) setTString(hContact, "FirstName", szValue);
+
+ szValue = json_as_string( json_get(pInfo, "last_name"));
+ if (szValue) setTString(hContact, "LastName", szValue);
+
+ szValue = json_as_string( json_get(pInfo, "photo"));
+ if (szValue) setTString(hContact, "AvatarUrl", szValue);
+
+ setWord(hContact, "Status", (json_as_int( json_get(pInfo, "online")) == 0) ? ID_STATUS_OFFLINE : ID_STATUS_ONLINE);
+
+ szValue = json_as_string( json_get(pInfo, "mobile_phone"));
+ if (szValue && *szValue) setTString(hContact, "Phone0", szValue);
+ szValue = json_as_string( json_get(pInfo, "home_phone"));
+ if (szValue && *szValue) setTString(hContact, "Phone1", szValue);
+ }
}
|