diff --git a/src/twister.cpp b/src/twister.cpp index fd4fdfc3..f1f02779 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -46,21 +46,6 @@ static map m_userTorrent; static std::string m_preferredSpamLang = "[en]"; static std::string m_receivedSpamMsgStr; static std::string m_receivedSpamUserStr; - -// in-memory unencrypted DMs -struct StoredDirectMsg { - int64 m_utcTime; - std::string m_text; - bool m_fromMe; -}; - -// in-memory data per wallet user -struct UserData { - std::set m_following; - // m_directmsg key is the other username - std::map > m_directmsg; -}; - static std::map m_users; sha1_hash dhtTargetHash(std::string const &username, std::string const &resource, std::string const &type) @@ -175,6 +160,20 @@ void ThreadWaitExtIP() //settings.min_announce_interval = 60; // test ses->set_settings(settings); + + boost::filesystem::path userDataPath = GetDataDir() / "user_data"; + loadUserData(userDataPath.string(), m_users); + printf("loaded user_data for %d users\n", m_users.size()); + + // now restart the user torrents (all m_following) + std::map::const_iterator i; + for (i = m_users.begin(); i != m_users.end(); ++i) { + UserData const &data = i->second; + BOOST_FOREACH(string username, data.m_following) { + startTorrentUser(username); + } + } + printf("libtorrent + dht started\n"); } @@ -452,6 +451,13 @@ void stopSessionTorrent() delete ses; ses = NULL; } + + if( m_users.size() ) { + printf("saving user_data (followers and DMs)...\n"); + boost::filesystem::path userDataPath = GetDataDir() / "user_data"; + saveUserData(userDataPath.string(), m_users); + } + printf("libtorrent + dht stopped\n"); } diff --git a/src/twister_utils.cpp b/src/twister_utils.cpp index 9ddc023e..ab264568 100644 --- a/src/twister_utils.cpp +++ b/src/twister_utils.cpp @@ -1,10 +1,14 @@ #include "twister_utils.h" #include +#include + +#include #include using namespace std; +using namespace boost; twister_utils::twister_utils() { @@ -125,3 +129,80 @@ entry jsonToEntry(const Value &v) } +int saveUserData(std::string const& filename, std::map const &users) +{ + entry userEntry; + + std::map::const_iterator i; + for (i = users.begin(); i != users.end(); ++i) { + UserData const &data = i->second; + + entry &dataEntry = userEntry[i->first]; + entry &followingEntry = dataEntry["following"]; + BOOST_FOREACH( std::string const &n, data.m_following) { + followingEntry.list().push_back(n); + } + + entry &dmEntry = dataEntry["dm"]; + + std::map >::const_iterator j; + for (j = data.m_directmsg.begin(); j != data.m_directmsg.end(); ++j) { + std::list const &stoDmList = j->second; + + entry &stoDmLstEntry = dmEntry[j->first]; + BOOST_FOREACH( StoredDirectMsg const &dm, stoDmList) { + entry stoDmEntry; + stoDmEntry["time"] = dm.m_utcTime; + stoDmEntry["text"] = dm.m_text; + stoDmEntry["fromMe"] = dm.m_fromMe; + stoDmLstEntry.list().push_back(stoDmEntry); + } + } + } + + std::vector buf; + bencode(std::back_inserter(buf), userEntry); + + return save_file(filename, buf); +} + + +int loadUserData(std::string const& filename, std::map &users) +{ + std::vector in; + if (load_file(filename, in) == 0) { + lazy_entry userEntry; + error_code ec; + if (lazy_bdecode(&in[0], &in[0] + in.size(), userEntry, ec) == 0) { + for( int i = 0; i < userEntry.dict_size(); i++) { + UserData data; + + const lazy_entry *dataEntry = userEntry.dict_at(i).second; + const lazy_entry *followingEntry = dataEntry->dict_find("following"); + for( int j = 0; j < followingEntry->list_size(); j++ ) { + data.m_following.insert( followingEntry->list_string_value_at(j) ); + } + + const lazy_entry *dmEntry = dataEntry->dict_find("dm"); + for( int j = 0; j < dmEntry->dict_size(); j++ ) { + const lazy_entry *stoDmLstEntry = dmEntry->dict_at(j).second; + + for( int k = 0; k < stoDmLstEntry->list_size(); k++ ) { + const lazy_entry *stoDmEntry = stoDmLstEntry->list_at(k); + StoredDirectMsg dm; + dm.m_text = stoDmEntry->dict_find_string_value("text"); + dm.m_utcTime = stoDmEntry->dict_find_int_value("time"); + dm.m_fromMe = stoDmEntry->dict_find_int_value("fromMe"); + data.m_directmsg[dmEntry->dict_at(j).first].push_back(dm); + } + } + + users[userEntry.dict_at(i).first] = data; + } + return 0; + } + } + return -1; +} + + diff --git a/src/twister_utils.h b/src/twister_utils.h index e25c0c23..7eaa9945 100644 --- a/src/twister_utils.h +++ b/src/twister_utils.h @@ -6,6 +6,22 @@ #include #include +#include + +// in-memory unencrypted DMs +struct StoredDirectMsg { + int64_t m_utcTime; + std::string m_text; + bool m_fromMe; +}; + +// in-memory data per wallet user +struct UserData { + std::set m_following; + // m_directmsg key is the other username + std::map > m_directmsg; +}; + class twister_utils { @@ -19,4 +35,7 @@ int save_file(std::string const& filename, std::vector& v); json_spirit::Value entryToJson(const libtorrent::entry &e); libtorrent::entry jsonToEntry(const json_spirit::Value &v); +int saveUserData(std::string const& filename, std::map const &users); +int loadUserData(std::string const& filename, std::map &users); + #endif // TWISTER_UTILS_H