bool test_userlist(plugin_pipe p) { message m=p.blocking_read(); if (m.type!="userlist") return false; auto u=dynamic_cast<userlist_message *>(m.getdata()); if (!u) return false; if (!u->statuses.empty()) return false; p.write(received_message::create(received_message_subtype::NORMAL, "POTUS", "James K Polk", "Invade Texas!", QHostAddress("3.4.18.45"))); this_thread::sleep_for(chrono::seconds(11)); m=p.read(); if (m.type!="userlist") return false; u=dynamic_cast<userlist_message *>(m.getdata()); if (!u) return false; if (u->statuses.size()!=1) return false; auto i=u->statuses.find("James K Polk"); if (i==u->statuses.end()) return false; if (i->second.nick!="James K Polk") return false; if (i->second.channels.size()!=1) return false; if (i->second.channels.find("POTUS")==i->second.channels.end()) return false; if (i->second.ip!=QHostAddress("3.4.18.45")) return false; auto diff=time(NULL)-i->second.lastseen; if (diff<10 || diff>12) return false; this_thread::sleep_for(chrono::minutes(2)); message mm=p.read(); while (mm.type!="") { m=mm; mm=p.read(); } if (m.type!="userlist") return false; u=dynamic_cast<userlist_message *>(m.getdata()); if (!u) return false; if (!u->statuses.empty()) return false; return true; }
void run(plugin_pipe p, string name) { if (name=="userlist") { p.write(registration_message::create(0, name, "userlist")); bool ready=false; while (!ready) { message m=p.blocking_read(); if (m.type!="registration_status") return; ready=dynamic_cast<registration_status *>(m.getdata())->status; } p.write(plugin_adder::create("real_userlist", "lib/libuserlist.so")); if (!test_userlist(p)) { p.write(core_quit_message::create()); return; } } p.write(core_quit_message::create()); cout << "Success!" << endl; }
void run(plugin_pipe p, std::string name) { // Register for the messages that pertain to the GUI p.write(registration_message::create(LIRCH_MSG_PRI_REG_MAX, name, LIRCH_MSG_TYPE_DISPLAY)); p.write(registration_message::create(LIRCH_MSG_PRI_REG_MAX, name, LIRCH_MSG_TYPE_USERLIST)); p.write(registration_message::create(LIRCH_MSG_PRI_REG_MAX, name, LIRCH_MSG_TYPE_CHANGED_NICK)); p.write(registration_message::create(LIRCH_MSG_PRI_REG_MAX, name, LIRCH_MSG_TYPE_SET_CHANNEL)); p.write(registration_message::create(LIRCH_MSG_PRI_REG_MAX, name, LIRCH_MSG_TYPE_LEAVE_CHANNEL)); extern LirchClientPipe mediator; mediator.open(p, QString::fromStdString(name)); // The mediator will act as a courier to the GUI while (mediator.ready()) { // Fetch a message from the pipe whenever it arrives message m = p.blocking_read(); // Determine what type of message it is if (m.type == LIRCH_MSG_TYPE_SHUTDOWN) { mediator.close(QObject::tr("core shutdown")); break; } else if (m.type == LIRCH_MSG_TYPE_REG_STAT) { // Recieved a registration status message auto reg = dynamic_cast<registration_status *>(m.getdata()); if (reg && !reg->status) { int registration_priority = reg->priority; // Retry over 9000 times until we succeed if (registration_priority < LIRCH_MSG_PRI_REG_MIN) { mediator.close(QObject::tr("failed to register with core")); break; } else { // Try again to register, if necessary p.write(registration_message::create(--registration_priority, name, reg->type)); } } } else if (m.type == LIRCH_MSG_TYPE_DISPLAY) { auto data = dynamic_cast<display_message *>(m.getdata()); if (data) { mediator.display(*data); } p.write(m.decrement_priority()); } else if (m.type == LIRCH_MSG_TYPE_USERLIST) { auto data = dynamic_cast<userlist_message *>(m.getdata()); if (data) { mediator.userlist(*data); } p.write(m.decrement_priority()); } else if (m.type == LIRCH_MSG_TYPE_CHANGED_NICK) { auto data = dynamic_cast<changed_nick_message *>(m.getdata()); if (data) { mediator.nick(*data); } p.write(m.decrement_priority()); } else if (m.type == LIRCH_MSG_TYPE_SET_CHANNEL) { auto data = dynamic_cast<set_channel_message *>(m.getdata()); if (data) { mediator.channel(*data); } p.write(m.decrement_priority()); } else if (m.type == LIRCH_MSG_TYPE_LEAVE_CHANNEL) { auto data = dynamic_cast<leave_channel_message *>(m.getdata()); if (data) { mediator.channel(*data); } p.write(m.decrement_priority()); } else { // By default, echo the message with decremented priority p.write(m.decrement_priority()); } } // We only get here through anomalous behavior (though it is good to have a catch-all) if (mediator.ready()) { mediator.close(); } }
void run(plugin_pipe p, string name) { p.write(registration_message::create(0, name, "userlist_request")); p.write(registration_message::create(0, name, "userlist_timer")); p.write(registration_message::create(30000, name, "received")); p.write(registration_message::create(30000, name, "received_me")); unordered_map<QString, user_status> statuses; while (true) { message m=p.blocking_read(); if (m.type=="shutdown") { return; } else if (m.type=="registration_status") { auto s=dynamic_cast<registration_status *>(m.getdata()); if (!s) continue; if (!s->status) { if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000)) p.write(registration_message::create(s->priority-1, name, s->type)); else return; } else { if (s->type=="userlist_timer") p.write(userlist_timer::create(10000)); } } else if (m.type=="userlist_request") { p.write(userlist_message::create(statuses)); } else if (m.type=="userlist_timer") { auto s=dynamic_cast<userlist_timer *>(m.getdata()); if (!s) continue; time_t now=time(NULL); //Remove all nicks that haven't been seen in 2 minutes decltype(statuses.begin()) i; while ((i=std::find_if(statuses.begin(), statuses.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=statuses.end()) statuses.erase(i); p.write(userlist_message::create(statuses)); int msecs=s->msecs; thread th([&p,msecs]() { plugin_pipe pp; this_thread::sleep_for(chrono::milliseconds(msecs)); pp.write(userlist_timer::create(msecs)); }); th.detach(); } else if (m.type=="received") { auto s=dynamic_cast<received_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); statuses[s->nick].nick=s->nick; statuses[s->nick].channels.insert(s->channel); statuses[s->nick].ip=s->ipAddress; statuses[s->nick].lastseen=time(NULL); } else if (m.type=="received_me") { auto s=dynamic_cast<received_me_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); statuses[s->nick].nick=s->nick; statuses[s->nick].channels.insert(s->channel); statuses[s->nick].ip=s->ipAddress; statuses[s->nick].lastseen=time(NULL); } else p.write(m.decrement_priority()); } }
void run(plugin_pipe p, string name) { p.write(registration_message::create(0, name, "userlist_request")); p.write(registration_message::create(0, name, "userlist_timer")); p.write(registration_message::create(30000, name, "received")); p.write(registration_message::create(30000, name, "received_status")); p.write(registration_message::create(0, name, "list_channels")); p.write(registration_message::create(0, name, "handler_ready")); p.write(registration_message::create(0, name, "leave_channel")); p.write(registration_message::create(0, name, "set_channel")); p.write(registration_message::create(-30000, name, "nick")); p.write(registration_message::create(-30000, name, "who_is")); p.write(registration_message::create(-30000, name, "block name")); bool firstTime=true; unordered_map<QString, user_status> userList; QString currentNick = LIRCH_DEFAULT_NICK; std::thread populate(populateDefaultChannel,p); populate.detach(); while (true) { message m=p.blocking_read(); if (m.type=="shutdown") { return; } else if (m.type=="registration_status") { auto s=dynamic_cast<registration_status *>(m.getdata()); if (!s) continue; if (!s->status) { if ((0>=s->priority && s->priority>-200) || (30000>=s->priority && s->priority>29000)) p.write(registration_message::create(s->priority-1, name, s->type)); else return; } else { if (s->type=="userlist_timer") { p.write(userlist_timer::create()); } else if (s->type=="handler_ready") { p.write(register_handler::create("/list", sendList)); p.write(register_handler::create("/nick", sendNick)); p.write(register_handler::create("/whois", sendWhois)); } } } else if (m.type=="userlist_request") { p.write(userlist_message::create(currentNick, userList)); } else if (m.type=="userlist_timer") { time_t now=time(NULL); //Remove all nicks that haven't been seen in 2 minutes decltype(userList.begin()) i; while ((i=std::find_if(userList.begin(), userList.end(), [now](const std::pair<const QString &, const user_status &> &p) {return p.second.lastseen<now-2*60;}))!=userList.end()) { for(auto iter = i->second.channels.begin(); iter!=i->second.channels.end(); iter++) p.write(notify_message::create(*iter, i->first + " has logged off.")); userList.erase(i); } p.write(userlist_message::create(currentNick, userList)); thread([](plugin_pipe p) { this_thread::sleep_for(chrono::seconds(10)); p.write(userlist_timer::create()); }, p).detach(); } else if (m.type=="handler_ready") { p.write(register_handler::create("/list", sendList)); p.write(register_handler::create("/nick", sendNick)); p.write(register_handler::create("/whois", sendWhois)); } else if (m.type=="received" || m.type=="received_status") { p.write(m.decrement_priority()); updateSenderStatus(p,m,userList,currentNick); } else if (m.type=="nick") { auto s=dynamic_cast<nick_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); if (firstTime) p.write(set_channel_message::create("default")); p.write(setNick(userList,currentNick,*s,firstTime)); //The userlist is no longer a virgin firstTime = false; if (s->changeDefault) { QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME); settings.beginGroup("UserData"); settings.setValue("nick", currentNick); settings.sync(); settings.endGroup(); } } else if (m.type=="list_channels") { auto s=dynamic_cast<list_channels *>(m.getdata()); if (!s) continue; for (auto &i : userList) { if (s->filterChannel=="" || i.second.channels.count(s->filterChannel)!=0) { QStringList channelList; for (auto &c : i.second.channels) channelList.append(c); p.write(notify_message::create(s->destinationChannel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(i.second.nick, i.second.ip.toString(), QDateTime::fromTime_t(i.second.lastseen).toString(), channelList.join(" ")))); } } } else if (m.type == "set_channel") { auto s=dynamic_cast<set_channel_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); // If you can't in the channel yet, ask who's there if (userList[currentNick].channels.count(s->channel)==0) askForUsers(p,s->channel); } else if (m.type == "leave_channel") { auto s=dynamic_cast<leave_channel_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); for(auto & person:userList) { person.second.channels.erase(s->channel); } } else if (m.type == "who_is") { auto s=dynamic_cast<who_is_message *>(m.getdata()); if (!s) continue; p.write(m.decrement_priority()); if (userList.count(s->nick)==0) continue; QStringList channelList; for (auto &c : userList[s->nick].channels) channelList.append(c); p.write(notify_message::create(s->channel, QObject::tr("User %1 (%2) was last seen at %3 and is in the following channels: %4").arg(userList[s->nick].nick, userList[s->nick].ip.toString(), QDateTime::fromTime_t(userList[s->nick].lastseen).toString(), channelList.join(" ")))); } else p.write(m.decrement_priority()); } }