From a6fb825ecbf5313b010fd8cf37754f494cabddc5 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 5 Jun 2012 17:56:48 +0000 Subject: Twitter plugin git-svn-id: http://svn.miranda-ng.org/main/trunk@316 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Twitter/contacts.cpp | 288 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 plugins/Twitter/contacts.cpp (limited to 'plugins/Twitter/contacts.cpp') diff --git a/plugins/Twitter/contacts.cpp b/plugins/Twitter/contacts.cpp new file mode 100644 index 0000000000..03aad22601 --- /dev/null +++ b/plugins/Twitter/contacts.cpp @@ -0,0 +1,288 @@ +/* +Copyright © 2009 Jim Porter + +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, either version 2 of the License, or +(at your option) any later version. + +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 "common.h" +#include "proto.h" + + +void TwitterProto::AddToListWorker(void *p) +{ + // TODO: what happens if there is an error? + if (p == 0) + return; + TCHAR *name = static_cast(p); + + try + { + ScopedLock s(twitter_lock_); + twitter_user user = twit_.add_friend(name); + s.Unlock(); + + HANDLE hContact = UsernameToHContact(name); + UpdateAvatar(hContact, user.profile_image_url); + } + catch(const std::exception &e) + { + ShowPopup((std::string("While adding a friend, an error occurred: ") + +e.what()).c_str()); + LOG("***** Error adding friend: %s", e.what()); + } + mir_free(name); +} + +HANDLE TwitterProto::AddToList(int flags, PROTOSEARCHRESULT *result) +{ + if (m_iStatus != ID_STATUS_ONLINE) + return 0; + + ForkThread(&TwitterProto::AddToListWorker, this, mir_tstrdup(result->nick)); + return AddToClientList(result->nick, _T("")); +} + +// ************************* + +void TwitterProto::UpdateInfoWorker(void *hContact) +{ + twitter_user user; + std::tstring username; + + DBVARIANT dbv; + if ( !DBGetContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, &dbv)) + { + username = dbv.ptszVal; + DBFreeVariant(&dbv); + } + else + return; + + { + ScopedLock s(twitter_lock_); + twit_.get_info(username, &user); + } + + UpdateAvatar(hContact, user.profile_image_url, true); + ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, 0, 0); +} + +int TwitterProto::GetInfo(HANDLE hContact, int info_type) +{ + if (m_iStatus != ID_STATUS_ONLINE) + return 1; + + if (!IsMyContact(hContact)) // Do nothing for chat rooms + return 1; + + if (info_type == 0) // From clicking "Update" in the Userinfo dialog + { + ForkThread(&TwitterProto::UpdateInfoWorker, this, hContact); + return 0; + } + + return 1; +} + +// ************************* + +struct search_query +{ + search_query(const std::tstring &query, bool by_email) : query(query), by_email(by_email) + {} + std::tstring query; + bool by_email; +}; + +void TwitterProto::DoSearch(void *p) +{ + if (p == 0) + return; + search_query *query = static_cast(p); + + twitter_user info; + PROTOSEARCHRESULT psr = {sizeof(psr)}; + + bool found; + try + { + ScopedLock s(twitter_lock_); + if (query->by_email) + found = twit_.get_info_by_email(query->query, &info); + else + found = twit_.get_info(query->query, &info); + } + catch(const std::exception &e) + { + ShowPopup( (std::string("While searching for contacts, an error occurred: ") + +e.what()).c_str()); + LOG("***** Error searching for contacts: %s", e.what()); + } + + if (found) + { + psr.nick = ( TCHAR* )info.username. c_str(); + psr.firstName = ( TCHAR* )info.real_name.c_str(); + + ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, + (LPARAM)&psr); + ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0); + } + else + { + ProtoBroadcastAck(m_szModuleName, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0); + } + + delete query; +} + +HANDLE TwitterProto::SearchBasic(const TCHAR *username) +{ + ForkThread(&TwitterProto::DoSearch, this, new search_query(username, false)); + return (HANDLE)1; +} + +HANDLE TwitterProto::SearchByEmail(const TCHAR *email) +{ + ForkThread(&TwitterProto::DoSearch, this, new search_query(email, true)); + return (HANDLE)1; +} + +// ************************* + +void TwitterProto::GetAwayMsgWorker(void *hContact) +{ + if (hContact == 0) + return; + + DBVARIANT dbv; + if ( !DBGetContactSettingTString(hContact, "CList", "StatusMsg", &dbv)) { + ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)dbv.ptszVal); + DBFreeVariant(&dbv); + } + else ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_AWAYMSG, ACKRESULT_FAILED, (HANDLE)1, 0); +} + +HANDLE TwitterProto::GetAwayMsg(HANDLE hContact) +{ + ForkThread(&TwitterProto::GetAwayMsgWorker, this, hContact); + return (HANDLE)1; +} + +int TwitterProto::OnContactDeleted(WPARAM wParam, LPARAM lParam) +{ + if (m_iStatus != ID_STATUS_ONLINE) + return 0; + + const HANDLE hContact = reinterpret_cast(wParam); + + if (!IsMyContact(hContact)) + return 0; + + DBVARIANT dbv; + if ( !DBGetContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, &dbv)) { + if ( in_chat_ ) + DeleteChatContact(dbv.ptszVal); + + ScopedLock s(twitter_lock_); + twit_.remove_friend(dbv.ptszVal); // Be careful about this until Miranda is fixed + DBFreeVariant(&dbv); + } + return 0; +} + +// ************************* + +bool TwitterProto::IsMyContact(HANDLE hContact, bool include_chat) +{ + const char *proto = reinterpret_cast( CallService(MS_PROTO_GETCONTACTBASEPROTO, + reinterpret_cast(hContact), 0)); + + if (proto && strcmp(m_szModuleName, proto) == 0) + { + if (include_chat) + return true; + else + return DBGetContactSettingByte(hContact, m_szModuleName, "ChatRoom", 0) == 0; + } + else + return false; +} + +HANDLE TwitterProto::UsernameToHContact(const TCHAR *name) +{ + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + hContact; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + if (!IsMyContact(hContact)) + continue; + + DBVARIANT dbv; + if ( !DBGetContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, &dbv)) { + if ( lstrcmp(name, dbv.ptszVal) == 0) { + DBFreeVariant(&dbv); + return hContact; + } + DBFreeVariant(&dbv); + } + } + + return 0; +} + +HANDLE TwitterProto::AddToClientList(const TCHAR *name, const TCHAR *status) +{ + // First, check if this contact exists + HANDLE hContact = UsernameToHContact(name); + if (hContact) + return hContact; + + if (in_chat_) + AddChatContact(name); + + // If not, make a new contact! + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + if (hContact ) { + if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)m_szModuleName) == 0) { + DBWriteContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, name); + DBWriteContactSettingWord(hContact, m_szModuleName, "Status", ID_STATUS_ONLINE); + DBWriteContactSettingTString(hContact, "CList", "StatusMsg", status); + + std::string url = profile_base_url(twit_.get_base_url()) + http::url_encode((char*)_T2A(name)); + DBWriteContactSettingString(hContact, m_szModuleName, "Homepage", url.c_str()); + + return hContact; + } + + CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + } + + return 0; +} + +void TwitterProto::SetAllContactStatuses(int status) +{ + for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + hContact; + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + if (!IsMyContact(hContact)) + continue; + + DBWriteContactSettingWord(hContact, m_szModuleName, "Status", status); + } + + SetChatStatus(status); +} \ No newline at end of file -- cgit v1.2.3