From 83f57f5092fd96fef29fd2784ed5d7701b52378b Mon Sep 17 00:00:00 2001 From: Tobias Weimer Date: Wed, 7 Nov 2012 20:49:14 +0000 Subject: Merged with original Twitter: v1.1.0.0 - fixed some memory leaks (thx borkra) - fixed up some API v1.1 preferences - avatars now work for users that tweet - fixed the retweet truncation issue finally (properly this time), i test for the "retweeted_status" attribute now instead of flailing around blindly. git-svn-id: http://svn.miranda-ng.org/main/trunk@2239 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Twitter/src/connection.cpp | 27 ++++++++------- protocols/Twitter/src/contacts.cpp | 3 +- protocols/Twitter/src/proto.cpp | 26 ++++++-------- protocols/Twitter/src/proto.h | 3 -- protocols/Twitter/src/theme.cpp | 6 ++-- protocols/Twitter/src/twitter.cpp | 67 +++++++++++++++--------------------- protocols/Twitter/src/ui.cpp | 2 +- protocols/Twitter/src/utility.cpp | 17 +++++---- protocols/Twitter/src/utility.h | 4 +-- protocols/Twitter/src/version.h | 4 +-- 10 files changed, 71 insertions(+), 88 deletions(-) diff --git a/protocols/Twitter/src/connection.cpp b/protocols/Twitter/src/connection.cpp index de78419936..443bddc77f 100644 --- a/protocols/Twitter/src/connection.cpp +++ b/protocols/Twitter/src/connection.cpp @@ -137,7 +137,10 @@ bool TwitterProto::NegotiateConnection() // twitter changed the base URL in v1.1 of the API, I don't think users will need to modify it, so // i'll be forcing it to the new API URL here. After a while I can get rid of this as users will // have either had this run at least once, or have reset their miranda profile. 14/10/2012 - DBWriteContactSettingString(0,m_szModuleName,TWITTER_KEY_BASEURL,"https://api.twitter.com/"); + if(DBGetContactSettingByte(0,m_szModuleName,"UpgradeBaseURL",1)) { + DBWriteContactSettingString(0,m_szModuleName,TWITTER_KEY_BASEURL,"https://api.twitter.com/"); + DBWriteContactSettingByte(0,m_szModuleName,"UpgradeBaseURL",0); + } if((oauthToken.size() <= 1) || (oauthTokenSecret.size() <= 1)) { // first, reset all the keys so we can start fresh @@ -380,16 +383,16 @@ void TwitterProto::MessageLoop(void*) { if(m_iStatus != ID_STATUS_ONLINE) - goto exit; - if(i%10 == 0) - UpdateFriends(); + break; +// if(i%10 == 0) +// UpdateFriends(); if(m_iStatus != ID_STATUS_ONLINE) - goto exit; + break; UpdateStatuses(new_account,popups, tweetToMsg); if(m_iStatus != ID_STATUS_ONLINE) - goto exit; + break; if(i%10 == 0) UpdateMessages(new_account); @@ -401,16 +404,15 @@ void TwitterProto::MessageLoop(void*) } if(m_iStatus != ID_STATUS_ONLINE) - goto exit; + break; LOG( _T("***** TwitterProto::MessageLoop going to sleep...")); if(SleepEx(poll_rate*1000,true) == WAIT_IO_COMPLETION) - goto exit; + break; LOG( _T("***** TwitterProto::MessageLoop waking up...")); popups = true; } -exit: { ScopedLock s(twitter_lock_); twit_.set_credentials("",L"",L"",L"",L"",L"", false); @@ -431,7 +433,7 @@ void TwitterProto::UpdateAvatarWorker(void *p) if(p == 0) return; std::auto_ptr data( static_cast(p)); - DBVARIANT dbv; + DBVARIANT dbv = {0}; // DBGetContactSettingString returns 0 when it suceeds, so if this suceeds it will return 0, or false. // therefore if it returns 1, or true, we want to return as there is no such user. @@ -478,7 +480,7 @@ void TwitterProto::UpdateAvatarWorker(void *p) void TwitterProto::UpdateAvatar(HANDLE hContact,const std::string &url,bool force) { - DBVARIANT dbv; + DBVARIANT dbv = {0}; if( !force && ( !DBGetContactSettingString(hContact,m_szModuleName,TWITTER_KEY_AV_URL,&dbv) && @@ -571,7 +573,7 @@ void TwitterProto::ShowContactPopup(HANDLE hContact,const std::string &text) } mbcs_to_tcs(CP_UTF8,text.c_str(),popup.lptzText,MAX_SECONDLINE); - CallService(MS_POPUP_ADDPOPUPT,reinterpret_cast(&popup),0); + PUAddPopUpT(&popup); } void TwitterProto::UpdateStatuses(bool pre_read, bool popups, bool tweetToMsg) @@ -595,6 +597,7 @@ void TwitterProto::UpdateStatuses(bool pre_read, bool popups, bool tweetToMsg) continue; HANDLE hContact = AddToClientList(i->username.c_str(),""); + UpdateAvatar(hContact,i->profile_image_url); // as UpdateFriends() doesn't work at the moment, i'm going to update the avatars here // i think we maybe should just do that DBEF_READ line instead of stopping ALL this code. have to test. if (tweetToMsg) { diff --git a/protocols/Twitter/src/contacts.cpp b/protocols/Twitter/src/contacts.cpp index fcceb6881c..902f485ea2 100644 --- a/protocols/Twitter/src/contacts.cpp +++ b/protocols/Twitter/src/contacts.cpp @@ -114,7 +114,7 @@ void TwitterProto::DoSearch(void *p) twitter_user info; PROTOSEARCHRESULT psr = {sizeof(psr)}; - bool found; + bool found = false; try { char* p = mir_utf8encodeT( query->query.c_str()); @@ -131,6 +131,7 @@ void TwitterProto::DoSearch(void *p) ShowPopup( (std::string("While searching for contacts, an error occurred: ") +e.what()).c_str()); LOG( _T("***** Error searching for contacts: %s"), e.what()); + found = false; } if(found) { diff --git a/protocols/Twitter/src/proto.cpp b/protocols/Twitter/src/proto.cpp index 0a43711390..93f7e55919 100644 --- a/protocols/Twitter/src/proto.cpp +++ b/protocols/Twitter/src/proto.cpp @@ -79,14 +79,7 @@ TwitterProto::TwitterProto(const char *proto_name,const TCHAR *username) ConsumerKey = OAUTH_CONSUMER_KEY; ConsumerSecret = OAUTH_CONSUMER_SECRET; - //codebrook's keys - //wstring ConsumerKey = L"T6XLGzrkfsJAgU59dbIjSA"; - //wstring ConsumerSecret = L"xsvm2NAksjsJGw63RMWAtec3Lz5uiBusfVt48gbdKLg"; - - AccessUrl = _T("http://api.twitter.com/oauth/access_token"); AuthorizeUrl = _T("http://api.twitter.com/oauth/authorize?oauth_token=%s"); - RequestUrl = _T("http://api.twitter.com/oauth/request_token?some_other_parameter=hello&another_one=goodbye#meep"); // threw in some parameters for fun, and to test UrlGetQuery - UserTimelineUrl = _T("http://twitter.com/statuses/user_timeline.json"); } TwitterProto::~TwitterProto() @@ -147,7 +140,8 @@ HICON TwitterProto::GetIcon(int index) int TwitterProto::RecvMsg(HANDLE hContact,PROTORECVEVENT *pre) { - return Proto_RecvMessage(hContact, pre); + Proto_RecvMessage(hContact, pre); + return 0; } // ************************* @@ -336,7 +330,7 @@ int TwitterProto::OnBuildStatusMenu(WPARAM wParam,LPARAM lParam) mi.pszService = text; mi.hParentMenu = hRoot; - mi.flags = CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE; + mi.flags = CMIF_ICONFROMICOLIB|CMIF_ROOTHANDLE|CMIF_TCHAR; mi.position = 1001; HANDLE m_hMenuRoot = Menu_AddStatusMenuItem(&mi); @@ -345,7 +339,7 @@ int TwitterProto::OnBuildStatusMenu(WPARAM wParam,LPARAM lParam) // "Send Tweet..." CreateProtoService(m_szModuleName,"/Tweet",&TwitterProto::OnTweet,this); strcpy(tDest,"/Tweet"); - mi.pszName = LPGEN("Send Tweet..."); + mi.ptszName = LPGENT("Send Tweet..."); mi.popupPosition = 200001; mi.icolibItem = GetIconHandle("tweet"); HANDLE m_hMenuBookmarks = Menu_AddStatusMenuItem(&mi); @@ -384,7 +378,7 @@ int TwitterProto::OnTweet(WPARAM wParam,LPARAM lParam) return 1; HWND hDlg = CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_TWEET), - (HWND)0,tweet_proc,reinterpret_cast(this)); + 0,tweet_proc,reinterpret_cast(this)); ShowWindow(hDlg,SW_SHOW); return 0; } @@ -401,7 +395,7 @@ int TwitterProto::OnModulesLoaded(WPARAM wParam,LPARAM lParam) nlu.ptszDescriptiveName = descr; hNetlib_ = (HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); if(hNetlib_ == 0) - MessageBoxA(0,"Unable to get Netlib connection for Twitter","",0); + MessageBox(0,_T("Unable to get Netlib connection for Twitter"),_T("Twitter"),0); // Create avatar network connection (TODO: probably remove this) char module[512]; @@ -411,7 +405,7 @@ int TwitterProto::OnModulesLoaded(WPARAM wParam,LPARAM lParam) nlu.ptszDescriptiveName = descr; hAvatarNetlib_ = (HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu); if(hAvatarNetlib_ == 0) - MessageBoxA(0,"Unable to get avatar Netlib connection for Twitter","",0); + MessageBox(0,_T("Unable to get avatar Netlib connection for Twitter"),_T("Twitter"),0); twit_.set_handle(hNetlib_); @@ -468,7 +462,7 @@ int TwitterProto::OnPrebuildContactMenu(WPARAM wParam,LPARAM lParam) int TwitterProto::ShowPinDialog() { HWND hDlg = (HWND)DialogBoxParam(g_hInstance,MAKEINTRESOURCE(IDD_TWITTERPIN), - (HWND)0,pin_proc,reinterpret_cast(this)); + 0,pin_proc,reinterpret_cast(this)); ShowWindow(hDlg,SW_SHOW); return 0; } @@ -486,7 +480,7 @@ void TwitterProto::ShowPopup(const wchar_t *text, int Error) } if(ServiceExists(MS_POPUP_ADDPOPUPT)) - CallService(MS_POPUP_ADDPOPUPT,reinterpret_cast(&popup),0); + PUAddPopUpT(&popup); else MessageBox(0,popup.lptzText,popup.lptzContactName,0); } @@ -503,7 +497,7 @@ void TwitterProto::ShowPopup(const char *text, int Error) } if(ServiceExists(MS_POPUP_ADDPOPUPT)) - CallService(MS_POPUP_ADDPOPUPT,reinterpret_cast(&popup),0); + PUAddPopUpT(&popup); else MessageBox(0,popup.lptzText,popup.lptzContactName,0); } diff --git a/protocols/Twitter/src/proto.h b/protocols/Twitter/src/proto.h index 31acca9768..0aa4920f83 100644 --- a/protocols/Twitter/src/proto.h +++ b/protocols/Twitter/src/proto.h @@ -174,10 +174,7 @@ private: wstring ConsumerSecret; // various twitter api URLs - wstring AccessUrl; wstring AuthorizeUrl; - wstring RequestUrl; - wstring UserTimelineUrl; }; // TODO: remove this diff --git a/protocols/Twitter/src/theme.cpp b/protocols/Twitter/src/theme.cpp index 1dc7e1cc78..82df5563b0 100644 --- a/protocols/Twitter/src/theme.cpp +++ b/protocols/Twitter/src/theme.cpp @@ -135,18 +135,18 @@ void InitContactMenus() PrebuildContactMenu); CLISTMENUITEM mi = {sizeof(mi)}; - mi.flags = CMIF_NOTOFFLINE | CMIF_ICONFROMICOLIB; + mi.flags = CMIF_NOTOFFLINE | CMIF_ICONFROMICOLIB | CMIF_TCHAR; mi.position=-2000006000; mi.icolibItem = GetIconHandle("reply"); - mi.pszName = LPGEN("Reply..."); + mi.ptszName = LPGENT("Reply..."); mi.pszService = "Twitter/ReplyToTweet"; g_hMenuEvts[1] = CreateServiceFunction(mi.pszService, GlobalService<&TwitterProto::ReplyToTweet>); g_hMenuItems[0] = Menu_AddContactMenuItem(&mi); mi.position=-2000006000; mi.icolibItem = GetIconHandle("homepage"); - mi.pszName = LPGEN("Visit Homepage"); + mi.ptszName = LPGENT("Visit Homepage"); mi.pszService = "Twitter/VisitHomepage"; g_hMenuEvts[2] = CreateServiceFunction(mi.pszService, GlobalService<&TwitterProto::VisitHomepage>); diff --git a/protocols/Twitter/src/twitter.cpp b/protocols/Twitter/src/twitter.cpp index f5c3d1a8b3..ffba858f7a 100644 --- a/protocols/Twitter/src/twitter.cpp +++ b/protocols/Twitter/src/twitter.cpp @@ -349,53 +349,42 @@ std::vector twitter::get_statuses(int count,twitter_id id) { const js::object &one = boost::any_cast(**i); const js::object &user = retrieve(one,"user"); - //size_t RTcount = retrieve(one,"retweet_count", true); // why doesn't this work?? it can't cast the output into an int even though twitter api says it's an int twitter_user u; u.username = retrieve(user,"screen_name"); - - std::string rawText = retrieve(one,"text"); - bool foundTruncatedRT = false; - if (rawText.length() == 140) { // might be a truncated tweet - if (rawText.substr(0, 4) == "RT @") { // starting to look like a RT... - if (rawText.substr(136, 4) == " ...") { // ok this is the best I can do. it starts with "RT @", ends with " ...", and is the full 140 chars - - - //if (RTcount > 0) { // the tweet will be truncated unless we take action. i hate you twitter API - //MessageBox(NULL, L"retweeted: TRUE", L"long tweets", MB_OK); - // here we grab the "retweeted_status" um.. section? it's in here that all the info we need is - // at this point the user will get no tweets and an error popup if the tweet happens to be exactly 140 chars, start with - // "RT @", end in " ...", and notactually be a real retweet. it's possible but unlikely, wish i knew how to get - // the retweet_count variable to work :( - const js::object &Retweet = retrieve(one,"retweeted_status"); - const js::object &RTUser = retrieve(Retweet,"user"); - - std::string retweeteesName = retrieve(RTUser,"screen_name"); // the user that is being retweeted - std::string retweetText = retrieve(Retweet,"text"); // their tweet in all it's untruncated glory - - // fix "&" in the tweets :( - size_t pos = 0; - while((pos = retweetText.find("&", pos)) != std::string::npos) { - retweetText.replace(pos, 5, "&"); - pos += 1; - } - - u.status.text = "RT @" + retweeteesName + " " + retweetText; // mash it together in some format people will understand - foundTruncatedRT = true; - } + u.profile_image_url = retrieve(user,"profile_image_url"); + + // the tweet will be truncated unless we take action. i hate you twitter API + if(one.find("retweeted_status") != one.end()) + { + //MessageBox(NULL, L"retweeted: TRUE", L"long tweets", MB_OK); + // here we grab the "retweeted_status" um.. section? it's in here that all the info we need is + // at this point the user will get no tweets and an error popup if the tweet happens to be exactly 140 chars, start with + // "RT @", end in " ...", and notactually be a real retweet. it's possible but unlikely, wish i knew how to get + // the retweet_count variable to work :( + const js::object &Retweet = retrieve(one,"retweeted_status"); + const js::object &RTUser = retrieve(Retweet,"user"); + + std::string retweeteesName = retrieve(RTUser,"screen_name"); // the user that is being retweeted + std::string retweetText = retrieve(Retweet,"text"); // their tweet in all it's untruncated glory + + // fix "&" in the tweets :( + for(size_t pos = 0;(pos = retweetText.find("&", pos)) != std::string::npos;pos++) + { + retweetText.replace(pos, 5, "&"); } - } - - if (foundTruncatedRT == false) { // if it's not truncated, then the twitter API returns the native RT correctly anyway, - - //std::string twt = retrieve(one,"text"); // no need to do this anymore, we already grabbed it above in rawText + u.status.text = "RT @" + retweeteesName + " " + retweetText; // mash it together in some format people will understand + } + else + { + // if it's not truncated, then the twitter API returns the native RT correctly anyway, + std::string rawText = retrieve(one,"text"); // ok here i'm trying some way to fix all the "&" things that are showing up // i dunno why it's happening, so i'll just find and replace each occurance :/ - size_t pos = 0; - while((pos = rawText.find("&", pos)) != std::string::npos) { + for(size_t pos = 0;(pos = rawText.find("&", pos)) != std::string::npos;pos++) + { rawText.replace(pos, 5, "&"); - pos += 1; } u.status.text = rawText; diff --git a/protocols/Twitter/src/ui.cpp b/protocols/Twitter/src/ui.cpp index 2d1c0feb4f..ada3fd5ae5 100644 --- a/protocols/Twitter/src/ui.cpp +++ b/protocols/Twitter/src/ui.cpp @@ -414,7 +414,7 @@ namespace popup_options popup.colorText = get_text_color(hwndDlg,false); popup.colorBack = get_back_color(hwndDlg,false); - CallService(MS_POPUP_ADDPOPUPT,reinterpret_cast(&popup),0); + PUAddPopUpT(&popup); } } diff --git a/protocols/Twitter/src/utility.cpp b/protocols/Twitter/src/utility.cpp index 090bfebf09..f82b2bc64a 100644 --- a/protocols/Twitter/src/utility.cpp +++ b/protocols/Twitter/src/utility.cpp @@ -38,7 +38,6 @@ http::response mir_twitter::slurp(const std::string &url,http::method meth, OAuthParameters postParams) { NETLIBHTTPREQUEST req = {sizeof(req)}; - NETLIBHTTPREQUEST *resp; req.requestType = (meth == http::get) ? REQUEST_GET:REQUEST_POST; req.szUrl = const_cast(url.c_str()); @@ -131,7 +130,7 @@ http::response mir_twitter::slurp(const std::string &url,http::method meth, req.nlc = httpPOST_; http::response resp_data; LOG("**SLURP - just before calling HTTPTRANSACTION"); - resp = reinterpret_cast(CallService( MS_NETLIB_HTTPTRANSACTION, + NETLIBHTTPREQUEST *resp = reinterpret_cast(CallService( MS_NETLIB_HTTPTRANSACTION, reinterpret_cast(handle_), reinterpret_cast(&req))); LOG("**SLURP - HTTPTRANSACTION complete."); if(resp) @@ -151,7 +150,7 @@ http::response mir_twitter::slurp(const std::string &url,http::method meth, return resp_data; } -int mir_twitter::LOG(const char *fmt,...) +INT_PTR mir_twitter::LOG(const char *fmt,...) { va_list va; char text[1024]; @@ -162,10 +161,10 @@ int mir_twitter::LOG(const char *fmt,...) mir_vsnprintf(text,sizeof(text),fmt,va); va_end(va); - return (int)CallService(MS_NETLIB_LOG,(WPARAM)handle_,(LPARAM)text); + return CallService(MS_NETLIB_LOG,(WPARAM)handle_,(LPARAM)text); } -int mir_twitter::WLOG(const char* first, const std::wstring last) +INT_PTR mir_twitter::WLOG(const char* first, const std::wstring last) { char *str1 = new char[1024*96]; sprintf(str1,"%ls", last.c_str()); @@ -176,17 +175,17 @@ int mir_twitter::WLOG(const char* first, const std::wstring last) bool save_url(HANDLE hNetlib,const std::string &url,const std::tstring &filename) { NETLIBHTTPREQUEST req = {sizeof(req)}; - NETLIBHTTPREQUEST *resp; req.requestType = REQUEST_GET; req.flags = NLHRF_HTTP11 | NLHRF_REDIRECT; req.szUrl = const_cast(url.c_str()); - resp = reinterpret_cast(CallService( MS_NETLIB_HTTPTRANSACTION, + NETLIBHTTPREQUEST *resp = reinterpret_cast(CallService( MS_NETLIB_HTTPTRANSACTION, reinterpret_cast(hNetlib), reinterpret_cast(&req))); if (resp) { - if (resp->resultCode == 200) + bool success = (resp->resultCode == 200); + if (success) { // Create folder if necessary std::tstring dir = filename.substr(0,filename.rfind('\\')); @@ -200,7 +199,7 @@ bool save_url(HANDLE hNetlib,const std::string &url,const std::tstring &filename } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)resp); - return resp->resultCode == 200; + return success; } else return false; diff --git a/protocols/Twitter/src/utility.h b/protocols/Twitter/src/utility.h index a8823291d1..bc94561274 100644 --- a/protocols/Twitter/src/utility.h +++ b/protocols/Twitter/src/utility.h @@ -111,8 +111,8 @@ public: protected: http::response slurp(const std::string &,http::method, OAuthParameters ); - int LOG(const char *fmt,...); - int WLOG(const char* first, const std::wstring last); + INT_PTR LOG(const char *fmt,...); + INT_PTR WLOG(const char* first, const std::wstring last); HANDLE httpPOST_; HANDLE handle_; diff --git a/protocols/Twitter/src/version.h b/protocols/Twitter/src/version.h index d3d3f6e21d..4b9b118193 100644 --- a/protocols/Twitter/src/version.h +++ b/protocols/Twitter/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 1 -#define __MINOR_VERSION 0 +#define __MINOR_VERSION 1 #define __RELEASE_NUM 0 -#define __BUILD_NUM 3 +#define __BUILD_NUM 0 #define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM #define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM -- cgit v1.2.3