23 #include "irc/configuration/chatnetworkscfg.h"
24 #include "irc/configuration/ircconfig.h"
25 #include "irc/entities/ircuserprefix.h"
26 #include "irc/ircchanneladapter.h"
27 #include "irc/ircglobal.h"
28 #include "irc/ircisupportparser.h"
29 #include "irc/ircmessageclass.h"
30 #include "irc/ircprivadapter.h"
31 #include "irc/ircrequestparser.h"
32 #include "irc/ircresponseparser.h"
33 #include "irc/ircuserinfo.h"
34 #include "irc/ircuserlist.h"
35 #include "irc/ops/ircdelayedoperationban.h"
36 #include "ircnetworkadapter.h"
42 this->connectionInfo = connectionInfo;
43 this->bIsJoining =
false;
44 this->bEmitAllIRCMessages =
false;
49 ircClient.connectSocketSignals(pIrcSocketSignalsAdapter);
51 QObject::connect(&ircClient, SIGNAL(ircServerResponse(
const QString&)),
52 this, SLOT(ircServerResponse(
const QString&)));
55 QObject::connect(&ircRequestParser, SIGNAL(echoPrivmsg(
const QString&,
const QString&)),
56 this, SLOT(echoPrivmsg(
const QString&,
const QString&)));
58 QObject::connect(&ircRequestParser, SIGNAL(query(
const QString&)),
62 QObject::connect(ircResponseParser, SIGNAL(helloClient(
const QString&)),
63 this, SLOT(helloClient(
const QString&)));
65 QObject::connect(ircResponseParser, SIGNAL(iSupportReceived(QString)),
66 SLOT(appendISupportLine(QString)));
68 QObject::connect(ircResponseParser, SIGNAL(kick(
const QString&,
const QString&,
const QString&,
const QString&)),
69 this, SLOT(kick(
const QString&,
const QString&,
const QString&,
const QString&)));
71 QObject::connect(ircResponseParser, SIGNAL(kill(
const QString&,
const QString&)),
72 this, SLOT(kill(
const QString&,
const QString&)));
74 QObject::connect(ircResponseParser, SIGNAL(modeInfo(
const QString&,
const QString&,
const QString&)),
75 this, SLOT(modeInfo(
const QString&,
const QString&,
const QString&)));
77 QObject::connect(ircResponseParser, SIGNAL(namesListReceived(
const QString&,
const QStringList&)),
78 this, SLOT(namesListReceived(
const QString&,
const QStringList&)));
80 QObject::connect(ircResponseParser, SIGNAL(namesListEndReceived(
const QString&)),
81 this, SLOT(namesListEndReceived(
const QString&)));
83 QObject::connect(ircResponseParser, SIGNAL(nicknameInUse(
const QString&)),
84 this, SLOT(nicknameInUse(
const QString&)));
86 QObject::connect(ircResponseParser, SIGNAL(noSuchNickname(
const QString&)),
87 this, SLOT(noSuchNickname(
const QString&)));
89 QObject::connect(ircResponseParser, SIGNAL (parseError(
const QString&)),
90 this, SLOT(parseError(
const QString&)));
94 QObject::connect(ircResponseParser, SIGNAL(
print(
const QString&,
const QString&)),
95 this, SLOT(
print(
const QString&,
const QString&)), Qt::DirectConnection);
96 QObject::connect(ircResponseParser,
97 SIGNAL(printWithClass(
const QString&,
const QString&,
const IRCMessageClass&)),
98 this, SLOT(printWithClass(
const QString&,
const QString&,
const IRCMessageClass&)),
99 Qt::DirectConnection);
100 QObject::connect(ircResponseParser, SIGNAL(printToNetworksCurrentChatBox(QString,
IRCMessageClass)),
103 QObject::connect(ircResponseParser, SIGNAL (privMsgReceived(
const QString&,
const QString&,
const QString&)),
104 this, SLOT(privMsgReceived(
const QString&,
const QString&,
const QString&)));
105 QObject::connect(ircResponseParser, SIGNAL (privMsgLiteralReceived(QString,QString,
IRCMessageClass)),
108 QObject::connect(ircResponseParser, SIGNAL (sendPongMessage(
const QString&)),
109 this, SLOT(sendPong(
const QString&)));
111 QObject::connect(ircResponseParser, SIGNAL (userChangesNickname(
const QString&,
const QString&)),
112 this, SLOT(userChangesNickname(
const QString&,
const QString&)));
114 QObject::connect(ircResponseParser, SIGNAL(userIdleTime(QString,
int)),
115 this, SLOT(userIdleTime(QString,
int)));
117 QObject::connect(ircResponseParser, SIGNAL (userJoinsChannel(
const QString&,
const QString&,
const QString&)),
118 this, SLOT(userJoinsChannel(
const QString&,
const QString&,
const QString&)));
120 QObject::connect(ircResponseParser,
121 SIGNAL(userModeChanged(
const QString&,
const QString&,
const QList<char>&,
const QList<char>&)),
123 SLOT(userModeChanged(
const QString&,
const QString&,
const QList<char>&,
const QList<char>&)));
125 QObject::connect(ircResponseParser, SIGNAL(userNetworkJoinDateTime(QString,QDateTime)),
126 this, SLOT(userNetworkJoinDateTime(QString,QDateTime)));
128 QObject::connect(ircResponseParser, SIGNAL (userPartsChannel(
const QString&,
const QString&,
const QString&)),
129 this, SLOT(userPartsChannel(
const QString&,
const QString&,
const QString&)));
131 QObject::connect(ircResponseParser, SIGNAL (userQuitsNetwork(
const QString&,
const QString&)),
132 this, SLOT(userQuitsNetwork(
const QString&,
const QString&)));
134 QObject::connect(ircResponseParser, SIGNAL (whoIsUser(
const QString&,
const QString&,
const QString&,
const QString&)),
135 this, SLOT(whoIsUser(
const QString&,
const QString&,
const QString&,
const QString&)));
138 IRCNetworkAdapter::~IRCNetworkAdapter()
140 disconnect(gIRCConfig.personal.quitMessage);
142 killAllChatWindows();
143 delete this->ircResponseParser;
144 delete this->ircISupportParser;
145 delete this->pIrcSocketSignalsAdapter;
148 void IRCNetworkAdapter::appendISupportLine(
const QString &line)
150 print(line, QString());
151 ircISupportParser->appendLine(line);
152 ircISupportParser->parse();
158 op->setReason(reason);
162 QList<IRCAdapterBase *> IRCNetworkAdapter::childrenAdapters()
164 QList<IRCAdapterBase *> result;
172 void IRCNetworkAdapter::connect()
180 chatWindows.remove(pAdapter->recipient().toLower());
183 void IRCNetworkAdapter::disconnect(
const QString &farewellMessage)
185 sendMessage(
"/quit " + farewellMessage);
186 ircClient.disconnect();
191 if (pOrigin ==
nullptr)
194 if (!ircClient.isConnected())
196 pOrigin->emitError(tr(
"You are not connected to the network."));
200 IRCRequestParser::IRCRequestParseResult result = ircRequestParser.
parse(pOrigin, message);
201 QString parsedMessage = ircRequestParser.output();
205 case IRCRequestParser::ErrorInputInsufficientParameters:
206 pOrigin->emitError(tr(
"Insufficient parameters."));
209 case IRCRequestParser::ErrorInputNotPrependedWithSlash:
210 emit error(tr(
"This is a server window. All commands must be prepended with a '/' character."));
213 case IRCRequestParser::ErrorMessageEmpty:
214 pOrigin->emitError(tr(
"Attempted to send empty message."));
217 case IRCRequestParser::ErrorMessageTooLong:
218 pOrigin->emitError(tr(
"Command is too long."));
221 case IRCRequestParser::ErrorChatWindowOnly:
222 pOrigin->emitError(tr(
"Not a chat window."));
225 case IRCRequestParser::Ok:
226 ircClient.sendMessage(parsedMessage);
229 case IRCRequestParser::QuitCommand:
230 ircClient.sendMessage(parsedMessage);
231 emit messageWithClass(tr(
"Quit"), IRCMessageClass::NetworkAction);
236 void IRCNetworkAdapter::echoPrivmsg(
const QString &recipient,
const QString &content)
240 if (hasRecipient(recipient))
242 const QString &sender = this->myNickname();
243 privMsgReceived(recipient, sender, content);
247 IRCChatAdapter *IRCNetworkAdapter::getChatAdapter(
const QString &recipient)
249 if (recipient.isEmpty())
251 emit error(
"Doomseeker error: getChatAdapter() received empty recipient.");
255 QString recipientLowercase = recipient.toLower();
256 if (hasRecipient(recipientLowercase))
257 return chatWindows[recipientLowercase];
262 const IRCChatAdapter *IRCNetworkAdapter::getChatAdapter(
const QString &recipient)
const
264 if (recipient.isEmpty())
267 QString recipientLowercase = recipient.toLower();
268 if (hasRecipient(recipientLowercase))
269 return chatWindows[recipientLowercase];
274 IRCChatAdapter *IRCNetworkAdapter::getOrCreateNewChatAdapter(
const QString &recipient)
278 if (recipient.isEmpty())
280 emit error(
"Doomseeker error: getOrCreateNewChatAdapter() received empty recipient.");
284 QString recipientLowercase = recipient.toLower();
286 if (hasRecipient(recipientLowercase))
287 return chatWindows[recipientLowercase];
290 Log::instance << QString(
"IRCNetworkAdapter::getOrCreateNewChatAdapter() Creating new adapter for recipient: %1").arg(recipientLowercase);
293 if (IRCGlobal::isChannelName(recipient))
298 chatWindows.insert(recipientLowercase, pAdapter);
304 bool IRCNetworkAdapter::hasRecipient(
const QString &recipient)
const
306 QString recipientLowercase = recipient.toLower();
307 return chatWindows.find(recipientLowercase) != chatWindows.end();
310 void IRCNetworkAdapter::helloClient(
const QString &nickname)
315 connectionInfo.
nick = nickname;
318 gLog << tr(
"IRC: Successfully registered on network %1 [%2:%3]").arg(network.
description(), network.
address()).arg(network.
port());
320 this->bIsJoining =
false;
322 if (!network.nickservPassword().isEmpty())
324 QString messageNickserv = network.nickservCommand();
325 messageNickserv = messageNickserv.arg(network.nickservPassword());
327 this->sendMessage(messageNickserv);
331 if (!command.trimmed().isEmpty())
332 this->sendMessage(command);
337 if (IRCGlobal::isChannelName(channel))
345 const PatternList &IRCNetworkAdapter::ignoredUsersPatterns()
const
350 void IRCNetworkAdapter::ircServerResponse(
const QString &message)
354 if (this->bEmitAllIRCMessages || !result.
wasParsed())
355 emit this->message(message.trimmed().replace(
"\n",
"\\n"));
357 if (!result.isValid())
358 emit this->error(tr(
"Invalid parse result for message: %1").arg(message));
363 if (
this == pAdapter)
366 QList<IRCChatAdapter *> adaptersList = chatWindows.values();
369 if (pChatWindow == pAdapter)
376 bool IRCNetworkAdapter::isMyNickname(
const QString &nickname)
const
379 return myUserInfo.isSameNickname(nickname);
384 if (IRCGlobal::isChannelName(channel))
386 const auto pChannelAdapter = (
const IRCChannelAdapter *) this->getChatAdapter(channel);
387 if (pChannelAdapter !=
nullptr)
388 return pChannelAdapter->isOperator(nickname);
394 void IRCNetworkAdapter::kick(
const QString &channel,
const QString &byWhom,
const QString &whoIsKicked,
const QString &reason)
396 if (hasRecipient(channel))
400 if (isMyNickname(whoIsKicked))
402 this->emitMessageWithClass(tr(
"You have been kicked from channel %1 by %2 (Reason: %3)").arg(channel, byWhom, reason), IRCMessageClass::ChannelAction);
403 killChatWindow(channel);
407 pAdapter->emitMessageWithClass(tr(
"%1 was kicked by %2 (%3)").arg(whoIsKicked, byWhom, reason), IRCMessageClass::ChannelAction);
408 pAdapter->removeNameFromCachedList(whoIsKicked);
413 void IRCNetworkAdapter::kill(
const QString &victim,
const QString &comment)
415 emit message(QString(
"Connection for user %1 was killed. (%2)").arg(victim, comment));
421 QList<IRCChatAdapter *> adaptersList = chatWindows.values();
424 pAdapter->
userLeaves(victim, comment, IRCChatAdapter::NetworkKill);
428 void IRCNetworkAdapter::killAllChatWindows()
430 QList<IRCChatAdapter *> pWindows = chatWindows.values();
442 void IRCNetworkAdapter::killChatWindow(
const QString &recipient)
444 if (hasRecipient(recipient))
447 chatWindows.remove(recipient.toLower());
456 void IRCNetworkAdapter::modeInfo(
const QString &channel,
const QString &whoSetThis,
const QString &modeParams)
459 pAdapter->emitMessageWithClass(tr(
"%1 sets mode: %2").arg(whoSetThis, modeParams), IRCMessageClass::ChannelAction);
462 void IRCNetworkAdapter::namesListReceived(
const QString &channel,
const QStringList &names)
464 if (this->hasRecipient(channel))
467 pAdapter->appendNamesToCachedList(names);
471 void IRCNetworkAdapter::namesListEndReceived(
const QString &channel)
473 if (this->hasRecipient(channel))
476 pAdapter->emitCachedNameListUpdated();
480 void IRCNetworkAdapter::nicknameInUse(
const QString &nickname)
482 emit messageToNetworksCurrentChatBox(tr(
"Nickname %1 is already taken.").arg(nickname), IRCMessageClass::Error);
483 if (this->bIsJoining)
487 if (this->connectionInfo.
nick.compare(altNick, Qt::CaseInsensitive) == 0)
488 emit messageWithClass(tr(
"Both nickname and alternate nickname are taken on this network."), IRCMessageClass::Error);
489 else if (altNick.isEmpty())
490 emit messageWithClass(tr(
"No alternate nickname specified."), IRCMessageClass::Error);
493 this->connectionInfo.
nick = altNick;
495 emit messageWithClass(tr(
"Using alternate nickname %1 to join.").arg(altNick), IRCMessageClass::NetworkAction);
496 QString message = QString(
"/nick %1").arg(altNick);
497 sendMessage(message);
502 void IRCNetworkAdapter::noSuchNickname(
const QString &nickname)
504 emit messageToNetworksCurrentChatBox(tr(
"User %1 is not logged in.").arg(nickname), IRCMessageClass::Error);
509 if (!isConnected() || recipientName.isEmpty())
512 bool bStandardRoutine = !IRCGlobal::isChannelName(recipientName)
513 || hasRecipient(recipientName);
515 if (bStandardRoutine)
517 IRCChatAdapter *pAdapter = this->getOrCreateNewChatAdapter(recipientName);
518 pAdapter->emitFocusRequest();
520 else if (IRCGlobal::isChannelName(recipientName))
521 this->sendMessage(
"/join " + recipientName);
524 void IRCNetworkAdapter::parseError(
const QString &error)
526 emit this->error(tr(
"IRC parse error: %1").arg(error));
534 void IRCNetworkAdapter::printWithClass(
const QString &printWhat,
539 if (!printWhere.isEmpty())
542 if (pAdapterCandidate !=
nullptr)
543 pAdapter = pAdapterCandidate;
548 if (pAdapter ==
nullptr)
549 this->emitMessageWithClass(tr(
"FROM %1: %2").arg(printWhere, printWhat), msgClass);
555 if ( pAdapter ==
this && this->bEmitAllIRCMessages )
558 pAdapter->emitMessageWithClass(printWhat, msgClass);
562 void IRCNetworkAdapter::printToCurrentChatBox(
const QString &printWhat,
const IRCMessageClass &msgClass)
564 emit messageToNetworksCurrentChatBox(printWhat, msgClass);
567 void IRCNetworkAdapter::privMsgReceived(
const QString &recipient,
const QString &sender,
const QString &content)
569 IRCChatAdapter *pAdapter = this->getOrCreateNewChatAdapter(recipient);
573 void IRCNetworkAdapter::printMsgLiteral(
const QString &recipient,
const QString &content,
576 this->getOrCreateNewChatAdapter(recipient);
577 printWithClass(content, recipient, msgClass);
580 void IRCNetworkAdapter::reloadNetworkEntityFromConfig()
584 if (entity.isValid())
585 setNetworkEntity(entity);
596 void IRCNetworkAdapter::sendCtcp(
const QString &nickname,
const QString &command)
598 QString msg = QString(
"/PRIVMSG %1 %2%3%2").arg(nickname).arg(QChar(0x1)).arg(command);
602 void IRCNetworkAdapter::sendPong(
const QString &toWhom)
604 QString message = QString(
"/PONG %1").arg(toWhom);
605 sendMessage(message);
610 QString cleanNickname =
userPrefixes().cleanNickname(nickname);
612 QString flagPrefixed;
614 flagPrefixed =
"+" + flag.trimmed();
616 flagPrefixed =
"-" + flag.trimmed();
618 QString message = QString(
"/mode %1 %2 %3").arg(channel, flagPrefixed, cleanNickname);
619 this->sendMessage(message);
627 void IRCNetworkAdapter::userChangesNickname(
const QString &oldNickname,
const QString &newNickname)
629 if (isMyNickname(oldNickname))
631 emit messageToNetworksCurrentChatBox(tr(
"Updated own nickname to %1.").arg(newNickname),
632 IRCMessageClass::NetworkAction);
633 connectionInfo.
nick = newNickname;
638 QList<IRCChatAdapter *> adaptersList = chatWindows.values();
646 if (hasRecipient(oldNickname))
648 QString oldNicknameLowercase = oldNickname.toLower();
649 QString newNicknameLowercase = newNickname.toLower();
652 chatWindows.remove(oldNicknameLowercase);
653 chatWindows.insert(newNicknameLowercase, pAdapter);
657 void IRCNetworkAdapter::userJoinsChannel(
const QString &channel,
const QString &nickname,
const QString &fullSignature)
659 if (!isMyNickname(nickname))
661 if (hasRecipient(channel))
664 pChannel->
userJoins(nickname, fullSignature);
670 pChannel->emitFocusRequest();
674 void IRCNetworkAdapter::userIdleTime(
const QString &nick,
int secondsIdle)
676 QString msg = tr(
"Last activity of user %1 was %2 ago.").arg(
678 emit messageToNetworksCurrentChatBox(msg, IRCMessageClass::NetworkAction);
681 void IRCNetworkAdapter::userModeChanged(
const QString &channel,
const QString &nickname,
682 const QList<char> &addedFlags,
const QList<char> &removedFlags)
684 if (hasRecipient(channel))
686 IRCChatAdapter *pAdapter = this->getOrCreateNewChatAdapter(channel);
691 void IRCNetworkAdapter::userNetworkJoinDateTime(
const QString &nick,
const QDateTime &timeOfJoin)
693 QString msg = tr(
"%1 joined the network on %2").arg(nick,
694 timeOfJoin.toString(
"yyyy-MM-dd HH:mm:ss"));
695 emit messageToNetworksCurrentChatBox(msg, IRCMessageClass::NetworkAction);
698 void IRCNetworkAdapter::userPartsChannel(
const QString &channel,
const QString &nickname,
const QString &farewellMessage)
700 if (hasRecipient(channel))
704 if (isMyNickname(nickname))
706 emit messageWithClass(tr(
"You left channel %1.").arg(channel), IRCMessageClass::ChannelAction);
707 killChatWindow(channel);
710 pChannel->userLeaves(nickname, farewellMessage, IRCChatAdapter::ChannelPart);
716 return ircISupportParser->userPrefixes();
719 void IRCNetworkAdapter::userQuitsNetwork(
const QString &nickname,
const QString &farewellMessage)
725 QList<IRCChatAdapter *> adaptersList = chatWindows.values();
728 pAdapter->
userLeaves(nickname, farewellMessage, IRCChatAdapter::NetworkQuit);
732 void IRCNetworkAdapter::userPing(
const QString &nickname, qint64 ping)
734 qint64 delta = QDateTime::currentMSecsSinceEpoch() - ping;
735 emit messageToNetworksCurrentChatBox(
736 tr(
"Ping to user %1: %2ms").arg(nickname).arg(delta),
737 IRCMessageClass::Ctcp);
740 void IRCNetworkAdapter::whoIsUser(
const QString &nickname,
const QString &user,
const QString &hostName,
const QString &realName)
742 emit messageToNetworksCurrentChatBox(
743 QString(
"%1 %2 %3 %4").arg(nickname, user, hostName, realName),
744 IRCMessageClass::NetworkAction);
749 void IRCSocketSignalsAdapter::connected()
751 pParent->bIsJoining =
true;
752 pParent->emitMessageWithClass(tr(
"Connected. Sending registration messages."), IRCMessageClass::NetworkAction);
756 QString messagePass =
"/PASS %1";
757 QString messageNick =
"/NICK %1";
758 QString messageUser =
"/USER %1 0 * :%2";
763 pParent->sendMessage(messagePass.arg(network.
password()));
765 pParent->sendMessage(messageNick.arg(connectionInfo.
nick));
766 pParent->sendMessage(messageUser.arg(connectionInfo.
userName).arg(connectionInfo.
realName));
769 void IRCSocketSignalsAdapter::disconnected()
771 pParent->killAllChatWindows();
773 emit pParent->message(
"Disconnected");
776 void IRCSocketSignalsAdapter::errorReceived(QAbstractSocket::SocketError error)
779 emit pParent->error(pSocket->errorString());
782 void IRCSocketSignalsAdapter::infoMessage(
const QString &message)
785 emit pParent->message(message);