ircchanneladapter.cpp
1 //------------------------------------------------------------------------------
2 // ircchanneladapter.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2010 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "irc/configuration/ircconfig.h"
24 #include "irc/ircglobal.h"
25 #include "irc/ircmessageclass.h"
26 #include "irc/ircnetworkadapter.h"
27 #include "irc/ircuserinfo.h"
28 #include "irc/ircuserlist.h"
29 #include "ircchanneladapter.h"
30 
31 IRCChannelAdapter::IRCChannelAdapter(IRCNetworkAdapter *pNetwork, const QString &recipient)
32  : IRCChatAdapter(pNetwork, recipient)
33 {
34  users = new IRCUserList();
35 }
36 
37 IRCChannelAdapter::~IRCChannelAdapter()
38 {
39  if (this->pNetwork != nullptr)
40  sendMessage("/part " + this->recipientName + " " + gIRCConfig.personal.quitMessage);
41 
42  delete users;
43 }
44 
46 {
47  const QString &myNickname = pNetwork->myNickname();
48  return isOperator(myNickname);
49 }
50 
52 {
53  if (users->appendNameToCachedList(IRCUserInfo(name, network())))
54  {
55  IRCUserInfo user = users->userCopy(name);
56  emit nameAdded(user);
57  }
58 }
59 
60 void IRCChannelAdapter::appendNamesToCachedList(const QStringList &names)
61 {
62  for (const QString &name : names)
63  {
65  }
66 }
67 
68 void IRCChannelAdapter::banUser(const QString &nickname, const QString &reason)
69 {
70  pNetwork->banUser(nickname, reason, this->recipientName);
71 }
72 
74 {
75  emit nameListUpdated(*users);
76 }
77 
78 void IRCChannelAdapter::emitChatMessage(const QString &sender, const QString &content)
79 {
80  // Ensure that all nickname artifacts are preserved.
81  const IRCUserInfo *pUserInfo = users->user(sender);
82 
83  QString actualSenderName = sender;
84  if (pUserInfo != nullptr)
85  actualSenderName = pUserInfo->prefixedName();
86 
87  // Check if content has our nickname.
88  // (do not play sounds for our own messages)
89  const QString &myNickname = pNetwork->myNickname();
90  if (content.contains(myNickname, Qt::CaseInsensitive)
91  && sender.compare(myNickname, Qt::CaseInsensitive) != 0)
92  {
93  emit myNicknameUsed();
94  }
95 
96  IRCChatAdapter::emitChatMessage(actualSenderName, content);
97 }
98 
99 bool IRCChannelAdapter::hasUser(const QString &nickname)
100 {
101  return users->hasUser(nickname);
102 }
103 
104 bool IRCChannelAdapter::isOperator(const QString &nickname) const
105 {
106  const IRCUserInfo *pUser = users->user(nickname);
107  if (pUser != nullptr)
108  return pUser->isOp();
109 
110  return false;
111 }
112 
113 void IRCChannelAdapter::kickUser(const QString &nickname, const QString &reason)
114 {
115  if (hasUser(nickname))
116  {
117  QString cleanNickname = IRCUserInfo(nickname, pNetwork).cleanNickname();
118  this->sendMessage(QString("/kick %1 %2 %3").arg(this->recipientName, cleanNickname, reason));
119  }
120 }
121 
123 {
124  IRCUserInfo user = users->userCopy(name);
125 
126  if (!users->removeNameFromCachedList(name))
127  emit error(QString(R"(Attempted to remove name "%1" from the "%2" channel's name list but no such name is on the list.)").arg(name, this->recipientName));
128  else
129  emit nameRemoved(user);
130 }
131 
132 void IRCChannelAdapter::setHalfOp(const QString &nickname, bool bSet)
133 {
134  pNetwork->setChannelMode(this->recipientName, nickname, "h", bSet);
135 }
136 
137 void IRCChannelAdapter::setOp(const QString &nickname, bool bSet)
138 {
139  pNetwork->setChannelMode(this->recipientName, nickname, "o", bSet);
140 }
141 
142 void IRCChannelAdapter::setVoiced(const QString &nickname, bool bSet)
143 {
144  pNetwork->setChannelMode(this->recipientName, nickname, "v", bSet);
145 }
146 
147 void IRCChannelAdapter::userChangesNickname(const QString &oldNickname, const QString &newNickname)
148 {
149  if (hasUser(oldNickname))
150  {
151  IRCUserInfo oldName = users->userCopy(oldNickname);
152 
153  users->changeNick(oldNickname, newNickname);
154  emit nameRemoved(oldName);
155  emit nameAdded(users->userCopy(newNickname));
156 
157  emit messageWithClass(tr("%1 is now known as %2").arg(oldNickname, newNickname),
158  IRCMessageClass::ChannelAction);
159  }
160 }
161 
162 void IRCChannelAdapter::userJoins(const QString &nickname, const QString &fullSignature)
163 {
164  appendNameToCachedList(nickname);
165 
166  emit messageWithClass(tr("User %1 [%2] has joined the channel.").arg(nickname, fullSignature),
167  IRCMessageClass::ChannelAction);
168 }
169 
170 void IRCChannelAdapter::userLeaves(const QString &nickname, const QString &farewellMessage, IRCQuitType quitType)
171 {
172  if (!hasUser(nickname))
173  {
174  // Nothing to do here. This user was not even on the channel.
175  return;
176  }
177 
178  removeNameFromCachedList(nickname);
179 
180  switch (quitType)
181  {
182  case IRCChatAdapter::ChannelPart:
183  emit messageWithClass(tr("User %1 has left the channel. (PART: %2)").arg(nickname, farewellMessage),
184  IRCMessageClass::ChannelAction);
185  break;
186 
187  case IRCChatAdapter::NetworkKill:
188  emit messageWithClass(tr("Connection for user %1 has been killed. (KILL: %2)").arg(nickname, farewellMessage),
189  IRCMessageClass::NetworkAction);
190  break;
191 
192  case IRCChatAdapter::NetworkQuit:
193  emit messageWithClass(tr("User %1 has quit the network. (QUIT: %2)").arg(nickname, farewellMessage),
194  IRCMessageClass::NetworkAction);
195  break;
196 
197  default:
198  emit error(tr("Unknown quit type from user %1.").arg(nickname));
199  break;
200  }
201 }
202 
203 void IRCChannelAdapter::userModeChanges(const QString &nickname,
204  const QList<char> &addedFlags, const QList<char> &removedFlags)
205 {
206  const IRCUserInfo *pUserInfo = this->users->user(nickname);
207  if (pUserInfo != nullptr)
208  {
209  IRCUserInfo newUserInfo = *pUserInfo;
210  for (char mode : addedFlags)
211  {
212  newUserInfo.setMode(mode);
213  }
214  for (char mode : removedFlags)
215  {
216  newUserInfo.unsetMode(mode);
217  }
218 
219  this->users->setUserModes(nickname, newUserInfo.modes());
220  emit nameUpdated(newUserInfo);
221  }
222 }