diff options
-rw-r--r-- | protocols/VKontakte/src/vk_chats.cpp | 178 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 19 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_thread.cpp | 132 |
3 files changed, 249 insertions, 80 deletions
diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp index bdbe536d1f..d7865e3f00 100644 --- a/protocols/VKontakte/src/vk_chats.cpp +++ b/protocols/VKontakte/src/vk_chats.cpp @@ -17,25 +17,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "stdafx.h"
-void CVkProto::AppendChat(int id, JSONNODE *pDlg)
-{
- CVkChatInfo *c = new CVkChatInfo(id);
+static LPCTSTR sttStatuses[] = { LPGENT("Participants"), LPGENT("Owners") };
- ptrT tszTitle(json_as_string(json_get(pDlg, "title")));
- c->m_tszTitle = mir_tstrdup((tszTitle != NULL) ? tszTitle : _T(""));
+CVkChatInfo* CVkProto::AppendChat(int id, JSONNODE *pDlg)
+{
+ if (id == 0)
+ return NULL;
- CMString ids = ptrT(json_as_string(json_get(pDlg, "chat_active")));
- for (int iStart = 0;;) {
- CMString uid = ids.Tokenize(_T(","), iStart);
- if (iStart == -1)
- break;
+ CVkChatInfo *c = m_chats.find((CVkChatInfo*)&id);
+ if (c != NULL)
+ return c;
- CVkChatUser *cu = new CVkChatUser();
- cu->userid = _ttoi(uid);
- c->m_users.insert(cu);
+ ptrT tszTitle;
+ c = new CVkChatInfo(id);
+ if (pDlg != NULL) {
+ tszTitle = json_as_string(json_get(pDlg, "title"));
+ c->m_tszTitle = mir_tstrdup((tszTitle != NULL) ? tszTitle : _T(""));
}
CMString sid; sid.Format(_T("%S_%d"), m_szModuleName, id);
+ c->m_tszId = mir_tstrdup(sid);
GCSESSION gcw = { sizeof(gcw) };
gcw.iType = GCW_CHATROOM;
@@ -52,8 +53,153 @@ void CVkProto::AppendChat(int id, JSONNODE *pDlg) c->m_hContact = gci.hContact;
m_chats.insert(c);
- GCDEST gcd = { m_szModuleName, sid.GetBuffer(), GC_EVENT_CONTROL };
- GCEVENT gce = { sizeof(GCEVENT), &gcd };
+ GCDEST gcd = { m_szModuleName, sid.GetBuffer(), GC_EVENT_ADDGROUP };
+ GCEVENT gce = { sizeof(gce), &gcd };
+ for (int i = SIZEOF(sttStatuses)-1; i >= 0; i--) {
+ gce.ptszStatus = TranslateTS(sttStatuses[i]);
+ CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
+ }
+
+ gcd.iType = GC_EVENT_CONTROL;
+ gce.ptszStatus = 0;
CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
- // CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
+ CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
+
+ RetrieveChatInfo(c);
+ return c;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CVkProto::RetrieveChatInfo(CVkChatInfo *cc)
+{
+ CMStringA szQuery("return { ");
+
+ // retrieve title if empty
+ if (!lstrlen(cc->m_tszTitle))
+ szQuery.AppendFormat("\"info\": API.messages.getChat({\"chat_id\":%d}),", cc->m_chatid);
+
+ // retrieve users
+ szQuery.AppendFormat("\"users\": API.messages.getChatUsers({\"chat_id\":%d, \"fields\":\"uid,first_name,last_name,photo\"})", cc->m_chatid);
+
+ if (!cc->m_bHistoryRead) {
+ cc->m_bHistoryRead = true;
+ szQuery.AppendFormat(",\"msgs\": API.messages.getHistory({\"chat_id\":%d, \"count\":\"20\", \"rev\":\"0\"})", cc->m_chatid);
+ }
+
+ szQuery.Append("};");
+
+ debugLogA("CVkProto::RetrieveChantInfo(%d)", cc->m_chatid);
+
+ HttpParam params[] = {
+ { "code", szQuery },
+ { "access_token", m_szAccessToken }
+ };
+ AsyncHttpRequest *pReq = PushAsyncHttpRequest(REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveChatInfo, SIZEOF(params), params);
+ pReq->pUserInfo = cc;
+}
+
+void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
+{
+ debugLogA("CVkProto::OnReceiveChatInfo %d", reply->resultCode);
+ if (reply->resultCode != 200)
+ return;
+
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
+ if (pResponse == NULL)
+ return;
+
+ CVkChatInfo *cc = (CVkChatInfo*)pReq->pUserInfo;
+ if (m_chats.indexOf(cc) == -1)
+ return;
+
+ JSONNODE *info = json_get(pResponse, "info");
+ if (info != NULL) {
+ ptrT tszTitle(json_as_string(json_get(info, "title")));
+ cc->m_tszTitle = mir_tstrdup(tszTitle);
+
+ cc->m_admin_id = json_as_int(json_get(info, "admin_id"));
+
+ JSONNODE *userids = json_as_array(json_get(info, "users"));
+ if (userids) {
+ for (int i = 0;; i++) {
+ int uid = json_as_int(json_at(userids, i));
+ if (uid == 0)
+ break;
+
+ CVkChatUser *cu = cc->m_users.find((CVkChatUser*)&uid);
+ if (cu == NULL)
+ cc->m_users.insert(cu = new CVkChatUser(uid));
+ }
+ }
+ }
+
+ JSONNODE *users = json_as_array(json_get(pResponse, "users"));
+ if (users != NULL) {
+ for (int i = 0;; i++) {
+ JSONNODE *pUser = json_at(users, i);
+ if (pUser == NULL)
+ break;
+
+ int uid = json_as_int(json_get(pUser, "uid"));
+ TCHAR tszId[20];
+ _itot(uid, tszId, 10);
+
+ CVkChatUser *cu = cc->m_users.find((CVkChatUser*)&uid);
+ if (cu == NULL)
+ cc->m_users.insert(cu = new CVkChatUser(uid));
+
+ ptrT fName(json_as_string(json_get(pUser, "first_name")));
+ ptrT lName(json_as_string(json_get(pUser, "last_name")));
+ CMString tszNick = CMString(fName).Trim() + _T(" ") + CMString(lName).Trim();
+ cu->m_tszTitle = mir_tstrdup(tszNick);
+
+ cu->m_tszImage = json_as_string(json_get(pUser, "photo"));
+
+ GCDEST gcd = { m_szModuleName, cc->m_tszId, GC_EVENT_JOIN };
+ GCEVENT gce = { sizeof(GCEVENT), &gcd };
+ gce.bIsMe = uid == m_myUserId;
+ gce.ptszUID = tszId;
+ gce.ptszNick = tszNick;
+ gce.ptszStatus = TranslateTS(sttStatuses[uid == cc->m_admin_id]);
+ gce.dwItemData = (INT_PTR)cu;
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
+ }
+ }
+
+ JSONNODE *msgs = json_as_array(json_get(pResponse, "msgs"));
+ if (msgs != NULL) {
+ for (int i = 1;; i++) {
+ JSONNODE *pMsg = json_at(msgs, i);
+ if (pMsg == NULL)
+ break;
+
+ int uid = json_as_int(json_get(pMsg, "from_id"));
+ TCHAR tszId[20];
+ _itot(uid, tszId, 10);
+
+ CVkChatUser *cu = cc->m_users.find((CVkChatUser*)&uid);
+ if (cu == NULL) {
+ cc->m_users.insert(cu = new CVkChatUser(uid));
+ cu->m_tszTitle = mir_tstrdup(TranslateT("Uknown"));
+ }
+
+ int iDate = json_as_int(json_get(pMsg, "date"));
+ ptrT tszBody(json_as_string(json_get(pMsg, "body")));
+
+ JSONNODE *pAttachments = json_get(pMsg, "attachments");
+ if (pAttachments != NULL)
+ tszBody = mir_tstrdup(CMString(tszBody) + GetAttachmentDescr(pAttachments));
+
+ GCDEST gcd = { m_szModuleName, cc->m_tszId, GC_EVENT_MESSAGE };
+ GCEVENT gce = { sizeof(GCEVENT), &gcd };
+ gce.bIsMe = uid == m_myUserId;
+ gce.ptszUID = tszId;
+ gce.time = iDate;
+ gce.ptszNick = cu->m_tszTitle;
+ gce.ptszText = tszBody;
+ CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
+ }
+ }
}
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 32f597d939..1cff543e4f 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -33,19 +33,22 @@ struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject struct CVkChatUser
{
- int userid;
- ptrT tszTitle, tszImage;
+ CVkChatUser(int _id) : m_uid(_id) {}
+
+ int m_uid;
+ ptrT m_tszTitle, m_tszImage;
};
-struct CVkChatInfo
+struct CVkChatInfo : public MZeroedObject
{
CVkChatInfo(int _id) :
m_users(10, NumericKeySortT),
m_chatid(_id)
{}
- int m_chatid;
- ptrT m_tszTitle;
+ int m_chatid, m_admin_id;
+ bool m_bHistoryRead;
+ ptrT m_tszTitle, m_tszId;
HANDLE m_hContact;
OBJLIST<CVkChatUser> m_users;
};
@@ -223,5 +226,9 @@ private: static INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
OBJLIST<CVkChatInfo> m_chats;
- void AppendChat(int id, JSONNODE *pNode);
+ CVkChatInfo* AppendChat(int id, JSONNODE *pNode);
+ void RetrieveChatInfo(CVkChatInfo*);
+ void OnReceiveChatInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
+
+ CMString GetAttachmentDescr(JSONNODE*);
};
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 9d7fc28a48..6df0321fd2 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -452,64 +452,8 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe int isRead = json_as_int(json_get(pMsg, "read_state"));
JSONNODE *pAttachments = json_get(pMsg, "attachments");
- if (pAttachments != NULL) {
- CMString tszBody(ptszBody);
- tszBody.AppendChar('\n');
- tszBody += TranslateT("Attachments:");
- tszBody.AppendChar('\n');
- JSONNODE *pAttach;
- for (int k = 0; (pAttach = json_at(pAttachments, k)) != NULL; k++) {
- tszBody.AppendChar('\t');
- ptrT ptszType(json_as_string(json_get(pAttach, "type")));
- if (!lstrcmp(ptszType, _T("photo"))) {
- JSONNODE *pPhoto = json_get(pAttach, "photo");
- if (pPhoto == NULL) continue;
-
- ptrT ptszLink;
- for (int i = 0; i < SIZEOF(szImageTypes); i++)
- if ((ptszLink = json_as_string(json_get(pPhoto, szImageTypes[i]))) != NULL)
- break;
-
- int iWidth = json_as_int(json_get(pPhoto, "width"));
- int iHeight = json_as_int(json_get(pPhoto, "height"));
- tszBody.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink, iWidth, iHeight);
- }
- else if (!lstrcmp(ptszType, _T("audio"))) {
- JSONNODE *pAudio = json_get(pAttach, "audio");
- if (pAudio == NULL) continue;
-
- int aid = json_as_int(json_get(pAudio, "aid"));
- int ownerID = json_as_int(json_get(pAudio, "owner_id"));
- ptrT ptszArtist(json_as_string(json_get(pAudio, "artist")));
- ptrT ptszTitle(json_as_string(json_get(pAudio, "title")));
- tszBody.AppendFormat(_T("%s: (%s - %s) - http://vk.com/audio%d_%d"),
- TranslateT("Audio"), ptszArtist, ptszTitle, ownerID, aid);
- }
- else if (!lstrcmp(ptszType, _T("video"))) {
- JSONNODE *pVideo = json_get(pAttach, "video");
- if (pVideo == NULL) continue;
-
- ptrT ptszTitle(json_as_string(json_get(pVideo, "title")));
- int vid = json_as_int(json_get(pVideo, "vid"));
- int ownerID = json_as_int(json_get(pVideo, "owner_id"));
- tszBody.AppendFormat(_T("%s: %s - http://vk.com/video%d_%d"),
- TranslateT("Video"), ptszTitle, ownerID, vid);
- }
- else if (!lstrcmp(ptszType, _T("doc"))) {
- JSONNODE *pDoc = json_get(pAttach, "doc");
- if (pDoc == NULL) continue;
-
- ptrT ptszTitle(json_as_string(json_get(pDoc, "title")));
- ptrT ptszUrl(json_as_string(json_get(pDoc, "url")));
- tszBody.AppendFormat(_T("%s: (%s) - %s"),
- TranslateT("Document"), ptszTitle, ptszUrl);
- }
- else tszBody.AppendFormat(TranslateT("Unsupported or unknown attachment type: %s"), ptszType);
-
- tszBody.AppendChar('\n');
- }
- ptszBody = mir_tstrdup(tszBody);
- }
+ if (pAttachments != NULL)
+ ptszBody = mir_tstrdup(CMString(ptszBody) + GetAttachmentDescr(pAttachments));
HANDLE hContact = FindUser(uid, true);
@@ -608,6 +552,13 @@ void CVkProto::PollUpdates(JSONNODE *pUpdates) if ((hContact = FindUser(uid)) != NULL)
CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, 5);
break;
+
+ case VKPOLL_CHAT_CHANGED:
+ int chatid = json_as_int(json_at(pChild, 1));
+ int isSelf = json_as_int(json_at(pChild, 2));
+ if (!isSelf)
+ AppendChat(chatid, NULL);
+ break;
}
}
@@ -667,3 +618,68 @@ void CVkProto::PollingThread(void*) m_pollingConn = NULL;
debugLogA("CVkProto::PollingThread: leaving");
}
+
+CMString CVkProto::GetAttachmentDescr(JSONNODE *pAttachments)
+{
+ CMString res;
+ res.AppendChar('\n');
+ res += TranslateT("Attachments:");
+ res.AppendChar('\n');
+ JSONNODE *pAttach;
+ for (int k = 0; (pAttach = json_at(pAttachments, k)) != NULL; k++) {
+ res.AppendChar('\t');
+ ptrT ptszType(json_as_string(json_get(pAttach, "type")));
+ if (!lstrcmp(ptszType, _T("photo"))) {
+ JSONNODE *pPhoto = json_get(pAttach, "photo");
+ if (pPhoto == NULL) continue;
+
+ ptrT ptszLink;
+ for (int i = 0; i < SIZEOF(szImageTypes); i++) {
+ JSONNODE *n = json_get(pPhoto, szImageTypes[i]);
+ if (n != NULL) {
+ ptszLink = json_as_string(n);
+ break;
+ }
+ }
+
+ int iWidth = json_as_int(json_get(pPhoto, "width"));
+ int iHeight = json_as_int(json_get(pPhoto, "height"));
+ res.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink, iWidth, iHeight);
+ }
+ else if (!lstrcmp(ptszType, _T("audio"))) {
+ JSONNODE *pAudio = json_get(pAttach, "audio");
+ if (pAudio == NULL) continue;
+
+ int aid = json_as_int(json_get(pAudio, "aid"));
+ int ownerID = json_as_int(json_get(pAudio, "owner_id"));
+ ptrT ptszArtist(json_as_string(json_get(pAudio, "artist")));
+ ptrT ptszTitle(json_as_string(json_get(pAudio, "title")));
+ res.AppendFormat(_T("%s: (%s - %s) - http://vk.com/audio%d_%d"),
+ TranslateT("Audio"), ptszArtist, ptszTitle, ownerID, aid);
+ }
+ else if (!lstrcmp(ptszType, _T("video"))) {
+ JSONNODE *pVideo = json_get(pAttach, "video");
+ if (pVideo == NULL) continue;
+
+ ptrT ptszTitle(json_as_string(json_get(pVideo, "title")));
+ int vid = json_as_int(json_get(pVideo, "vid"));
+ int ownerID = json_as_int(json_get(pVideo, "owner_id"));
+ res.AppendFormat(_T("%s: %s - http://vk.com/video%d_%d"),
+ TranslateT("Video"), ptszTitle, ownerID, vid);
+ }
+ else if (!lstrcmp(ptszType, _T("doc"))) {
+ JSONNODE *pDoc = json_get(pAttach, "doc");
+ if (pDoc == NULL) continue;
+
+ ptrT ptszTitle(json_as_string(json_get(pDoc, "title")));
+ ptrT ptszUrl(json_as_string(json_get(pDoc, "url")));
+ res.AppendFormat(_T("%s: (%s) - %s"),
+ TranslateT("Document"), ptszTitle, ptszUrl);
+ }
+ else res.AppendFormat(TranslateT("Unsupported or unknown attachment type: %s"), ptszType);
+
+ res.AppendChar('\n');
+ }
+
+ return res;
+}
|