int CVkProto::OnChatEvent(WPARAM, LPARAM lParam) { GCHOOK *gch = (GCHOOK*)lParam; if (gch == NULL) return 0; if (lstrcmpiA(gch->pDest->pszModule, m_szModuleName)) return 0; CVkChatInfo *cc = GetChatById(gch->pDest->ptszID); if (cc == NULL) return 0; switch (gch->pDest->iType) { case GC_USER_MESSAGE: if (m_bOnline && lstrlen(gch->ptszText) > 0) { TCHAR *buf = NEWTSTR_ALLOCA(gch->ptszText); rtrimt(buf); UnEscapeChatTags(buf); Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg) << INT_PARAM("type", 1) << INT_PARAM("chat_id", cc->m_chatid) << TCHAR_PARAM("message", buf)); } case GC_USER_LOGMENU: LogMenuHook(cc, gch); break; case GC_USER_NICKLISTMENU: NickMenuHook(cc, gch); break; } return 0; }
int CVkProto::SendMsg(HANDLE hContact, int flags, const char *msg) { LONG userID = getDword(hContact, "ID", -1); if (userID == -1) return 0; ptrA szMsg; if (flags & PREF_UTF) szMsg = mir_strdup(msg); else if (flags & PREF_UNICODE) msg = mir_utf8encodeW((wchar_t*)&msg[strlen(msg)+1]); else msg = mir_utf8encode(msg); ULONG msgId = ::InterlockedIncrement(&m_msgId); AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendMessage) << INT_PARAM("type", 0) << INT_PARAM("uid", userID) << CHAR_PARAM("message", msg); pReq->pData = (char*)hContact; pReq->pUserInfo = (void*)msgId; Push(pReq); if (!m_bServerDelivery) ForkThread(&CVkProto::SendMsgAck, new TFakeAckParams(hContact, msgId)); return msgId; }
void CVkProto::LogMenuHook(CVkChatInfo *cc, GCHOOK *gch) { HANDLE hContact; switch (gch->dwData) { case IDM_TOPIC: if (LPTSTR ptszNew = ChangeChatTopic(cc)) { Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.editChat.json", true, &CVkProto::OnReceiveSmth) << TCHAR_PARAM("title", ptszNew) << INT_PARAM("chat_id", cc->m_chatid)); mir_free(ptszNew); } break; case IDM_INVITE: hContact = (HANDLE)DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INVITE), NULL, InviteDlgProc, (LPARAM)this); if (hContact != NULL) { int uid = getDword(hContact, "ID", -1); if (uid != -1) Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.addChatUser.json", true, &CVkProto::OnReceiveSmth) << INT_PARAM("uid", uid) << INT_PARAM("chat_id", cc->m_chatid)); } break; case IDM_DESTROY: if (IDYES == MessageBox(NULL, TranslateT("This chat is going to be destroyed forever with all its contents. This action cannot be undone. Are you sure?"), TranslateT("Warning"), MB_YESNOCANCEL | MB_ICONQUESTION)) { Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.deleteDialog.json", true, &CVkProto::OnChatDestroy) << INT_PARAM("chat_id", cc->m_chatid))->pUserInfo = cc; } break; } }
void CVkProto::RetrieveUnreadNews(time_t tLastNewsTime) { debugLogA("CVkProto::RetrieveUnreadNews"); if (!IsOnline()) return; time_t tLastNewsReqTime = getDword("LastNewsReqTime", time(NULL) - 24 * 60 * 60); if (time(NULL) - tLastNewsReqTime < 3 * 60) return; CMStringA szFilter; szFilter = m_bNewsFilterPosts ? "post" : ""; szFilter += szFilter.IsEmpty() ? "" : ","; szFilter += m_bNewsFilterPhotos ? "photo" : ""; szFilter += szFilter.IsEmpty() ? "" : ","; szFilter += m_bNewsFilterTags ? "photo_tag" : ""; szFilter += szFilter.IsEmpty() ? "" : ","; szFilter += m_bNewsFilterWallPhotos ? "wall_photo" : ""; if (szFilter.IsEmpty()) { debugLogA("CVkProto::RetrieveUnreadNews szFilter empty"); return; } CMStringA szSource; szSource = m_bNewsSourceFriends ? "friends" : ""; szSource += szSource.IsEmpty() ? "" : ","; szSource += m_bNewsSourceGroups ? "groups" : ""; szSource += szSource.IsEmpty() ? "" : ","; szSource += m_bNewsSourcePages ? "pages" : ""; szSource += szSource.IsEmpty() ? "" : ","; szSource += m_bNewsSourceFollowing ? "following" : ""; if (szSource.IsEmpty()) { debugLogA("CVkProto::RetrieveUnreadNews szSource empty"); return; } Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/newsfeed.get.json", true, &CVkProto::OnReceiveUnreadNews)) << INT_PARAM("count", 100) << INT_PARAM("return_banned", m_bNewsSourceIncludeBanned ? 1 : 0) << INT_PARAM("max_photos", m_iMaxLoadNewsPhoto) << INT_PARAM("start_time", tLastNewsTime + 1) << CHAR_PARAM("filters", szFilter) << CHAR_PARAM("source_ids", szSource) << VER_API; setDword("LastNewsReqTime", (DWORD)time(NULL)); }
int CVkProto::SendMsg(MCONTACT hContact, int, const char *szMsg) { debugLogA("CVkProto::SendMsg"); if (!IsOnline()) return 0; bool bIsChat = isChatRoom(hContact); LONG iUserID = getDword(hContact, bIsChat ? "vk_chat_id" : "ID" , -1); if (iUserID == -1 || iUserID == VK_FEED_USER) { ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact)); return 0; } int StickerId = 0; ptrA pszRetMsg(GetStickerId(szMsg, StickerId)); ULONG uMsgId = ::InterlockedIncrement(&m_msgId); AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, bIsChat? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh) << INT_PARAM(bIsChat ? "chat_id" : "user_id", iUserID) << INT_PARAM("random_id", ((LONG) time(NULL)) * 100 + uMsgId % 100); pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); if (StickerId) pReq << INT_PARAM("sticker_id", StickerId); else { pReq << CHAR_PARAM("message", szMsg); if (m_vkOptions.bSendVKLinksAsAttachments) { CMStringA szAttachments = GetAttachmentsFromMessage(szMsg); if (!szAttachments.IsEmpty()) { debugLogA("CVkProto::SendMsg Attachments = %s", szAttachments); pReq << CHAR_PARAM("attachment", szAttachments); } } } if (!bIsChat) pReq->pUserInfo = new CVkSendMsgParam(hContact, uMsgId); Push(pReq); if (!m_bServerDelivery && !bIsChat) ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact, uMsgId)); if (!IsEmpty(pszRetMsg)) SendMsg(hContact, 0, pszRetMsg); return uMsgId; }
void CVkProto::RetrieveFriends() { debugLogA("CVkProto::RetrieveFriends"); Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends) << INT_PARAM("count", 1000) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,country,timezone,contacts")); }
void CVkProto::RetrieveUnreadMessages() { debugLogA("CVkProto::RetrieveUnreadMessages"); if (!IsOnline()) return; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getDialogs.json", true, &CVkProto::OnReceiveDlgs) << INT_PARAM ("count", 200)); }
void CVkProto::RetrievePollingInfo() { debugLogA("CVkProto::RetrievePollingInfo"); if (!IsOnline()) return; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getLongPollServer.json", true, &CVkProto::OnReceivePollingInfo, AsyncHttpRequest::rpHigh) << INT_PARAM("use_ssl", 1) << VER_API); }
void CVkProto::RetrieveFriends() { debugLogA("CVkProto::RetrieveFriends"); if (!IsOnline()) return; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends) << INT_PARAM("count", 1000) << CHAR_PARAM("fields", fieldsName) <<VER_API); }
void CVkProto::RetrieveFriends(bool bCleanNonFriendContacts) { debugLogA("CVkProto::RetrieveFriends"); if (!IsOnline()) return; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends) << INT_PARAM("count", 1000) << CHAR_PARAM("fields", fieldsName) << VER_API)->pUserInfo = new CVkSendMsgParam(NULL, bCleanNonFriendContacts ? 1 : 0); }
void CVkProto::MarkMessagesRead(const MCONTACT hContact) { debugLogA("CVkProto::MarkMessagesRead (hContact)"); if (!IsOnline() || !hContact) return; LONG userID = getDword(hContact, "ID", -1); if (userID == -1 || userID == VK_FEED_USER) return; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth, AsyncHttpRequest::rpLow) << INT_PARAM("peer_id", userID)); }
void CVkProto::WallPost(MCONTACT hContact, TCHAR *ptszMsg, TCHAR *ptszUrl, bool bFriendsOnly) { debugLogA("CVkProto::WallPost"); if (!IsOnline() || (IsEmpty(ptszMsg) && IsEmpty(ptszUrl))) return; LONG userID = hContact ? m_myUserId : getDword(hContact, "ID", -1); if (userID == -1 || userID == VK_FEED_USER) return; AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/wall.post.json", true, &CVkProto::OnReceiveSmth) << INT_PARAM("owner_id", userID) << INT_PARAM("friends_only", bFriendsOnly ? 1 : 0); if (!IsEmpty(ptszMsg)) pReq << TCHAR_PARAM("message", ptszMsg); if (!IsEmpty(ptszUrl)) pReq << TCHAR_PARAM("attachments", ptszUrl); Push(pReq); }
void CVkProto::NickMenuHook(CVkChatInfo *cc, GCHOOK *gch) { CVkChatUser* cu = cc->GetUserById(gch->ptszUID); if (cu == NULL) return; char szUid[20], szChatId[20]; _itoa(cu->m_uid, szUid, 10); _itoa(cc->m_chatid, szChatId, 10); switch (gch->dwData) { case IDM_INFO: if (HANDLE hContact = FindUser(cu->m_uid)) CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)hContact, 0); break; case IDM_KICK: Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.removeChatUser.json", true, &CVkProto::OnReceiveSmth) << INT_PARAM("chat_id", cc->m_chatid) << INT_PARAM("uid", cu->m_uid)); cu->m_bUnknown = true; break; } }
INT_PTR __cdecl CVkProto::SvcReportAbuse(WPARAM hContact, LPARAM) { debugLogA("CVkProto::SvcReportAbuse"); LONG userID = getDword(hContact, "ID", -1); if (!IsOnline() || userID == -1 || userID == VK_FEED_USER) return 1; CMString tszNick(ptrT(db_get_tsa(hContact, m_szModuleName, "Nick"))), ptszMsg(FORMAT, TranslateT("Are you sure to report abuse on %s?"), tszNick.IsEmpty() ? TranslateT("(Unknown contact)") : tszNick); if (IDNO == MessageBox(NULL, ptszMsg, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO)) return 1; Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/users.report.json", true, &CVkProto::OnReceiveSmth) << INT_PARAM("user_id", userID) << CHAR_PARAM("type", "spam") << VER_API); return 0; }
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() || userID == VK_FEED_USER) return 1; if (m_iMarkMessageReadOn == markOnTyping) MarkMessagesRead(hContact); Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.setActivity.json", true, &CVkProto::OnReceiveSmth, AsyncHttpRequest::rpLow) << INT_PARAM("user_id", userID) << CHAR_PARAM("type", "typing") << VER_API); return 0; } return 1; }
INT_PTR __cdecl CVkProto::SvcDeleteFriend(WPARAM hContact, LPARAM flag) { debugLogA("CVkProto::SvcDeleteFriend"); LONG userID = getDword(hContact, "ID", -1); if (!IsOnline() || userID == -1 || userID == VK_FEED_USER) return 1; ptrT ptszNick(db_get_tsa(hContact, m_szModuleName, "Nick")); CMString ptszMsg; if (flag == 0) { ptszMsg.AppendFormat(TranslateT("Are you sure to delete %s from your friend list?"), IsEmpty(ptszNick) ? TranslateT("(Unknown contact)") : ptszNick); if (IDNO == MessageBox(NULL, ptszMsg, TranslateT("Attention!"), MB_ICONWARNING | MB_YESNO)) return 1; } Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.delete.json", true, &CVkProto::OnReceiveDeleteFriend) << INT_PARAM("user_id", userID) << VER_API)->pUserInfo = new CVkSendMsgParam(hContact); return 0; }
int CVkProto::AuthRequest(MCONTACT hContact,const TCHAR* message) { debugLogA("CVkProto::AuthRequest"); if (!IsOnline()) return 1; LONG userID = getDword(hContact, "ID", -1); if (userID == -1 || !hContact || userID == VK_FEED_USER) return 1; TCHAR msg[501] = {0}; if (message) _tcsncpy_s(msg, 500, message, _TRUNCATE); Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.add.json", true, &CVkProto::OnReceiveAuthRequest) << INT_PARAM("user_id", userID) << TCHAR_PARAM("text", msg) << VER_API)->pUserInfo = new CVkSendMsgParam(hContact); return 0; }
void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { SendFileFiled(fup, VKERR_OFFLINE); return; } debugLogA("CVkProto::OnReciveUploadFile %d", reply->resultCode); if (reply->resultCode != 200) { SendFileFiled(fup, VKERR_FILE_NOT_UPLOADED); return; } JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse || pReq->m_iErrorCode) { SendFileFiled(fup, pReq->m_iErrorCode); return; } int id = fup->GetType() == CVkFileUploadParam::typeAudio ? jnResponse["id"].as_int() : (*jnResponse.begin())["id"].as_int(); int owner_id = fup->GetType() == CVkFileUploadParam::typeAudio ? jnResponse["owner_id"].as_int() : (*jnResponse.begin())["owner_id"].as_int(); if ((id == 0) || (owner_id == 0)) { SendFileFiled(fup, VKERR_INVALID_PARAMETERS); return; } CMString Attachment; switch (fup->GetType()) { case CVkFileUploadParam::typeImg: Attachment.AppendFormat(_T("photo%d_%d"), owner_id, id); break; case CVkFileUploadParam::typeAudio: Attachment.AppendFormat(_T("audio%d_%d"), owner_id, id); break; case CVkFileUploadParam::typeDoc: Attachment.AppendFormat(_T("doc%d_%d"), owner_id, id); break; default: SendFileFiled(fup, VKERR_FTYPE_NOT_SUPPORTED); return; } AsyncHttpRequest *pMsgReq; if (isChatRoom(fup->hContact)) { ptrT tszChatID(getTStringA(fup->hContact, "ChatRoomID")); if (!tszChatID) { SendFileFiled(fup, VKERR_INVALID_USER); return; } CVkChatInfo *cc = GetChatById(tszChatID); if (cc == NULL) { SendFileFiled(fup, VKERR_INVALID_USER); return; } pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh) << INT_PARAM("chat_id", cc->m_chatid); pMsgReq->pUserInfo = pReq->pUserInfo; } else { LONG userID = getDword(fup->hContact, "ID", -1); if (userID == -1 || userID == VK_FEED_USER) { SendFileFiled(fup, VKERR_INVALID_USER); return; } pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh) << INT_PARAM("user_id", userID); pMsgReq->pUserInfo = new CVkSendMsgParam(fup->hContact, fup); } pMsgReq << TCHAR_PARAM("message", fup->Desc) << TCHAR_PARAM("attachment", Attachment) << VER_API; pMsgReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); Push(pMsgReq); }
void CVkProto::WorkerThread(void*) { debugLogA("CVkProto::WorkerThread: entering"); m_bTerminated = m_prevError = false; m_szAccessToken = getStringA("AccessToken"); char Score[] = "friends,photos,audio,docs,video,wall,messages,offline,status,notifications,groups"; CMStringA szAccessScore(ptrA(getStringA("AccessScore"))); if (szAccessScore != Score) { setString("AccessScore", Score); delSetting("AccessToken"); m_szAccessToken = NULL; } if (m_szAccessToken != NULL) // try to receive a response from server RetrieveMyInfo(); else { // Initialize new OAuth session extern char szBlankUrl[]; AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "https://oauth.vk.com/authorize", false, &CVkProto::OnOAuthAuthorize) << INT_PARAM("client_id", VK_APP_ID) << CHAR_PARAM("scope", Score) << CHAR_PARAM("redirect_uri", szBlankUrl) << CHAR_PARAM("display", "mobile") << CHAR_PARAM("response_type", "token") << VER_API; pReq->m_bApiReq = false; pReq->bIsMainConn = true; Push(pReq); } m_hAPIConnection = NULL; while (true) { WaitForSingleObject(m_evRequestsQueue, 1000); if (m_bTerminated) break; AsyncHttpRequest *pReq; bool need_sleep = false; while (true) { { mir_cslock lck(m_csRequestsQueue); if (m_arRequestsQueue.getCount() == 0) break; pReq = m_arRequestsQueue[0]; m_arRequestsQueue.remove(0); need_sleep = (m_arRequestsQueue.getCount() > 1) && (pReq->m_bApiReq); // more than two to not gather } if (m_bTerminated) break; ExecuteRequest(pReq); if (need_sleep) { // There can be maximum 3 requests to API methods per second from a client Sleep(330); // (c) https://vk.com/dev/api_requests debugLogA("CVkProto::WorkerThread: need sleep"); } } } if (m_hAPIConnection) { debugLogA("CVkProto::WorkerThread: Netlib_CloseHandle(m_hAPIConnection) beg"); Netlib_CloseHandle(m_hAPIConnection); debugLogA("CVkProto::WorkerThread: Netlib_CloseHandle(m_hAPIConnection) end"); } m_hAPIConnection = NULL; m_hWorkerThread = 0; debugLogA("CVkProto::WorkerThread: leaving m_bTerminated = %d", m_bTerminated ? 1 : 0); }
void CVkProto::RetrieveUserInfo(LONG userID) { Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo) << INT_PARAM("uids", userID) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,bdate,city,relation")); }
void SetupParams(int argc, char **argv) { char fname[STRLEN]; init_params(argc, argv); // PARAMETER DEFINITIONS GO HERE STRING_PARAM(FileBase); INT_PARAM(ElecNo); INT_PARAM(MinClusters); INT_PARAM(MaxClusters); INT_PARAM(MaxPossibleClusters); INT_PARAM(nStarts); INT_PARAM(RandomSeed); BOOLEAN_PARAM(Debug); INT_PARAM(Verbose); STRING_PARAM(UseFeatures); INT_PARAM(DistDump); FLOAT_PARAM(DistThresh); INT_PARAM(FullStepEvery); FLOAT_PARAM(ChangedThresh); BOOLEAN_PARAM(Log); BOOLEAN_PARAM(Screen); INT_PARAM(MaxIter); STRING_PARAM(StartCluFile); INT_PARAM(SplitEvery); FLOAT_PARAM(PenaltyMix); INT_PARAM(Subset); if (argc<3) { fprintf(stderr, "Usage: KlustaKwik FileBase ElecNo [Arguments]\n\n"); fprintf(stderr, "Default Parameters: \n"); print_params(stderr); exit(1); } strcpy(FileBase, argv[1]); ElecNo = atoi(argv[2]); if (Screen) print_params(stdout); // open log file, if required if (Log) { sprintf(fname, "%s.klg.%d", FileBase, ElecNo); logfp = fopen_safe(fname, "w"); print_params(logfp); } }