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;
 +}
 | 
