Пример #1
0
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;
}
Пример #2
0
void askForUsers(plugin_pipe p, QString channel)
{
	for(int i=0; i<5; i++)
	{
		p.write(who_is_here_message::create(channel));
		this_thread::sleep_for(chrono::milliseconds(50));
	}
}
Пример #3
0
void run(plugin_pipe pipe, std::string internal_name)
{
	// TODO remove this line once race condition is fixed
	pipe.write(register_handler::create(QObject::tr("/quip"), QuipPlugin::forward_quip_request));
	// Construct a plugin object (used throughout)
	QuipPlugin plugin(internal_name, pipe);
	// Register for these message types with the following priorities:
	plugin.register_for_message_type(QObject::tr(LIRCH_MESSAGE_TYPE_HANDLER_READY));
	plugin.register_for_message_type(QObject::tr(LIRCH_MESSAGE_TYPE_QUIP_REQUEST));
	// Begin a loop that will only exit when sent the shutdown command
	while (plugin.has_not_received_shutdown_command());
}
Пример #4
0
void populateDefaultChannel(plugin_pipe p)
{
	QSettings settings(QSettings::IniFormat, QSettings::UserScope, LIRCH_COMPANY_NAME, LIRCH_PRODUCT_NAME);
	settings.beginGroup("UserData");
	QString defaultNick = settings.value("nick",LIRCH_DEFAULT_NICK).value<QString>();
	settings.sync();
	settings.endGroup();

	askForUsers(p,"default");

	p.write(nick_message::create(defaultNick, true));

}
Пример #5
0
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;
}
Пример #6
0
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();
    }
}
Пример #7
0
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());
	}
}
Пример #8
0
//updates all of the relevent fields of out status map based on the received message
void updateSenderStatus(plugin_pipe p, message m, unordered_map<QString, user_status> & userList, QString currentNick)
{

	if (m.type=="received")
	{
		auto msg=dynamic_cast<received_message *>(m.getdata());
		if (!msg) {
			return;
		}
		userList[msg->nick].nick=msg->nick;
		userList[msg->nick].channels.insert(msg->channel);
		userList[msg->nick].ip=msg->ipAddress;
		userList[msg->nick].lastseen=time(NULL);
	}

	if (m.type=="received_status")
	{
		auto msg=dynamic_cast<received_status_message *>(m.getdata());
		if (!msg) {
			return;
		}
		userList[msg->nick].lastseen=time(NULL);
		userList[msg->nick].nick=msg->nick;
		userList[msg->nick].ip=msg->ipAddress;

		if (msg->subtype==received_status_message_subtype::LEFT)
		{
			userList[msg->nick].channels.erase(msg->channel);
			if (msg->channel=="")
			{
				for(const auto & iterator:userList[msg->nick].channels)
					p.write(notify_message::create(iterator,msg->nick + " has logged off."));
				userList.erase(msg->nick);
			}
			else
				p.write(notify_message::create(msg->channel,msg->nick+" has left channel "+msg->channel+"."));
		}
		else if (msg->subtype==received_status_message_subtype::JOIN)
		{
			//Only notify people if they're joining a channel they're not in
			if (userList[msg->nick].channels.count(msg->channel)) {
				return;
			}
			userList[msg->nick].channels.insert(msg->channel);
			p.write(notify_message::create(msg->channel,msg->nick+" has joined channel "+msg->channel+"."));
		}
		else if (msg->subtype==received_status_message_subtype::HERE && msg->channel!="")
		{
			userList[msg->nick].channels.insert(msg->channel);
		}
		else if (msg->subtype==received_status_message_subtype::WHOHERE)
		{
			// Only reply that you're in channels you're in
			if (userList[currentNick].channels.count(msg->channel)) {
				p.write(here_message::create(msg->channel));
				userList[msg->nick].channels.insert(msg->channel);
			}
		}
		else if (msg->subtype==received_status_message_subtype::NICK)
		{
			//message->channel is storing the old nickname of the user in the case that it is a nick type received.
			//if it is, remove the person of the old nickname
			user_status oldNickInfo = userList[msg->channel];
			oldNickInfo.nick=msg->nick;
			userList.erase(msg->channel);
			userList[msg->nick]=oldNickInfo;
			for(const auto & iterator:userList[msg->nick].channels)
				p.write(notify_message::create(iterator,msg->channel+" has changed their nick to "+msg->nick+"."));
		}

	}

	p.write(userlist_message::create(currentNick, userList));
}
Пример #9
0
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());
	}
}
Пример #10
0
void runplugin(plugin_pipe &p, const string &name)
{
	text_line input;
	QString channel="default";
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	//WindowWrapper channel_output=newpad(10000, maxx);
	unordered_map<QString, WindowWrapper> channel_windows;
	if (channel_windows["default"]==nullptr)
		return;
	WindowWrapper input_display=newwin(1, maxx-1, maxy-1, 0);
	if (input_display==nullptr)
		return;
	//Be lazy and let the input scroll
	scrollok(input_display, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				p.write(raw_edict_message::create(input.getQString(),channel));
				input.kill_whole_line();
			}
			else if (key==(unsigned char)CTRL('U'))
			{
				input.backward_kill_line();
			}
			else if (key==(unsigned char)CTRL('H'))
			{
				input.backward_delete_char();
			}
			else if (key==WEOF)
			{
				//Quit since we have no more input
				break;
			}
			else
			{
				//This conversion is always valid, since key's
				//only valid values are valid wchar_t values
				//and WEOF, and we know it's not WEOF.
				input.insert(key);
			}
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				input.backward_delete_char();
			}
			else if (key==KEY_ENTER)
			{
				p.write(raw_edict_message::create(input.getQString(),channel));
				input.kill_whole_line();
			}
		}
		while (p.has_message())
		{
			message m=p.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 (s->priority>-32000)
						p.write(registration_message::create(s->priority-1, name, s->type));
				}
			}
			else if (m.type=="display")
			{
				auto s=dynamic_cast<display_message *>(m.getdata());
				if (!s)
					continue;
				p.write(m.decrement_priority());

				QString message_channel=s->channel;
				string nick=s->nick.toLocal8Bit().constData();
				string contents=s->contents.toLocal8Bit().constData();

				if (s->channel=="")
					message_channel=channel;

				if (channel_windows.count(message_channel)!=0)
				{
					if(s->subtype==display_message_subtype::NORMAL)
						wprintu(channel_windows[message_channel], "<%s> %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::ME)
						wprintu(channel_windows[message_channel], "* %s %s\n", nick.c_str(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY)
						wprintu(channel_windows[message_channel], QString((QChar[]){0x203C, 0x203D, ' ', '%', 's', '\n', 0}).toLocal8Bit().constData(), contents.c_str());
					if(s->subtype==display_message_subtype::NOTIFY_CURRENT)
						wprintu(channel_windows[message_channel], QString((QChar[]){0x203C, 0x203C, 0x203D, ' ', '%', 's', '\n', 0}).toLocal8Bit().constData(), contents.c_str());
				}
			}
			else if (m.type=="set_channel")
			{
				auto i=dynamic_cast<set_channel_message *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					p.write(notify_message::create(channel, "On channel "+channel));
				else
					channel=i->channel;
			}
			else if (m.type=="leave_channel")
			{
				auto i=dynamic_cast<leave_channel_message *>(m.getdata());
				if (!i)
					continue;
				p.write(m.decrement_priority());
				if (i->channel=="")
					i->channel=channel;
				channel_windows.erase(i->channel);
				if (i->channel==channel)
					p.write(set_channel_message::create(channel));
			}
			else
				p.write(m.decrement_priority());
		}