From ab4740c7b632ecfb6e94f8fea3eb872d8c6ef88b Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 17 Dec 2015 17:42:15 +0100 Subject: [PATCH] Communi: Support /whois (or .whois) command --- backends/libcommuni/ircnetworkplugin.cpp | 3 + backends/libcommuni/session.cpp | 71 +++++++++++++++++------- backends/libcommuni/session.h | 6 ++ spectrum/src/tests/muc_whois.py | 44 +++++++++++++++ 4 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 spectrum/src/tests/muc_whois.py diff --git a/backends/libcommuni/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp index 17b91ebf..641d8980 100644 --- a/backends/libcommuni/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -181,6 +181,9 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s if (message.find("/me") == 0) { m_sessions[session]->sendCommand(IrcCommand::createCtcpAction(FROM_UTF8(target), FROM_UTF8(message.substr(4)))); } + else if (message.find("/whois") == 0 || message.find(".whois") == 0) { + m_sessions[session]->sendWhoisCommand(target, message.substr(7)); + } else { m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message))); } diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index 8edd2bcc..6a58c558 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -224,22 +224,30 @@ void MyIrcSession::on_topicChanged(IrcMessage *message) { m_np->handleSubject(m_user, TO_UTF8(m->channel().toLower()) + m_suffix, TO_UTF8(m->topic()), nickname); } -void MyIrcSession::on_messageReceived(IrcMessage *message) { - IrcPrivateMessage *m = (IrcPrivateMessage *) message; - if (m->isRequest()) { - QString request = m->content().split(" ", QString::SkipEmptyParts).value(0).toUpper(); - if (request == "PING" || request == "TIME" || request == "VERSION") { - LOG4CXX_INFO(logger, m_user << ": " << TO_UTF8(request) << " received and has been answered"); - return; - } +void MyIrcSession::sendWhoisCommand(const std::string &channel, const std::string &to) { + m_whois[to] = channel; + sendCommand(IrcCommand::createWhois(FROM_UTF8(to))); +} + +void MyIrcSession::on_whoisMessageReceived(IrcMessage *message) { + IrcWhoisMessage *m = (IrcWhoisMessage *) message; + std::string nickname = TO_UTF8(m->nick()); + if (m_whois.find(nickname) == m_whois.end()) { + LOG4CXX_INFO(logger, "Whois response received with unexpected nickname " << nickname); + return; } - QString msg = m->content(); - if (m->isAction()) { - msg = QString("/me ") + msg; - } + std::string msg = ""; + msg += nickname + " is connected to " + TO_UTF8(m->server()) + " (" + TO_UTF8(m->realName()) + ")\n"; + msg += nickname + " is a user on channels: " + TO_UTF8(m->channels().join(", ")); + + sendMessageToFrontend(m_whois[nickname], "whois", msg); + m_whois.erase(nickname); +} + +void MyIrcSession::sendMessageToFrontend(const std::string &channel, const std::string &nick, const std::string &msg) { QString html = "";//msg; - CommuniBackport::toPlainText(msg); +// CommuniBackport::toPlainText(msg); // TODO: Communi produces invalid html now... // if (html == msg) { @@ -249,20 +257,18 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) { // html = IrcUtil::messageToHtml(html); // } - std::string target = TO_UTF8(m->target().toLower()); - if (target.find("#") == 0) { - std::string nickname = TO_UTF8(m->nick()); + std::string nickname = nick; + if (channel.find("#") == 0) { correctNickname(nickname); - m_np->handleMessage(m_user, target + m_suffix, TO_UTF8(msg), nickname, TO_UTF8(html)); + m_np->handleMessage(m_user, channel + m_suffix, msg, nickname, TO_UTF8(html)); } else { - std::string nickname = TO_UTF8(m->nick()); correctNickname(nickname); if (m_pms.find(nickname) != m_pms.end()) { std::string room = m_pms[nickname].substr(0, m_pms[nickname].find("/")); room = room.substr(0, room.find("@")); if (hasIRCBuddy(room, nickname)) { - m_np->handleMessage(m_user, room + m_suffix, TO_UTF8(msg), nickname, TO_UTF8(html), "", false, true); + m_np->handleMessage(m_user, room + m_suffix, msg, nickname, TO_UTF8(html), "", false, true); return; } else { @@ -275,17 +281,37 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) { continue; } addPM(nickname, it->second->getChannel()); - m_np->handleMessage(m_user, it->second->getChannel() + m_suffix, TO_UTF8(msg), nickname, TO_UTF8(html), "", false, true); + m_np->handleMessage(m_user, it->second->getChannel() + m_suffix, msg, nickname, TO_UTF8(html), "", false, true); return; } nickname = nickname + m_suffix; } - m_np->handleMessage(m_user, nickname, TO_UTF8(msg), "", TO_UTF8(html)); + m_np->handleMessage(m_user, nickname, msg, "", TO_UTF8(html)); } } +void MyIrcSession::on_messageReceived(IrcMessage *message) { + IrcPrivateMessage *m = (IrcPrivateMessage *) message; + if (m->isRequest()) { + QString request = m->content().split(" ", QString::SkipEmptyParts).value(0).toUpper(); + if (request == "PING" || request == "TIME" || request == "VERSION") { + LOG4CXX_INFO(logger, m_user << ": " << TO_UTF8(request) << " received and has been answered"); + return; + } + } + + std::string msg = TO_UTF8(m->content()); + if (m->isAction()) { + msg = "/me " + msg; + } + + std::string target = TO_UTF8(m->target().toLower()); + std::string nickname = TO_UTF8(m->nick()); + sendMessageToFrontend(target, nickname, msg); +} + void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { QString channel; QStringList members; @@ -470,6 +496,9 @@ void MyIrcSession::onMessageReceived(IrcMessage *message) { case IrcMessage::Notice: on_noticeMessageReceived(message); break; + case IrcMessage::Whois: + on_whoisMessageReceived(message); + break; default:break; } } diff --git a/backends/libcommuni/session.h b/backends/libcommuni/session.h index bf00e92e..b5fcf106 100644 --- a/backends/libcommuni/session.h +++ b/backends/libcommuni/session.h @@ -123,6 +123,9 @@ public: bool correctNickname(std::string &nickname); + void sendWhoisCommand(const std::string &channel, const std::string &to); + void sendMessageToFrontend(const std::string &channel, const std::string &nickname, const std::string &msg); + void on_joined(IrcMessage *message); void on_parted(IrcMessage *message); void on_quit(IrcMessage *message); @@ -132,6 +135,7 @@ public: void on_messageReceived(IrcMessage *message); void on_numericMessageReceived(IrcMessage *message); void on_noticeMessageReceived(IrcMessage *message); + void on_whoisMessageReceived(IrcMessage *message); int rooms; @@ -143,6 +147,7 @@ protected Q_SLOTS: void onMessageReceived(IrcMessage* message); void awayTimeout(); + protected: IRCNetworkPlugin *m_np; std::string m_user; @@ -156,6 +161,7 @@ protected: IRCBuddyMap m_buddies; QTimer *m_awayTimer; std::string m_suffix; + std::map m_whois; }; #endif // SESSION_H diff --git a/spectrum/src/tests/muc_whois.py b/spectrum/src/tests/muc_whois.py new file mode 100644 index 00000000..8c8b08b8 --- /dev/null +++ b/spectrum/src/tests/muc_whois.py @@ -0,0 +1,44 @@ +import optparse +import sys +import time +import subprocess +import os + +import sleekxmpp + + +class Responder(sleekxmpp.ClientXMPP): + def __init__(self, jid, password, room, nick): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + self.room = room + self.nick = nick + self.finished = False + self.add_event_handler("session_start", self.start) + self.tests = {} + + def start(self, event): + self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True) + +class Client(sleekxmpp.ClientXMPP): + def __init__(self, jid, password, room, nick): + sleekxmpp.ClientXMPP.__init__(self, jid, password) + self.room = room + self.nick = nick + self.add_event_handler("session_start", self.start) + self.add_event_handler("groupchat_message", self.muc_message) + self.finished = False + + self.tests = {} + self.tests["whois_received"] = ["libcommuni: Receive /whois command response", False] + + def muc_message(self, msg): + if msg['mucnick'] != self.nick: + if msg["body"] == "responder is connected to irc.example.net (responder)\nresponder is a user on channels: @#channel": + self.tests["whois_received"][1] = True + self.finished = True + + def start(self, event): + self.getRoster() + self.sendPresence() + self.plugin['xep_0045'].joinMUC(self.room, self.nick, wait=True) + self.send_message(mto=self.room, mbody="/whois responder", mtype='groupchat')