From 0220c65f60daedd91dc8db724e73094d3d88db99 Mon Sep 17 00:00:00 2001 From: Sergey Bolhovskoy Date: Thu, 18 Dec 2014 04:17:30 +0000 Subject: =?UTF-8?q?VKontakte:=20vk=20feeds=20support=20(notifications)=20?= =?UTF-8?q?=E2=80=93=20part=203=20version=20bump?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.miranda-ng.org/main/trunk@11498 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/VKontakte/res/resource.rc | 2 +- protocols/VKontakte/src/misc.cpp | 41 +++++ protocols/VKontakte/src/version.h | 2 +- protocols/VKontakte/src/vk_feed.cpp | 281 ++++++++++++++++++++++++++++------ protocols/VKontakte/src/vk_proto.h | 30 +++- protocols/VKontakte/src/vk_queue.cpp | 2 +- protocols/VKontakte/src/vk_thread.cpp | 6 +- 7 files changed, 306 insertions(+), 58 deletions(-) (limited to 'protocols/VKontakte') diff --git a/protocols/VKontakte/res/resource.rc b/protocols/VKontakte/res/resource.rc index 290e159da7..8051263fad 100644 --- a/protocols/VKontakte/res/resource.rc +++ b/protocols/VKontakte/res/resource.rc @@ -113,7 +113,7 @@ BEGIN GROUPBOX "News and event notifications",IDC_STATIC,4,8,293,83 CTEXT "WARNING: Causes excessive network traffic!!!",IDC_STATIC,12,19,278,8 CONTROL "Enable news feeds",IDC_NEWS_ENBL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,30,278,10 - CONTROL "Enable event notifications",IDC_NOTIF_ENBL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,12,41,278,10 + CONTROL "Enable event notifications",IDC_NOTIF_ENBL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,41,278,10 CONTROL "BBCode support on news and event notifications",IDC_BBC_NEWS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,52,278,10 LTEXT "Interval for updates (min):",IDC_STATIC,16,67,97,8 diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index eba3462555..05d0b6483b 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -631,3 +631,44 @@ int CVkProto::OnDbSettingChanged(WPARAM hContact, LPARAM lParam) return 0; } + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CVkProto::SpanVKNotificationType(CMString& tszType, VKObjType& vkFeedback, VKObjType& vkParent) +{ + CVkNotification vkNotification[] = { + { _T("follow"), vkNull, vkUsers }, + { _T("friend_accepted"), vkNull, vkUsers }, + { _T("mention"), vkNull, vkPost }, + { _T("mention_comments"), vkPost, vkComment }, + { _T("wall"), vkNull, vkPost }, + { _T("wall_publish"), vkNull, vkPost }, + { _T("comment_post"), vkPost, vkComment }, + { _T("comment_photo"), vkPhoto, vkComment }, + { _T("comment_video"), vkVideo, vkComment }, + { _T("reply_comment"), vkComment, vkComment }, + { _T("reply_comment_photo"), vkComment, vkComment }, + { _T("reply_comment_video"), vkComment, vkComment }, + { _T("reply_topic"), vkTopic, vkComment }, + { _T("like_post"), vkPost, vkUsers }, + { _T("like_comment"), vkComment, vkUsers }, + { _T("like_photo"), vkPhoto, vkUsers }, + { _T("like_video"), vkVideo, vkUsers }, + { _T("like_comment_photo"), vkComment, vkUsers }, + { _T("like_comment_video"), vkComment, vkUsers }, + { _T("like_comment_topic"), vkComment, vkUsers }, + { _T("copy_post"), vkPost, vkCopy }, + { _T("copy_photo"), vkPhoto, vkCopy }, + { _T("copy_video"), vkVideo, vkCopy }, + { _T("mention_comment_photo"), vkPhoto, vkComment }, + { _T("mention_comment_video"), vkVideo, vkComment } + }; + + vkFeedback = vkParent = vkNull; + for (int i = 0; i < SIZEOF(vkNotification); i++) + if (tszType == vkNotification[i].tszType) { + vkFeedback = vkNotification[i].vkFeedback; + vkParent = vkNotification[i].vkParent; + break; + } +} \ No newline at end of file diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h index e765d64d4f..ccfd097a0f 100644 --- a/protocols/VKontakte/src/version.h +++ b/protocols/VKontakte/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 0 -#define __BUILD_NUM 31 +#define __BUILD_NUM 32 #include diff --git a/protocols/VKontakte/src/vk_feed.cpp b/protocols/VKontakte/src/vk_feed.cpp index c719a1647d..4eb2ef2a80 100644 --- a/protocols/VKontakte/src/vk_feed.cpp +++ b/protocols/VKontakte/src/vk_feed.cpp @@ -17,7 +17,6 @@ along with this program. If not, see . #include "stdafx.h" -#define VK_EVENTTYPE_FEED 10001 static char* szImageTypes[] = { "photo_2560", "photo_1280", "photo_807", "photo_604", "photo_256", "photo_130", "photo_128", "photo_75", "photo_64" }; void CVkProto::AddFeedSpecialUser() @@ -45,13 +44,11 @@ void CVkProto::AddFeedSpecialUser() } void CVkProto::AddFeedEvent(CMString& tszBody, time_t tTime) -{ - +{ MCONTACT hContact = FindUser(VK_FEED_USER, true); - ptrT ptszBody; + ptrT ptszBody(mir_tstrdup(tszBody.GetBuffer())); PROTORECVEVENT recv = { 0 }; - ptszBody = mir_tstrdup(tszBody.GetBuffer()); recv.flags = PREF_TCHAR; recv.timestamp = tTime; recv.tszMessage = ptszBody; @@ -62,23 +59,29 @@ void CVkProto::AddFeedEvent(CMString& tszBody, time_t tTime) ProtoChainRecvMsg(hContact, &recv); } -void CVkProto::RetrieveUnreadNews() +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CVkUserInfo* CVkProto::GetVkUserInfo(LONG iUserId, OBJLIST &vkUsers) { - debugLogA("CVkProto::RetrieveUnreadNews"); - if (!IsOnline() || !(m_bNewsEnabled || m_bNotificationsEnabled)) - return; + debugLogA("CVkProto::GetVkUserInfo %d", iUserId); + if (iUserId == 0) + return NULL; - time_t tLastNewsTime = getDword("LastNewsTime", time(NULL) - 24 * 60 * 60); - if (time(NULL) - tLastNewsTime <= m_iNewsInterval * 60 ) - return; + bool bIsGroup = (iUserId < 0); + CVkUserInfo * vkUser = vkUsers.find((CVkUserInfo *)&iUserId); - Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/newsfeed.get.json", true, &CVkProto::OnReceiveUnreadNews) - << INT_PARAM("count", 100) - << INT_PARAM("return_banned", 0) - << INT_PARAM("max_photos", 100) - << INT_PARAM("start_time", tLastNewsTime + 1) - << CHAR_PARAM("filters", "post,photo,photo_tag,wall_photo") - << VER_API); + if (vkUser == NULL) { + CMString tszNick = TranslateT("Unknown"); + CMString tszLink = _T("https://vk.com/"); + if (iUserId){ + tszLink += bIsGroup ? "club" : "id"; + tszLink.AppendFormat(_T("%d"), bIsGroup ? -iUserId : iUserId); + } + vkUser = new CVkUserInfo(iUserId, bIsGroup, tszNick, tszLink, bIsGroup ? NULL : FindUser(iUserId)); + vkUsers.insert(vkUser); + } + + return vkUser; } void CVkProto::CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pResponse) @@ -100,8 +103,7 @@ void CVkProto::CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pRe tszNick += json_as_string(json_get(pProfile, "last_name")); CMString tszLink = _T("https://vk.com/"); tszLink += json_as_string(json_get(pProfile, "screen_name")); - CVkUserInfo * vkUser = new CVkUserInfo(UserId, false, tszNick, tszLink); - debugLog(_T("CVkProto::CreateVkUserInfoList %d %d %s %s"), UserId, false, tszNick.GetBuffer(), tszLink.GetBuffer()); + CVkUserInfo * vkUser = new CVkUserInfo(UserId, false, tszNick, tszLink, FindUser(UserId)); vkUsers.insert(vkUser); } @@ -116,7 +118,6 @@ void CVkProto::CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pRe CMString tszLink = _T("https://vk.com/"); tszLink += json_as_string(json_get(pProfile, "screen_name")); CVkUserInfo * vkUser = new CVkUserInfo(UserId, true, tszNick, tszLink); - debugLog(_T("CVkProto::CreateVkUserInfoList %d %d %s %s"), UserId, true, tszNick.GetBuffer(), tszLink.GetBuffer()); vkUsers.insert(vkUser); } } @@ -139,7 +140,8 @@ CMString CVkProto::GetVkPhotoItem(JSONNODE *pPhoto) int iWidth = json_as_int(json_get(pPhoto, "width")); int iHeight = json_as_int(json_get(pPhoto, "height")); - tszRes.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink, iWidth, iHeight); + + tszRes.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink ? ptszLink : _T(""), iWidth, iHeight); if (m_bAddImgBbc) tszRes.AppendFormat(_T("\n\t[img]%s[/img]"), ptszLink); CMString tszText = json_as_string(json_get(pPhoto, "text")); @@ -149,6 +151,8 @@ CMString CVkProto::GetVkPhotoItem(JSONNODE *pPhoto) return tszRes; } +////////////////////////////////////////////////////////////////////////////////////////////////////////// + CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, time_t &tDate) { debugLogA("CVkProto::GetVkNewsItem"); @@ -161,21 +165,7 @@ CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, LONG iSourceId = json_as_int(json_get(pItem, "source_id")); iSourceId = iSourceId ? iSourceId : json_as_int(json_get(pItem, "owner_id")); - - bool bIsGroup = (iSourceId < 0); - CVkUserInfo * vkUser = vkUsers.find((CVkUserInfo *)&iSourceId); - - if (vkUser == NULL) { - CMString tszNick = TranslateT("Unknown"); - CMString tszLink = _T("https://vk.com/"); - if (iSourceId){ - tszLink += bIsGroup ? "club" : "id"; - tszLink.AppendFormat(_T("%d"), bIsGroup ? -iSourceId : iSourceId); - } - vkUser = new CVkUserInfo(iSourceId, bIsGroup, tszNick, tszLink); - vkUsers.insert(vkUser); - } - + CVkUserInfo *vkUser = GetVkUserInfo(iSourceId, vkUsers); LONG iPostId = json_as_int(json_get(pItem, "post_id")); tDate = json_as_int(json_get(pItem, "date")); CMString tszText = json_as_string(json_get(pItem, "text")); @@ -199,11 +189,9 @@ CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, bPostLink = false; JSONNODE *pPhotos = json_get(pItem, "photos"); if (pPhotos){ - JSONNODE *pPhotoItems = json_get(pPhotos, "items"); - if (pPhotoItems){ - JSONNODE *pPhotoItem; - for (size_t i = 0; (pPhotoItem = json_at(pPhotoItems, i)) != NULL; i++){ - + JSONNODE *pPhotoItems = json_get(pPhotos, "items"), *pPhotoItem; + if (pPhotoItems) + for (size_t i = 0; (pPhotoItem = json_at(pPhotoItems, i)) != NULL; i++){ tszText += GetVkPhotoItem(pPhotoItem) + _T("\n"); if (i == 0 && tszType == _T("wall_photo")){ iPostId = json_as_int(json_get(pPhotoItem, "post_id")); @@ -211,9 +199,9 @@ CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, break; // Max 1 wall_photo } } - } } - } else if (tszType == _T("post") || tszType.IsEmpty()) { + } + else if (tszType == _T("post") || tszType.IsEmpty()) { bPostLink = true; JSONNODE * pRepost = json_get(pItem, "copy_history"); if (pRepost){ @@ -253,12 +241,162 @@ CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, return tszRes; } +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CMString CVkProto::GetVkFeedback(JSONNODE *pFeedback, VKObjType vkFeedbackType, OBJLIST &vkUsers, CVkUserInfo *vkUser) +{ + debugLogA("CVkProto::GetVkFeedback"); + CMString tszRes; + if (!pFeedback || !vkFeedbackType) + return tszRes; + + + CMString tszBBCIn = m_bBBCOnNews ? "[b]" : "["; + CMString tszBBCOut = m_bBBCOnNews ? "[/b]" : "]"; + CMString tszFormat; + LONG iUserId = 0; + + if (vkFeedbackType == vkComment) { + iUserId = json_as_int(json_get(pFeedback, "from_id")); + tszFormat = TranslateT("%s%s%s (%s) commented %%s\n%s"); + } + else if (vkFeedbackType == vkPost) { + iUserId = json_as_int(json_get(pFeedback, "owner_id ")); + tszFormat = TranslateT("%s%s%s (%s) posted %%s\n%s"); + } + else if (vkFeedbackType == VKObjType::vkUsers || vkFeedbackType == vkCopy){ + JSONNODE *pUsers = json_get(pFeedback, "items"), *pUserItem; + + CMString tszUsers; + for (int i = 0; (pUserItem = json_at(pUsers, i)) != NULL; i++){ + iUserId = json_as_int(json_get(pUserItem, "from_id")); + if (iUserId == 0) + continue; + vkUser = GetVkUserInfo(iUserId, vkUsers); + if (!tszUsers.IsEmpty()) + tszUsers += _T(", "); + tszUsers.AppendFormat(_T("%s%s%s (%s)"), tszBBCIn.GetBuffer(), vkUser->m_tszUserNick.GetBuffer(), tszBBCOut.GetBuffer(), vkUser->m_tszLink.GetBuffer()); + } + tszRes.AppendFormat(_T("User(s) %s %s %%s"), tszUsers.GetBuffer(), (vkFeedbackType == VKObjType::vkUsers) ? TranslateT("liked you") : TranslateT("shared you")); + vkUser = NULL; + iUserId = 0; + } + + if (iUserId){ + vkUser = GetVkUserInfo(iUserId, vkUsers); + CMString tszText = json_as_string(json_get(pFeedback, "text")); + tszRes.AppendFormat(tszFormat, tszBBCIn.GetBuffer(), vkUser->m_tszUserNick.GetBuffer(), tszBBCOut.GetBuffer(), vkUser->m_tszLink.GetBuffer(), tszText.GetBuffer()); + } + + return tszRes; +} + +CMString CVkProto::GetVkParent(JSONNODE *pParent, VKObjType vkParentType) +{ + debugLogA("CVkProto::GetVkParent"); + CMString tszRes; + if (!pParent || !vkParentType) + return tszRes; + + CMString tszBBCIn = m_bBBCOnNews ? "[b]" : "["; + CMString tszBBCOut = m_bBBCOnNews ? "[/b]" : "]"; + + if (vkParentType == vkPhoto) { + CMString tszPhoto = GetVkPhotoItem(pParent); + LONG iOwnerId = json_as_int(json_get(pParent, "owner_id")); + LONG iId = json_as_int(json_get(pParent, "id")); + CMString tszFormat = _T("%s\n%s\n%s: https://vk.com/photo%d_%d"); + tszRes.AppendFormat(tszFormat, TranslateT("photo"), tszPhoto.GetBuffer(), TranslateT("Link"), iOwnerId, iId); + } + else if (vkParentType == vkVideo) { + LONG iOwnerId = json_as_int(json_get(pParent, "owner_id")); + LONG iId = json_as_int(json_get(pParent, "id")); + CMString tszTitle = json_as_string(json_get(pParent, "title")); + + CMString tszFormat = _T("%s %s%s%s\n%s: https://vk.com/video%d_%d"); + tszRes.AppendFormat(tszFormat, TranslateT("video"), tszBBCIn.GetBuffer(), tszTitle.GetBuffer(), tszBBCOut.GetBuffer(), TranslateT("Link"), iOwnerId, iId); + } + else if (vkParentType == vkPost) { + LONG iOwnerId = json_as_int(json_get(pParent, "from_id")); + LONG iId = json_as_int(json_get(pParent, "id")); + CMString tszFormat = _T("%s\n%s: https://vk.com/wall%d_%d"); + tszRes.AppendFormat(tszFormat, TranslateT("post"), TranslateT("Link"), iOwnerId, iId); + } + else if (vkParentType == vkTopic) { + LONG iOwnerId = json_as_int(json_get(pParent, "owner_id")); + LONG iId = json_as_int(json_get(pParent, "id")); + CMString tszTitle = json_as_string(json_get(pParent, "title")); + + CMString tszFormat = _T("%s %s%s%s\n%s: https://vk.com/topic%d_%d"); + tszRes.AppendFormat(tszFormat, TranslateT("topic"), tszBBCIn.GetBuffer(), tszTitle.GetBuffer(), tszBBCOut.GetBuffer(), TranslateT("Link"), iOwnerId, iId); + } + else if (vkParentType == vkComment) { + LONG iOwnerId = json_as_int(json_get(pParent, "owner_id")); + LONG iId = json_as_int(json_get(pParent, "id")); + CMString tszTitle = json_as_string(json_get(pParent, "title")); + + CMString tszFormat = _T("%s %s%s%s\n%s: https://vk.com/topic%d_%d"); + tszRes.AppendFormat(tszFormat, TranslateT("topic"), tszBBCIn.GetBuffer(), tszTitle.GetBuffer(), tszBBCOut.GetBuffer(), TranslateT("Link"), iOwnerId, iId); + } + + return tszRes; +} + +CMString CVkProto::GetVkNotificationsItem(JSONNODE *pItem, OBJLIST &vkUsers, time_t &tDate) +{ + debugLogA("CVkProto::GetVkNotificationsItem"); + CMString tszRes; + if (pItem == NULL) + return tszRes; + + CMString tszType = json_as_string(json_get(pItem, "type")); + tDate = json_as_int(json_get(pItem, "date")); + + VKObjType vkFeedbackType = vkNull, vkParentType = vkNull; + SpanVKNotificationType(tszType, vkFeedbackType, vkParentType); + + JSONNODE *pFeedback = json_get(pItem, "feedback"); + if (!pFeedback) + return tszRes; + CVkUserInfo *vkUser = NULL; + CMString tszFeedback = GetVkFeedback(pFeedback, vkFeedbackType, vkUsers, vkUser); + + JSONNODE *pParent = json_get(pItem, "parent"); + if (!pParent) + return tszRes; + CMString tszParent = GetVkParent(pParent, vkParentType); + if (!tszParent.IsEmpty() && !tszFeedback.IsEmpty()) + tszRes.AppendFormat(tszFeedback, tszParent.GetBuffer()); + return tszRes; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CVkProto::RetrieveUnreadNews() +{ + debugLogA("CVkProto::RetrieveUnreadNews"); + if (!IsOnline() || !m_bNewsEnabled) + return; + + time_t tLastNewsTime = getDword("LastNewsTime", time(NULL) - 24 * 60 * 60); + if (time(NULL) - tLastNewsTime <= m_iNewsInterval * 60) + return; + + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/newsfeed.get.json", true, &CVkProto::OnReceiveUnreadNews) + << INT_PARAM("count", 100) + << INT_PARAM("return_banned", 0) + << INT_PARAM("max_photos", 100) + << INT_PARAM("start_time", tLastNewsTime + 1) + << CHAR_PARAM("filters", "post,photo,photo_tag,wall_photo") + << VER_API); +} + void CVkProto::OnReceiveUnreadNews(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUnreadNews %d", reply->resultCode); if (reply->resultCode != 200) return; - + JSONROOT pRoot; JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot); if (pResponse == NULL) @@ -272,12 +410,59 @@ void CVkProto::OnReceiveUnreadNews(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *p if (pItems != NULL) for (int i = 0; (pItem = json_at(pItems, i)) != NULL; i++){ - time_t tDate; + time_t tDate; CMString tszText = GetVkNewsItem(pItem, vkUsers, tDate); AddFeedEvent(tszText, tDate); } - + setDword("LastNewsTime", time(NULL)); vkUsers.destroy(); } + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CVkProto::RetrieveUnreadNotifications() +{ + debugLogA("CVkProto::RetrieveUnreadNotifications"); + if (!IsOnline() || !m_bNotificationsEnabled) + return; + + time_t tLastNotificationsTime = getDword("LastNotificationsTime", time(NULL) - 24 * 60 * 60); + if (time(NULL) - tLastNotificationsTime <= m_iNewsInterval * 60) + return; + + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/notifications.get.json", true, &CVkProto::OnReceiveUnreadNotifications) + << INT_PARAM("count", 100) + << INT_PARAM("start_time", tLastNotificationsTime + 1) + << CHAR_PARAM("filters", "wall,comments,mentions,likes,reposts") + << VER_API); +} + +void CVkProto::OnReceiveUnreadNotifications(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +{ + debugLogA("CVkProto::OnReceiveUnreadNotifications %d", reply->resultCode); + if (reply->resultCode != 200) + return; + + JSONROOT pRoot; + JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot); + if (pResponse == NULL) + return; + + OBJLIST vkUsers(5, NumericKeySortT); + CreateVkUserInfoList(vkUsers, pResponse); + + JSONNODE *pItems = json_get(pResponse, "items"); + JSONNODE *pItem; + + if (pItems != NULL) + for (int i = 0; (pItem = json_at(pItems, i)) != NULL; i++){ + time_t tDate; + CMString tszText = GetVkNotificationsItem(pItem, vkUsers, tDate); + AddFeedEvent(tszText, tDate); + } + + setDword("LastNotificationsTime", time(NULL)); + vkUsers.destroy(); +} \ No newline at end of file diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 8167a0b47d..6ee5a25b7b 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -163,14 +163,16 @@ struct CVkUserInfo : public MZeroedObject{ m_bIsGroup(false) {} - CVkUserInfo(LONG _UserId, bool _bIsGroup, CMString& _tszUserNick, CMString& _tszLink) : + CVkUserInfo(LONG _UserId, bool _bIsGroup, CMString& _tszUserNick, CMString& _tszLink, MCONTACT _hContact = NULL) : m_UserId(_UserId), m_bIsGroup(_bIsGroup), m_tszUserNick(_tszUserNick), - m_tszLink(_tszLink) + m_tszLink(_tszLink), + m_hContact(_hContact) {} - LONG m_UserId; + LONG m_UserId; + MCONTACT m_hContact; CMString m_tszUserNick; CMString m_tszLink; bool m_bIsGroup; @@ -186,6 +188,13 @@ struct TFakeAckParams int msgid; }; +enum VKObjType { vkNull, vkPost, vkPhoto, vkVideo, vkComment, vkTopic, vkUsers, vkCopy }; + +struct CVkNotification { + TCHAR *tszType; + VKObjType vkParent, vkFeedback; +}; + struct CVkProto : public PROTO { CVkProto(const char*, const TCHAR*); @@ -309,11 +318,24 @@ struct CVkProto : public PROTO void AddFeedSpecialUser(); void AddFeedEvent(CMString& tszBody, time_t tTime); - void CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pResponse); + + CVkUserInfo * GetVkUserInfo(LONG iUserId, OBJLIST &vkUsers); + void CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pResponse); CMString GetVkPhotoItem(JSONNODE *pPhotoItem); + CMString GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, time_t &tDate); + + CMString GetVkNotificationsItem(JSONNODE *pItem, OBJLIST &vkUsers, time_t &tDate); + CMString GetVkFeedback(JSONNODE *pFeedback, VKObjType vkFeedbackType, OBJLIST &vkUsers, CVkUserInfo *vkUser); + CMString GetVkParent(JSONNODE *pParent, VKObjType vkParentType); + void RetrieveUnreadNews(); void OnReceiveUnreadNews(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + + void RetrieveUnreadNotifications(); + void OnReceiveUnreadNotifications(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + + void SpanVKNotificationType(CMString& tszType, VKObjType& vkFeedback, VKObjType& vkParent); //==== Misc ========================================================================== diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index f3134be484..e5f494d68c 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -103,7 +103,7 @@ void CVkProto::WorkerThread(void*) extern char szBlankUrl[]; Push(new AsyncHttpRequest(this, REQUEST_GET, "/oauth/authorize", false, &CVkProto::OnOAuthAuthorize) << INT_PARAM("client_id", VK_APP_ID) - << CHAR_PARAM("scope", "friends,photos,audio,docs,video,wall,messages,offline,status") + << CHAR_PARAM("scope", "friends,photos,audio,docs,video,wall,messages,offline,status,notifications") << CHAR_PARAM("redirect_uri", szBlankUrl) << CHAR_PARAM("display", "mobile") << CHAR_PARAM("response_type", "token") diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 23226755ab..15bf752f69 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -55,6 +55,7 @@ static VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD) vk_Instances[i]->SetServerStatus(vk_Instances[i]->m_iDesiredStatus); vk_Instances[i]->RetrieveUsersInfo(true); vk_Instances[i]->RetrieveUnreadNews(); + vk_Instances[i]->RetrieveUnreadNotifications(); } } @@ -1278,7 +1279,7 @@ CMString CVkProto::GetAttachmentDescr(JSONNODE *pAttachments) 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); + res.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink ? ptszLink : _T(""), iWidth, iHeight); if (m_bAddImgBbc) res.AppendFormat(_T("\n\t[img]%s[/img]"), ptszLink); } @@ -1365,8 +1366,7 @@ CMString CVkProto::GetAttachmentDescr(JSONNODE *pAttachments) res.AppendFormat(_T("\n\t%s: %s"), TranslateT("Image"), tszImage.GetBuffer()); if (ptszDescription) - res.AppendFormat(_T("\n\t%s"), ptszDescription ? ptszDescription: _T("")); - + res.AppendFormat(_T("\n\t%s"), ptszDescription); } else res.AppendFormat(TranslateT("Unsupported or unknown attachment type: %s"), ptszType); -- cgit v1.2.3