diff options
-rw-r--r-- | protocols/VKontakte/src/misc.cpp | 20 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk.h | 1 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_feed.cpp | 283 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_files.cpp | 5 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_history.cpp | 4 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.cpp | 24 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 39 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_thread.cpp | 34 | ||||
-rw-r--r-- | protocols/VKontakte/vk_10.vcxproj | 1 | ||||
-rw-r--r-- | protocols/VKontakte/vk_10.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/VKontakte/vk_12.vcxproj | 1 | ||||
-rw-r--r-- | protocols/VKontakte/vk_12.vcxproj.filters | 9 |
12 files changed, 382 insertions, 42 deletions
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index 3525ce9692..31124b26b3 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -488,44 +488,44 @@ void CVkProto::SetMirVer(MCONTACT hContact, int platform) switch (platform) {
case VK_APP_ID:
- MirVer = "Miranda NG VKontakte";
+ MirVer = _T("Miranda NG VKontakte");
break;
case 2386311:
- MirVer = "QIP 2012 VKontakte";
+ MirVer = _T("QIP 2012 VKontakte");
break;
case 1:
- MirVer = "VKontakte (mobile)";
+ MirVer = _T("VKontakte (mobile)");
break;
case 3087106: // iPhone
case 3140623:
case 2:
- MirVer = "VKontakte (iphone)";
+ MirVer = _T("VKontakte (iphone)");
break;
case 3682744: // iPad
case 3:
- MirVer = "VKontakte (ipad)";
+ MirVer = _T("VKontakte (ipad)");
break;
case 2685278: // Android - Kate
case 2890984: // Android
case 2274003:
case 4:
- MirVer = "VKontakte (android)";
+ MirVer = _T("VKontakte (android)");
break;
case 3059453: // Windows Phone
case 2424737:
case 3502561:
case 5:
- MirVer = "VKontakte (wphone)";
+ MirVer = _T("VKontakte (wphone)");
break;
case 3584591: // Windows 8.x
case 6:
- MirVer = "VKontakte (windows)";
+ MirVer = _T("VKontakte (windows)");
break;
case 7:
- MirVer = "VKontakte (website)";
+ MirVer = _T("VKontakte (website)");
break;
default:
- MirVer = "VKontakte (other)";
+ MirVer = _T("VKontakte (other)");
bSetFlag = OldMirVer.IsEmpty();
}
diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h index fddb6aebb1..ff1914446f 100644 --- a/protocols/VKontakte/src/vk.h +++ b/protocols/VKontakte/src/vk.h @@ -67,6 +67,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define VK_API_VER "5.27"
#define VER_API CHAR_PARAM("v", VK_API_VER)
+#define VK_FEED_USER 2147483647L
#if defined(_DEBUG)
#define VK_NODUMPHEADERS 0
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 <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()
+{
+ 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<CVkUserInfo> &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<CVkUserInfo> &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<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 = GetVkNewsItem(pItem, vkUsers, tDate);
+ AddFeedEvent(tszText, tDate);
+ }
+
+
+ setDword("LastNewsTime", time(NULL));
+ vkUsers.destroy();
+}
diff --git a/protocols/VKontakte/src/vk_files.cpp b/protocols/VKontakte/src/vk_files.cpp index f20fc3760d..5399ba4b04 100644 --- a/protocols/VKontakte/src/vk_files.cpp +++ b/protocols/VKontakte/src/vk_files.cpp @@ -72,7 +72,8 @@ CVkFileUploadParam::VKFileType CVkFileUploadParam::GetType() HANDLE CVkProto::SendFile(MCONTACT hContact, const PROTOCHAR *desc, PROTOCHAR **files)
{
debugLogA("CVkProto::SendFile");
- if (!IsOnline())
+ LONG userID = getDword(hContact, "ID", -1);
+ if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
return (HANDLE)0;
CVkFileUploadParam *fup = new CVkFileUploadParam(hContact, desc, files);
ForkThread(&CVkProto::SendFileThread, (void *)fup);
@@ -348,7 +349,7 @@ void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pR }
LONG userID = getDword(fup->hContact, "ID", -1);
- if (userID == -1) {
+ if (userID == -1 || userID == VK_FEED_USER) {
SendFileFiled(fup);
return;
}
diff --git a/protocols/VKontakte/src/vk_history.cpp b/protocols/VKontakte/src/vk_history.cpp index 2ce58429ee..7474b512ea 100644 --- a/protocols/VKontakte/src/vk_history.cpp +++ b/protocols/VKontakte/src/vk_history.cpp @@ -29,7 +29,7 @@ INT_PTR __cdecl CVkProto::SvcGetAllServerHistory(WPARAM hContact, LPARAM) return 0;
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1)
+ if (userID == -1 || userID == VK_FEED_USER)
return 0;
HANDLE hDBEvent = db_event_first(hContact);
@@ -125,7 +125,7 @@ void CVkProto::GetServerHistory(MCONTACT hContact, int iOffset, int iCount, int return;
LONG userID = getDword(hContact, "ID", -1);
- if (-1 == userID)
+ if (-1 == userID || userID == VK_FEED_USER)
return;
CMStringA code, formatcode = "var iOffset=%d;var iReqCount=%d;var userID=%d;var iTime=%d;var lastMid=%d;"
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index e5a1ec9c14..6238e399a5 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -78,6 +78,9 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) : CMStringA szListeningTo(m_szModuleName);
szListeningTo += "Enabled";
db_set_b(NULL, "ListeningTo", szListeningTo.GetBuffer(), m_iMusicSendMetod == 0 ? 0 : 1);
+ m_bNewsEnabled = getBool("NewsEnabled", false);
+ m_bBBCOnNews = getBool("BBCOnNews", false);
+ m_iNewsInterval = getDword("NewsInterval", 15);
// Set all contacts offline -- in case we crashed
SetAllContactStatuses(ID_STATUS_OFFLINE);
@@ -272,18 +275,19 @@ void CVkProto::InitMenus() int CVkProto::OnPreBuildContactMenu(WPARAM hContact, LPARAM)
{
+ LONG userID = getDword(hContact, "ID", -1);
bool bisFriend = (getByte(hContact, "Auth", -1) == 0);
bool bisBroadcast = !(CMString(db_get_tsa(hContact, m_szModuleName, "AudioUrl")).IsEmpty());
Menu_ShowItem(g_hContactMenuItems[CMI_VISITPROFILE], !isChatRoom(hContact));
- Menu_ShowItem(g_hContactMenuItems[CMI_ADDASFRIEND], !bisFriend && !isChatRoom(hContact));
- Menu_ShowItem(g_hContactMenuItems[CMI_DELETEFRIEND], bisFriend);
- Menu_ShowItem(g_hContactMenuItems[CMI_BANUSER], !isChatRoom(hContact));
- Menu_ShowItem(g_hContactMenuItems[CMI_REPORTABUSE], !isChatRoom(hContact));
+ Menu_ShowItem(g_hContactMenuItems[CMI_ADDASFRIEND], !bisFriend && !isChatRoom(hContact) && userID != VK_FEED_USER);
+ Menu_ShowItem(g_hContactMenuItems[CMI_DELETEFRIEND], bisFriend && userID != VK_FEED_USER);
+ Menu_ShowItem(g_hContactMenuItems[CMI_BANUSER], !isChatRoom(hContact) && userID != VK_FEED_USER);
+ Menu_ShowItem(g_hContactMenuItems[CMI_REPORTABUSE], !isChatRoom(hContact) && userID != VK_FEED_USER);
Menu_ShowItem(g_hContactMenuItems[CMI_DESTROYKICKCHAT], isChatRoom(hContact) && getBool(hContact, "off", false));
Menu_ShowItem(g_hContactMenuItems[CMI_OPENBROADCAST], !isChatRoom(hContact) && bisBroadcast);
- Menu_ShowItem(g_hContactMenuItems[CMI_GETSERVERHISTORY], !isChatRoom(hContact));
+ Menu_ShowItem(g_hContactMenuItems[CMI_GETSERVERHISTORY], !isChatRoom(hContact) && userID != VK_FEED_USER);
for (int i = 0; i < CHMI_COUNT; i++)
- Menu_ShowItem(g_hContactHistoryMenuItems[i], !isChatRoom(hContact));
+ Menu_ShowItem(g_hContactHistoryMenuItems[i], !isChatRoom(hContact) && userID != VK_FEED_USER);
return 0;
}
@@ -420,7 +424,7 @@ int CVkProto::SendMsg(MCONTACT hContact, int flags, const char *msg) if (!IsOnline())
return 0;
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1)
+ if (userID == -1 || userID == VK_FEED_USER)
return 0;
ptrA szMsg;
@@ -568,7 +572,7 @@ int CVkProto::AuthRequest(MCONTACT hContact,const PROTOCHAR* message) return 1;
LONG userID = getDword(hContact, "ID", -1);
- if ((userID == -1) || !hContact)
+ if (userID == -1 || !hContact || userID == VK_FEED_USER)
return 1;
TCHAR msg[501] = {0};
@@ -649,7 +653,7 @@ int CVkProto::UserIsTyping(MCONTACT hContact, int type) debugLogA("CVkProto::UserIsTyping");
if (PROTOTYPE_SELFTYPING_ON == type) {
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1 || !IsOnline())
+ if (userID == -1 || !IsOnline() || userID == VK_FEED_USER)
return 1;
if (m_iMarkMessageReadOn == markOnTyping)
@@ -678,7 +682,7 @@ int CVkProto::GetInfo(MCONTACT hContact, int) {
debugLogA("CVkProto::GetInfo");
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1)
+ if (userID == -1 || userID == VK_FEED_USER)
return 1;
RetrieveUserInfo(userID);
return 0;
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 5c7be266a0..2e906bb011 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -47,11 +47,11 @@ struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject CMStringA m_szUrl;
CMStringA m_szParam;
- bool bNeedsRestart, bIsMainConn;
VK_REQUEST_HANDLER m_pFunc;
void *pUserInfo;
- bool m_bApiReq;
int m_iRetry;
+ bool m_bApiReq;
+ bool bNeedsRestart, bIsMainConn;
};
struct PARAM
@@ -157,6 +157,25 @@ struct CVkFileUploadParam { __forceinline char* fileName() { return fname; }
};
+struct CVkUserInfo : public MZeroedObject{
+ CVkUserInfo(LONG _UserId) :
+ m_UserId(_UserId),
+ m_bIsGroup(false)
+ {}
+
+ CVkUserInfo(LONG _UserId, bool _bIsGroup, CMString& _tszUserNick, CMString& _tszLink) :
+ m_UserId(_UserId),
+ m_bIsGroup(_bIsGroup),
+ m_tszUserNick(_tszUserNick),
+ m_tszLink(_tszLink)
+ {}
+ LONG m_UserId;
+
+ CMString m_tszUserNick;
+ CMString m_tszLink;
+ bool m_bIsGroup;
+};
+
struct TFakeAckParams
{
__inline TFakeAckParams(MCONTACT _hContact, int _msgid) :
@@ -286,6 +305,16 @@ struct CVkProto : public PROTO<CVkProto> void OnReciveUpload(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
void OnReciveUploadFile(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
+ //==== Feed ==========================================================================
+
+ void AddFeedSpecialUser();
+ void AddFeedEvent(CMString& tszBody, time_t tTime);
+ void CreateVkUserInfoList(OBJLIST<CVkUserInfo> &vkUsers, JSONNODE *pResponse);
+ CMString GetVkPhotoItem(JSONNODE *pPhotoItem);
+ CMString GetVkNewsItem(JSONNODE *pItem, OBJLIST<CVkUserInfo> &vkUsers, time_t &tDate);
+ void RetrieveUnreadNews();
+ void OnReceiveUnreadNews(NETLIBHTTPREQUEST*, AsyncHttpRequest*);
+
//==== Misc ==========================================================================
TCHAR* GetUserStoredPassword(void);
@@ -445,7 +474,11 @@ private: m_bPopUpSyncHistory,
m_bAddImgBbc,
m_bStikersAsSmyles,
- m_bUserForceOnlineOnActivity;
+ m_bUserForceOnlineOnActivity,
+ m_bNewsEnabled,
+ m_bBBCOnNews;
+
+ int m_iNewsInterval;
enum MarkMsgReadOn{ markOnRead, markOnReceive, markOnReply, markOnTyping };
int m_iMarkMessageReadOn;
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 2bb05aa571..39dc6b304a 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -54,6 +54,7 @@ static VOID CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD) if (vk_Instances[i]->IsOnline()) {
vk_Instances[i]->SetServerStatus(vk_Instances[i]->m_iDesiredStatus);
vk_Instances[i]->RetrieveUsersInfo(true);
+ vk_Instances[i]->RetrieveUnreadNews();
}
}
@@ -244,7 +245,7 @@ void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) RetrieveUserInfo(m_myUserId);
RetrieveUnreadMessages();
RetrieveFriends();
- RetrievePollingInfo();
+ RetrievePollingInfo();
}
MCONTACT CVkProto::SetContactInfo(JSONNODE* pItem, bool flag, bool self)
@@ -256,7 +257,7 @@ MCONTACT CVkProto::SetContactInfo(JSONNODE* pItem, bool flag, bool self) LONG userid = json_as_int(json_get(pItem, "id"));
debugLogA("CVkProto::SetContactInfo %d", userid);
- if (userid == 0)
+ if (userid == 0 || userid == VK_FEED_USER)
return NULL;
MCONTACT hContact = FindUser(userid, flag);
@@ -377,7 +378,7 @@ MCONTACT CVkProto::SetContactInfo(JSONNODE* pItem, bool flag, bool self) void CVkProto::RetrieveUserInfo(LONG userID)
{
debugLogA("CVkProto::RetrieveUserInfo (%d)", userID);
- if (!IsOnline())
+ if (userID == VK_FEED_USER || !IsOnline())
return;
CMString userIDs, code;
@@ -400,7 +401,7 @@ void CVkProto::RetrieveUsersInfo(bool flag) CMString userIDs, code;
for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1)
+ if (userID == -1 || userID == VK_FEED_USER)
continue;
if (!userIDs.IsEmpty())
userIDs.AppendChar(',');
@@ -448,10 +449,12 @@ void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe for (size_t i = 0; (hContact = SetContactInfo(json_at(pUsers, i))) != INVALID_CONTACT_ID; i++)
if (hContact)
arContacts.remove((HANDLE)hContact);
+
if (json_as_int(json_get(pResponse, "freeoffline")))
for (int i = 0; i < arContacts.getCount(); i++) {
hContact = (MCONTACT)arContacts[i];
- if (getDword(hContact, "ID", -1) == (DWORD)m_myUserId)
+ LONG userID = getDword(hContact, "ID", -1);
+ if (userID == m_myUserId || userID == VK_FEED_USER)
continue;
if (getWord(hContact, "Status", 0) != ID_STATUS_OFFLINE) {
setWord(hContact, "Status", ID_STATUS_OFFLINE);
@@ -459,6 +462,7 @@ void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe }
}
arContacts.destroy();
+ AddFeedSpecialUser();
JSONNODE *pRequests = json_get(pResponse, "requests");
if (pRequests == NULL)
@@ -533,8 +537,13 @@ void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq }
if (bCleanContacts)
- for (int i = 0; i < arContacts.getCount(); i++)
- CallService(MS_DB_CONTACT_DELETE, (WPARAM)arContacts[i], 0);
+ for (int i = 0; i < arContacts.getCount(); i++) {
+ MCONTACT hContact = (MCONTACT)arContacts[i];
+ LONG userID = getDword(hContact, "ID", -1);
+ if (userID == m_myUserId || userID == VK_FEED_USER)
+ continue;
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+ }
arContacts.destroy();
}
@@ -568,7 +577,7 @@ void CVkProto::MarkMessagesRead(const MCONTACT hContact) if (!IsOnline())
return;
LONG userID = getDword(hContact, "ID", -1);
- if (userID == -1)
+ if (userID == -1 || userID == VK_FEED_USER)
return;
Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth)
@@ -1066,7 +1075,8 @@ INT_PTR __cdecl CVkProto::SvcSetListeningTo(WPARAM, LPARAM lParam) INT_PTR __cdecl CVkProto::SvcAddAsFriend(WPARAM hContact, LPARAM)
{
debugLogA("CVkProto::SvcAddAsFriend");
- if (!IsOnline())
+ LONG userID = getDword(hContact, "ID", -1);
+ if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
return 1;
CallContactService(hContact, PSS_AUTHREQUESTW, 0, (LPARAM)TranslateT("Please authorize me to add you to my friend list."));
return 0;
@@ -1076,7 +1086,7 @@ INT_PTR __cdecl CVkProto::SvcDeleteFriend(WPARAM hContact, LPARAM flag) {
debugLogA("CVkProto::SvcDeleteFriend");
LONG userID = getDword(hContact, "ID", -1);
- if (!IsOnline() ||(userID == -1))
+ if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
return 1;
CMString formatstr = TranslateT("Are you sure to delete %s from your friend list?"),
@@ -1131,7 +1141,7 @@ INT_PTR __cdecl CVkProto::SvcBanUser(WPARAM hContact, LPARAM) {
debugLogA("CVkProto::SvcBanUser");
LONG userID = getDword(hContact, "ID", -1);
- if (!IsOnline() || userID == -1)
+ if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
return 1;
CMStringA code;
@@ -1194,7 +1204,7 @@ INT_PTR __cdecl CVkProto::SvcReportAbuse(WPARAM hContact, LPARAM) {
debugLogA("CVkProto::SvcReportAbuse");
LONG userID = getDword(hContact, "ID", -1);
- if (!IsOnline() || userID == -1)
+ if (!IsOnline() || userID == -1 || userID == VK_FEED_USER)
return 1;
CMString formatstr = TranslateT("Are you sure to report abuse on %s?"),
diff --git a/protocols/VKontakte/vk_10.vcxproj b/protocols/VKontakte/vk_10.vcxproj index 6fc27a66be..3fe519c80d 100644 --- a/protocols/VKontakte/vk_10.vcxproj +++ b/protocols/VKontakte/vk_10.vcxproj @@ -183,6 +183,7 @@ <ClCompile Include="src\vk_avatars.cpp" />
<ClCompile Include="src\vk_captcha.cpp" />
<ClCompile Include="src\vk_chats.cpp" />
+ <ClCompile Include="src\vk_feed.cpp" />
<ClCompile Include="src\vk_files.cpp" />
<ClCompile Include="src\vk_history.cpp" />
<ClCompile Include="src\vk_options.cpp" />
diff --git a/protocols/VKontakte/vk_10.vcxproj.filters b/protocols/VKontakte/vk_10.vcxproj.filters index 13f571045a..252f7625db 100644 --- a/protocols/VKontakte/vk_10.vcxproj.filters +++ b/protocols/VKontakte/vk_10.vcxproj.filters @@ -57,6 +57,9 @@ <ClCompile Include="src\vk_history.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_feed.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\version.h">
diff --git a/protocols/VKontakte/vk_12.vcxproj b/protocols/VKontakte/vk_12.vcxproj index ec614a89a8..aaf94fb2e4 100644 --- a/protocols/VKontakte/vk_12.vcxproj +++ b/protocols/VKontakte/vk_12.vcxproj @@ -193,6 +193,7 @@ <ClCompile Include="src\vk_search.cpp" />
<ClCompile Include="src\vk_thread.cpp" />
<ClCompile Include="src\vk_history.cpp" />
+ <ClCompile Include="src\vk_feed.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h" />
diff --git a/protocols/VKontakte/vk_12.vcxproj.filters b/protocols/VKontakte/vk_12.vcxproj.filters index 61165d6b0e..6ce39b7884 100644 --- a/protocols/VKontakte/vk_12.vcxproj.filters +++ b/protocols/VKontakte/vk_12.vcxproj.filters @@ -33,9 +33,6 @@ <ClCompile Include="src\misc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\vk_thread.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="src\vk_queue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -57,6 +54,12 @@ <ClCompile Include="src\vk_history.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_thread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\vk_feed.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\version.h">
|