From e94c705bb01c662d934c0096480bc9a732d0e1ec Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 19 Jan 2012 12:21:27 +0000 Subject: FacebookRM: Version bump Version 0.0.7.0 + Support for group chats (EXPERIMENTAL!) - enable it in options ! Fixed loading contact list ! Fixed potential freeze. Total downloads: (None or statistics not available yet) Version 0.0.6.1a Reuploaded. Total downloads: (None or statistics not available yet) Version 0.0.6.1 + Returned option to close chat windows (on website) + New option to map non-standard statuses to Invisible (insetad of Online) + New option to load contacts, which have "On the Phone" status ! Fixed changing chat visibility ! Very long messages are no longer received duplicitely ! Changes and fixes related to multiuser messages and messages from people, which are not in server-list Total downloads: (None or statistics not available yet) git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@261 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- FacebookRM/json.cpp | 248 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 206 insertions(+), 42 deletions(-) (limited to 'FacebookRM/json.cpp') diff --git a/FacebookRM/json.cpp b/FacebookRM/json.cpp index 1c57f00..bd69c75 100644 --- a/FacebookRM/json.cpp +++ b/FacebookRM/json.cpp @@ -62,8 +62,32 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use i->data->status_id = ID_STATUS_OFFLINE; } - const Object& nowAvailableList = objRoot["payload"]["buddy_list"]["nowAvailableList"]; + // Find mobile friends + if (DBGetContactSettingByte(NULL,proto->m_szModuleName,FACEBOOK_KEY_LOAD_MOBILE, DEFAULT_LOAD_MOBILE)) { + const Array& mobileFriends = objRoot["payload"]["buddy_list"]["mobile_friends"]; + + for ( Array::const_iterator buddy( mobileFriends.Begin() ); buddy != mobileFriends.End(); ++buddy) { + const Number& member = *buddy; + char was_id[32]; + lltoa( member.Value(), was_id, 10 ); + + std::string id = was_id; + if (!id.empty()) { + current = buddy_list->find( id ); + + if ( current == NULL) { + buddy_list->insert( std::make_pair( id, new facebook_user( ) ) ); + current = buddy_list->find( id ); + current->user_id = id; + } + + current->status_id = ID_STATUS_ONTHEPHONE; + } + } + } + const Object& nowAvailableList = objRoot["payload"]["buddy_list"]["nowAvailableList"]; + // Find now awailable contacts for (Object::const_iterator itAvailable(nowAvailableList.Begin()); itAvailable != nowAvailableList.End(); ++itAvailable) { @@ -78,13 +102,13 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use buddy_list->insert( std::make_pair( member.name, new facebook_user( ) ) ); current = buddy_list->find( member.name ); current->user_id = current->real_name = member.name; - } + } current->status_id = (idle ? ID_STATUS_OFFLINE : ID_STATUS_ONLINE); } const Object& userInfosList = objRoot["payload"]["buddy_list"]["userInfos"]; - + // Get aditional informations about contacts (if available) for (Object::const_iterator itUserInfo(userInfosList.Begin()); itUserInfo != userInfosList.End(); ++itUserInfo) { @@ -121,6 +145,83 @@ int facebook_json_parser::parse_buddy_list( void* data, List::List< facebook_use return EXIT_SUCCESS; } +int facebook_json_parser::parse_facepiles( void* data, std::map< std::string, std::string > *facepiles ) +{ + using namespace json; + + try + { + std::string buddyData = static_cast< std::string* >( data )->substr( 9 ); + std::istringstream sDocument( buddyData ); + Object objDocument; + Reader::Read(objDocument, sDocument); + std::map< std::string, std::string >::iterator it; + + const Object& objRoot = objDocument; +/* const Array& infos = objRoot["payload"]["facepile_click_info"]; + + for ( Array::const_iterator info( infos.Begin() ); + info != infos.End(); ++info) + { + const Object& objMember = *info; + + if (objMember.Find("uid") != objMember.End()) { + const Number& id = objMember["uid"]; + char was_id[32]; + lltoa( id.Value(), was_id, 10 ); + + const String& name = objMember["name"]; + std::string user_name = utils::text::slashu_to_utf8( + utils::text::special_expressions_decode( name.Value() ) ); + + it = facepiles->find( std::string( was_id ) ); + if ( it == facepiles->end() ) { + facepiles->insert( std::make_pair( was_id, user_name ) ); + } + } + } */ + + // Contacts in chat are getting by parsing html response. Don't know if it will work also for many people in chat room. + const String& response_html = objRoot["payload"]["response_html"]; + std::string contacts = utils::text::slashu_to_utf8( utils::text::special_expressions_decode( response_html.Value( ) ) ); + + std::string::size_type pos = 0; + while ((pos = contacts.find("") - pos); + + std::string status = utils::text::source_get_value2( &row, "chat", "\" " ); // "Online" or "Idle" + std::string name = utils::text::source_get_value( &row, 2, "title=\"", "\"" ); + std::string id = utils::text::source_get_value( &row, 3, "href=\"", "/profile.php?id=", "\"" ); + if (id.empty()) + id = utils::text::source_get_value( &row, 3, "href=\"", "facebook.com/", "\"" ); + + it = facepiles->find( id ); + if ( it == facepiles->end() ) { + facepiles->insert( std::make_pair( id, name ) ); + } + + pos++; + } + + } + catch (Reader::ParseException& e) + { + proto->Log( "!!!!! Caught json::ParseException: %s", e.what() ); + proto->Log( " Line/offset: %d/%d", e.m_locTokenBegin.m_nLine + 1, e.m_locTokenBegin.m_nLineOffset + 1 ); + } + catch (const Exception& e) + { + proto->Log( "!!!!! Caught json::Exception: %s", e.what() ); + } + catch (const std::exception& e) + { + proto->Log( "!!!!! Caught std::exception: %s", e.what() ); + } + + return EXIT_SUCCESS; +} + + int facebook_json_parser::parse_friends( void* data, std::map< std::string, facebook_user* >* friends ) { using namespace json; @@ -256,7 +357,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess const String& type = objMember["type"]; - if ( type.Value( ) == "msg" ) // chat message + if ( type.Value( ) == "msg" || type.Value() == "offline_msg" ) // direct message { const Number& from = objMember["from"]; char was_id[32]; @@ -264,20 +365,22 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess const Object& messageContent = objMember["msg"]; const String& text = messageContent["text"]; + //"tab_type":"friend", objMember["tab_type"] //const Number& time_sent = messageContent["time"]; - // proto->Log("????? Checking time %15.2f > %15.2f", time_sent.Value(), proto->facy.last_message_time_); - if (last_msg != text.Value()) -/* if (time_sent.Value() > proto->facy.last_message_time_ - || (time_sent.Value() < 0 && proto->facy.last_message_time_ >= 0)) // Check agains duplicit messages*/ - { + if ((messageContent.Find("truncated") != messageContent.End()) + && (((const Number &)messageContent["truncated"]).Value() == 1)) { + // If we got truncated message, we can ignore it, because we should get it again as "messaging" type + std::string msg = "????? We got truncated message so we ignore it\n"; + msg += utils::text::special_expressions_decode(utils::text::slashu_to_utf8(text.Value())); + proto->Log(msg.c_str()); + } else if (last_msg != text.Value()) { last_msg = text.Value(); - //proto->facy.last_message_time_ = time_sent.Value(); facebook_message* message = new facebook_message( ); - message->message_text= utils::text::special_expressions_decode( + message->message_text = utils::text::special_expressions_decode( utils::text::slashu_to_utf8( text.Value( ) ) ); message->time = ::time( NULL ); message->user_id = was_id; @@ -289,7 +392,7 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess proto->Log(msg.c_str()); } } - else if ( type.Value( ) == "messaging" ) // inbox message + else if ( type.Value( ) == "messaging" ) // inbox message (multiuser or direct) { const String& type = objMember["event"]; @@ -299,32 +402,69 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess const Number& from = messageContent["sender_fbid"]; char was_id[32]; lltoa( from.Value(), was_id, 10 ); + + + // Ignore if message is from self user + if (was_id == proto->facy.self_.user_id) + continue; + const String& text = messageContent["body"]; + //std::string tid = ((const String&)messageContent["tid"]).Value(); + + const String& sender_name = messageContent["sender_name"]; - // TODO RM: include sender name - // const String& name = messageContent["sender_name"]; + std::string row = ((const String &)objMember["thread_row"]).Value(); //const Number& time_sent = messageContent["timestamp"]; //proto->Log("????? Checking time %15.2f > %15.2f", time_sent.Value(), proto->facy.last_message_time_); - if (last_msg != text.Value()) -/* if (time_sent.Value() > proto->facy.last_message_time_ - || (time_sent.Value() < 0 && proto->facy.last_message_time_ >= 0)) // Check agains duplicit messages*/ - { + if (last_msg != text.Value()) { last_msg = text.Value(); - //proto->facy.last_message_time_ = time_sent.Value(); facebook_message* message = new facebook_message( ); - message->message_text= utils::text::special_expressions_decode( + message->message_text = utils::text::special_expressions_decode( utils::text::slashu_to_utf8( text.Value( ) ) ); - message->time = ::time( NULL ); + message->sender_name = utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( sender_name.Value( ) ) ); + + message->time = ::time( NULL ); + message->user_id = was_id; // TODO: Check if we have contact with this ID in friendlist and then do something different? - message->user_id = was_id; + if (row.find("uiSplitPic",0) != std::string::npos) { + // This is multiuser message + + std::string authors = utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( row ) ); + authors = utils::text::source_get_value(&authors, 2, "", "<"); - messages->push_back( message ); + const String& to_id = messageContent["tid"]; + + std::string popup_text = message->sender_name; + popup_text += ": "; + popup_text += message->message_text; + + std::string title = Translate("Multichat"); + title += ": "; + title += authors; + + std::string url = "/?action=read&sk=inbox&page&query&tid="; + url += to_id.Value(); + + proto->Log(" Got multichat message"); + + TCHAR* szTitle = mir_a2t_cp(title.c_str(), CP_UTF8); + TCHAR* szText = mir_a2t_cp(popup_text.c_str(), CP_UTF8); + TCHAR* szUrl = mir_a2t_cp(url.c_str(), CP_UTF8); + proto->NotifyEvent(szTitle,szText,NULL,FACEBOOK_EVENT_OTHER, szUrl); + mir_free(szTitle); + mir_free(szText); + + } else { + messages->push_back( message ); + } } else { std::string msg = "????? Got duplicit inbox message?\n"; msg += utils::text::special_expressions_decode(utils::text::slashu_to_utf8(text.Value())); @@ -334,13 +474,10 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess } else if ( type.Value( ) == "group_msg" ) // chat message { - if ( (::time(NULL) - proto->facy.last_grpmessage_time_) < 15 ) // TODO RM: remove dont notify more than once every 15 secs + if (!DBGetContactSettingByte(NULL,proto->m_szModuleName,FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS)) continue; - - proto->facy.last_grpmessage_time_ = ::time(NULL); - + const String& from_name = objMember["from_name"]; - const String& group_name = objMember["to_name"]; const Number& to = objMember["to"]; char group_id[32]; @@ -350,6 +487,32 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess char was_id[32]; lltoa( from.Value(), was_id, 10 ); + const Object& messageContent = objMember["msg"]; + const String& text = messageContent["text"]; + + std::string msg = utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( text.Value( ) ) ); + + std::string name = utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( from_name.Value( ) ) ); + + // Add contact into chat, if isn't there already + if (!proto->IsChatContact(group_id, was_id)) + proto->AddChatContact(group_id, was_id, name.c_str()); + + // Add message into chat + proto->UpdateChat(group_id, was_id, name.c_str(), msg.c_str()); + } + else if ( type.Value( ) == "thread_msg" ) // multiuser message + { + const String& from_name = objMember["from_name"]; + const String& to_name = objMember["to_name"]["__html"]; + const String& to_id = objMember["to"]; + + const Number& from = objMember["from"]; + char was_id[32]; + lltoa( from.Value(), was_id, 10 ); + // Ignore if message is from self user if (was_id == proto->facy.self_.user_id) continue; @@ -357,24 +520,25 @@ int facebook_json_parser::parse_messages( void* data, std::vector< facebook_mess const Object& messageContent = objMember["msg"]; const String& text = messageContent["text"]; - std::string popup_text = utils::text::remove_html( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( from_name.Value( ) ) ) ); + + last_msg = text.Value(); + + + std::string popup_text = utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( from_name.Value( ) ) ); popup_text += ": "; - popup_text += utils::text::remove_html( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( text.Value( ) ) ) ); + popup_text += utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( text.Value( ) ) ); - std::string title = Translate("Groupchat"); + std::string title = Translate("Multichat"); title += ": "; - title += utils::text::remove_html( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( group_name.Value( ) ) ) ); - - std::string url = "/home.php?sk=group_"; - url += group_id; + title += utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( to_name.Value( ) ) ); + + std::string url = "/?action=read&sk=inbox&page&query&tid="; + url += to_id.Value(); - proto->Log(" Got groupchat message"); + proto->Log(" Got multichat message"); TCHAR* szTitle = mir_a2t_cp(title.c_str(), CP_UTF8); TCHAR* szText = mir_a2t_cp(popup_text.c_str(), CP_UTF8); -- cgit v1.2.3