summaryrefslogtreecommitdiff
path: root/protocols/VKontakte
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/VKontakte')
-rw-r--r--protocols/VKontakte/res/resource.rc2
-rw-r--r--protocols/VKontakte/src/misc.cpp41
-rw-r--r--protocols/VKontakte/src/version.h2
-rw-r--r--protocols/VKontakte/src/vk_feed.cpp281
-rw-r--r--protocols/VKontakte/src/vk_proto.h30
-rw-r--r--protocols/VKontakte/src/vk_queue.cpp2
-rw-r--r--protocols/VKontakte/src/vk_thread.cpp6
7 files changed, 306 insertions, 58 deletions
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 <stdver.h>
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 <http://www.gnu.org/licenses/>.
#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<CVkUserInfo> &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<CVkUserInfo> &vkUsers, JSONNODE *pResponse)
@@ -100,8 +103,7 @@ void CVkProto::CreateVkUserInfoList(OBJLIST<CVkUserInfo> &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<CVkUserInfo> &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<CVkUserInfo> &vkUsers, time_t &tDate)
{
debugLogA("CVkProto::GetVkNewsItem");
@@ -161,21 +165,7 @@ CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST<CVkUserInfo> &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<CVkUserInfo> &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<CVkUserInfo> &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<CVkUserInfo> &vkUsers,
return tszRes;
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CMString CVkProto::GetVkFeedback(JSONNODE *pFeedback, VKObjType vkFeedbackType, OBJLIST<CVkUserInfo> &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<CVkUserInfo> &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<CVkUserInfo> 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>
{
CVkProto(const char*, const TCHAR*);
@@ -309,11 +318,24 @@ struct CVkProto : public PROTO<CVkProto>
void AddFeedSpecialUser();
void AddFeedEvent(CMString& tszBody, time_t tTime);
- void CreateVkUserInfoList(OBJLIST<CVkUserInfo> &vkUsers, JSONNODE *pResponse);
+
+ CVkUserInfo * GetVkUserInfo(LONG iUserId, OBJLIST<CVkUserInfo> &vkUsers);
+ void CreateVkUserInfoList(OBJLIST<CVkUserInfo> &vkUsers, JSONNODE *pResponse);
CMString GetVkPhotoItem(JSONNODE *pPhotoItem);
+
CMString GetVkNewsItem(JSONNODE *pItem, OBJLIST<CVkUserInfo> &vkUsers, time_t &tDate);
+
+ CMString GetVkNotificationsItem(JSONNODE *pItem, OBJLIST<CVkUserInfo> &vkUsers, time_t &tDate);
+ CMString GetVkFeedback(JSONNODE *pFeedback, VKObjType vkFeedbackType, OBJLIST<CVkUserInfo> &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);