From 27a37d3d9753b378fa85cce0f7fa3e2de8e35a57 Mon Sep 17 00:00:00 2001 From: Sergey Bolhovskoy Date: Mon, 15 Dec 2014 06:12:18 +0000 Subject: =?UTF-8?q?VKontakte:=20fix=20for=20warning=20C4121=20in=20AsyncHt?= =?UTF-8?q?tpRequest=20struct=20fix=20for=20TCHAR=20in=20SetMirVer=20add?= =?UTF-8?q?=20vk=20feeds=20support=20(wall)=20=E2=80=93=20part=201?= 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@11430 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/VKontakte/src/vk_feed.cpp | 283 ++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 protocols/VKontakte/src/vk_feed.cpp (limited to 'protocols/VKontakte/src/vk_feed.cpp') diff --git a/protocols/VKontakte/src/vk_feed.cpp b/protocols/VKontakte/src/vk_feed.cpp new file mode 100644 index 0000000000..d2d22e21bd --- /dev/null +++ b/protocols/VKontakte/src/vk_feed.cpp @@ -0,0 +1,283 @@ +/* +Copyright (c) 2013-14 Miranda NG project (http://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +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() +{ + MCONTACT hContact = FindUser(VK_FEED_USER, m_bNewsEnabled); + if (!m_bNewsEnabled) { + if (hContact) + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + return; + } + + CMString tszNick = TranslateT("VKontakte"); + setTString(hContact, "Nick", tszNick.GetBuffer()); + CMString url = _T("https://vk.com/press/Simple.png"); + SetAvatarUrl(hContact, url); + ReloadAvatarInfo(hContact); + + if (getWord(hContact, "Status", 0) != ID_STATUS_ONLINE) + setWord(hContact, "Status", ID_STATUS_ONLINE); + SetMirVer(hContact, 7); + + setTString(hContact, "domain", _T("feed")); + setTString(hContact, "Homepage", _T("https://vk.com/feed")); +} + +void CVkProto::AddFeedEvent(CMString& tszBody, time_t tTime) +{ + + MCONTACT hContact = FindUser(VK_FEED_USER, true); + ptrT ptszBody; + PROTORECVEVENT recv = { 0 }; + + ptszBody = mir_tstrdup(tszBody.GetBuffer()); + recv.flags = PREF_TCHAR; + recv.timestamp = tTime; + recv.tszMessage = ptszBody; + recv.lParam = 0; + recv.pCustomData = NULL; + recv.cbCustomDataSize = 0; + + ProtoChainRecvMsg(hContact, &recv); +} + +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::CreateVkUserInfoList(OBJLIST &vkUsers, JSONNODE *pResponse) +{ + debugLogA("CVkProto::CreateVkUserInfoList"); + if (pResponse == NULL) + return; + + JSONNODE *pProfiles = json_get(pResponse, "profiles"); + JSONNODE *pProfile; + if (pProfiles != NULL) + for (size_t i = 0; (pProfile = json_at(pProfiles, i)) != NULL; i++){ + LONG UserId = json_as_int(json_get(pProfile, "id")); + if (!UserId) + continue; + + CMString tszNick = json_as_string(json_get(pProfile, "first_name")); + tszNick.AppendChar(' '); + 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()); + vkUsers.insert(vkUser); + } + + JSONNODE *pGroups = json_get(pResponse, "groups"); + if (pGroups != NULL) + for (size_t i = 0; (pProfile = json_at(pGroups, i)) != NULL; i++){ + LONG UserId = -json_as_int(json_get(pProfile, "id")); + if (!UserId) + continue; + + CMString tszNick = json_as_string(json_get(pProfile, "name")); + 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); + } +} + +CMString CVkProto::GetVkPhotoItem(JSONNODE *pPhoto) +{ + CMString tszRes; + + if (pPhoto == NULL) + return tszRes; + + 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")); + tszRes.AppendFormat(_T("%s: %s (%dx%d)"), TranslateT("Photo"), ptszLink, iWidth, iHeight); + if (m_bAddImgBbc) + tszRes.AppendFormat(_T("\n\t[img]%s[/img]"), ptszLink); + CMString tszText = json_as_string(json_get(pPhoto, "text")); + if (!tszText.IsEmpty()) + tszRes += "\n" + tszText; + + return tszRes; +} + +CMString CVkProto::GetVkNewsItem(JSONNODE *pItem, OBJLIST &vkUsers, time_t &tDate) +{ + debugLogA("CVkProto::GetVkNewsItem"); + bool m_bBBCOnNews = true; //!!! + bool bPostLink = true; + CMString tszRes; + if (pItem == NULL) + return tszRes; + + CMString tszType = json_as_string(json_get(pItem, "type")); + + 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); + } + + 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")); + if (!tszText.IsEmpty()) + tszText += _T("\n"); + + if (tszType == _T("photo_tag")){ + bPostLink = false; + JSONNODE *pPhotos = json_get(pItem, "photo_tags"); + if (pPhotos){ + JSONNODE *pPhotoItems = json_get(pPhotos, "items"); + if (pPhotoItems){ + JSONNODE *pPhotoItem; + tszText = TranslateT("User was tagged in these photos:"); + for (size_t i = 0; (pPhotoItem = json_at(pPhotoItems, i)) != NULL; i++) + tszText += _T("\n") + GetVkPhotoItem(pPhotoItem); + } + } + } + else if (tszType == _T("photo") || tszType == _T("wall_photo")){ + 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++){ + + tszText += GetVkPhotoItem(pPhotoItem) + _T("\n"); + if (i == 0 && tszType == _T("wall_photo")){ + iPostId = json_as_int(json_get(pPhotoItem, "post_id")); + bPostLink = true; + break; // Max 1 wall_photo + } + } + } + } + } else if (tszType == _T("post") || tszType.IsEmpty()) { + bPostLink = true; + JSONNODE * pRepost = json_get(pItem, "copy_history"); + if (pRepost){ + time_t tRDate; + CMString tszRepostText = GetVkNewsItem(json_at(pRepost, 0), vkUsers, tRDate); + tszRepostText.Replace(_T("\n"), _T("\n\t")); + tszText += tszRepostText; + tszText += _T("\n"); + } + + JSONNODE *pAttachments = json_get(pItem, "attachments"); + if (pAttachments) + tszText += GetAttachmentDescr(pAttachments); + } + + CMString tszResFormat; + CMString tszBBCIn, tszBBCOut; + CMString tszUrl; + + if (iPostId) + tszResFormat = Translate("News from %s%s%s (%s)\n%s"); + else { + tszResFormat = Translate("\tRepost from %s%s%s (%s)\n%s"); + bPostLink = false; + } + + tszBBCIn = m_bBBCOnNews ? "[b]" : "["; + tszBBCOut = m_bBBCOnNews ? "[/b]" : "]"; + tszRes.AppendFormat(tszResFormat, tszBBCIn.GetBuffer(), vkUser->m_tszUserNick.GetBuffer(), tszBBCOut.GetBuffer(), vkUser->m_tszLink.GetBuffer(), tszText.GetBuffer()); + + if (bPostLink) { + tszUrl.AppendFormat(_T("%d_%d"), vkUser->m_UserId, iPostId); + tszUrl = CMString(_T("https://vk.com/wall")) + tszUrl; + tszRes.AppendFormat(TranslateT("\nNews link: %s"), tszUrl.GetBuffer()); + } + + return tszRes; +} + +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) + 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 = GetVkNewsItem(pItem, vkUsers, tDate); + AddFeedEvent(tszText, tDate); + } + + + setDword("LastNewsTime", time(NULL)); + vkUsers.destroy(); +} -- cgit v1.2.3