// Zoe AIM Away Message RSS Feed Generator // // Seth King and Douglas Thrift // // $Id$ #include "AwayMessage.hpp" #include "Collector.hpp" #include "Stamp.hpp" #include extern "C" { #include #include } Collector::Collector(const ext::String& login, ext::String& password, const std::set& buddies, const Database& database, bool start) : login(login), password(password), buddies(buddies), database(database), start(start), prompted(false) { if (start) { if (password.IsEmpty()) prompt(); collector.Spawn(etl::Bind<0>(&Collector::collect, this)); } } int Collector::collect() { cerr << bright << green << "Started collector daemon at " << Stamp() << ".\n" << reset; net::Oscar::Session session; net::Oscar::AuthTool auth(session); net::Oscar::BuddyTool buddy(session); net::Oscar::ChatTool chat(session); net::Oscar::IcbmTool icbm(session); net::Oscar::InfoTool info(session); auth.Login(login, password); if (prompted) password.Clear(); this->buddy = &buddy; this->icbm = &icbm; this->info = &info; buddy.OnOnline += etl::Bind<0>(&Collector::status, this); icbm.OnReceive += etl::Bind<0>(&Collector::receive, this); net::Oscar::StringSet buddies; for (std::set::const_iterator buddy(this->buddies.begin()); buddy != this->buddies.end(); ++buddy) buddies.Insert(*buddy); buddy.Insert(buddies); net::Oscar::Capabilities capabilities; capabilities.Insert(net::Oscar::ChatCapability); info.SetProfile("I am Zoe. :-*", "Mommy told me not to talk to strangers. O:-)", capabilities); // XXX figure out whether or not we logged in while (true) sleep(Hour(1)); } void Collector::prompt() { if (!prompted) prompted = true; ext::String prompt(login + "'s AIM Password: "); char* password(getpass(prompt.NullTerminate())); this->password = password; for (size_t index(std::strlen(password)); index > 0; --index) password[index - 1] = '\0'; } void Collector::status(const net::Oscar::UserInfo& user) { Buddy buddy(*buddies.find(user)); AwayMessage message(buddy, *info); if (!ext::String(message).IsEmpty()) // XXX { if (Zoe::debug) cerr << "buddy = " << buddy << "\nmessage = " << message << '\n'; ext::Handle driver(dbi::GetDriver(database.driver)); ext::Handle db(driver->Connect(database.host, database.user, database.password, database.db)); ext::Handle previous(db->Execute("SELECT message " "FROM messages WHERE stamp=(SELECT MAX(stamp) FROM messages " "WHERE id='" + lexical_cast(buddy.getId()) + "') AND id='" + lexical_cast(buddy.getId()) + "'")); if (previous->MoveNext()) { if (ext::String(message) == previous->GetString("message")) return; } db->Execute("INSERT INTO messages (stamp, message, id) VALUES ('" + ext::String(message.getStamp()) + "', '" + db->Escape(message) + "', '" + lexical_cast(buddy.getId()) + "')"); cerr << bright << red << "Collected away message from " << blue << buddy << red << " at " << Stamp() << ".\n" << reset; } if (user.screenname != buddy.getDisplay(database)) { buddy.setDisplay(user.screenname, database); sleep(1); icbm->Simple(buddy, "So sexy! :-*"); } } void Collector::receive(const ext::String& buddy, const ext::String& message) { if (Zoe::debug) cerr << "buddy = " << Buddy(buddy) << "\nmessage = " << message << '\n'; if (buddies.find(buddy) != buddies.end()) { Buddy buddy_(*buddies.find(buddy)); sleep(1); icbm->Simple(buddy, "Hello! I am Zoe. I am" " supposed to be collecting your Away Messages (" "RSS 2.0) (Atom)." " :-*"); } else { sleep(1); icbm->Simple(buddy, "Mommy told me not to " "talk to strangers. O:-)"); } }