Implemented a channel browser (BR #176).
[quassel.git] / src / core / ircserverhandler.cpp
index c2264ac..9bdb3c6 100644 (file)
@@ -22,6 +22,7 @@
 #include "util.h"
 
 #include "coresession.h"
+#include "coreirclisthelper.h"
 #include "networkconnection.h"
 #include "network.h"
 #include "identity.h"
@@ -144,7 +145,7 @@ void IrcServerHandler::defaultHandler(QString cmd, const QString &prefix, const
         break;
       }
       // Ignore these commands.
-      case 366: case 376:
+      case 321: case 366: case 376:
         break;
 
       // Everything else will be marked in red, so we can add them somewhere.
@@ -170,7 +171,10 @@ void IrcServerHandler::handleJoin(const QString &prefix, const QList<QByteArray>
   emit displayMsg(Message::Join, BufferInfo::ChannelBuffer, channel, channel, prefix);
   //qDebug() << "IrcServerHandler::handleJoin()" << prefix << params;
   ircuser->joinChannel(channel);
-  if(network()->isMe(ircuser)) networkConnection()->setChannelJoined(channel);
+  if(network()->isMe(ircuser)) {
+    networkConnection()->setChannelJoined(channel);
+    putCmd("MODE", params[0]); // we want to know the modes of the channel we just joined, so we ask politely
+  }
 }
 
 void IrcServerHandler::handleKick(const QString &prefix, const QList<QByteArray> &params) {
@@ -204,11 +208,9 @@ void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray>
     emit displayMsg(Message::Mode, BufferInfo::ChannelBuffer, serverDecode(params[0]), serverDecode(params).join(" "), prefix);
 
     IrcChannel *channel = network()->ircChannel(params[0]);
-    // FIXME: currently the IrcChannels only support PREFIX-Modes for users
-    // This cannot be fixed unless the SignalProxy() doesn't rely on methodIds anymore
     QString modes = params[1];
     bool add = true;
-    int modeIndex = 2;
+    int paramOffset = 2;
     for(int c = 0; c < modes.length(); c++) {
       if(modes[c] == '+') {
        add = true;
@@ -219,15 +221,36 @@ void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray>
        continue;
       }
 
-      // this is the part where we restrict the mode changes to PREFIXES:
-      if(network()->prefixModes().contains(modes[c]) && modeIndex < params.count()) {
-       IrcUser *ircUser = network()->ircUser(params[modeIndex]);
+      if(network()->prefixModes().contains(modes[c])) {
+       // user channel modes (op, voice, etc...)
+       if(paramOffset < params.count()) {
+         IrcUser *ircUser = network()->ircUser(params[paramOffset]);
+         if(add)
+           channel->addUserMode(ircUser, QString(modes[c]));
+         else
+           channel->removeUserMode(ircUser, QString(modes[c]));
+       } else {
+         qWarning() << "Received MODE with too few parameters:" << serverDecode(params);
+       }
+       paramOffset++;
+      } else {
+       // regular channel modes
+       QString value;
+       Network::ChannelModeType modeType = network()->channelModeType(modes[c]);
+       if(modeType == Network::A_CHANMODE || modeType == Network::B_CHANMODE || (modeType == Network::C_CHANMODE && add)) {
+           if(paramOffset < params.count()) {
+             value = params[paramOffset];
+           } else {
+             qWarning() << "Received MODE with too few parameters:" << serverDecode(params);
+           }
+           paramOffset++;
+       }
+       
        if(add)
-         channel->addUserMode(ircUser, QString(modes[c]));
+         channel->addChannelMode(modes[c], value);
        else
-         channel->removeUserMode(ircUser, QString(modes[c]));
+         channel->removeChannelMode(modes[c], value);
       }
-      modeIndex++;
     }
     
   } else {
@@ -411,7 +434,6 @@ void IrcServerHandler::handle005(const QString &prefix, const QList<QByteArray>
   const int numParams = params.size();
   if(numParams < 1) {
     qWarning() << "IrcServerHandler::handle005(): received RPL_ISUPPORT (005) with too few parameters:" << serverDecode(params);
-    return;
   }
 
   QString rpl_isupport_suffix = serverDecode(params.last());
@@ -506,6 +528,30 @@ void IrcServerHandler::handle301(const QString &prefix, const QList<QByteArray>
   }
 }
 
+// 305  RPL_UNAWAY
+//      ":You are no longer marked as being away"
+void IrcServerHandler::handle305(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix);
+  IrcUser *me = network()->me();
+  if(me)
+    me->setAway(false);
+
+  if(!params.isEmpty())
+    emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", serverDecode(params[0]));
+}
+
+// 306  RPL_NOWAWAY
+//      ":You have been marked as being away"
+void IrcServerHandler::handle306(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix);
+  IrcUser *me = network()->me();
+  if(me)
+    me->setAway(true);
+
+  if(!params.isEmpty())
+    emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", serverDecode(params[0]));
+}
+
 /* RPL_WHOISSERVICE - "<user> is registered nick" */
 void IrcServerHandler::handle307(const QString &prefix, const QList<QByteArray> &params) {
   Q_UNUSED(prefix)
@@ -677,6 +723,49 @@ void IrcServerHandler::handle320(const QString &prefix, const QList<QByteArray>
   emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("[Whois] %1").arg(serverDecode(params).join(" ")));
 }
 
+/* RPL_LIST -  "<channel> <# visible> :<topic>" */
+void IrcServerHandler::handle322(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix)
+  QString channelName;
+  quint32 userCount = 0;
+  QString topic;
+  
+  int paramCount = params.count();
+  switch(paramCount) {
+  case 3:
+    topic = serverDecode(params[2]);
+  case 2:
+    userCount = serverDecode(params[1]).toUInt();
+  case 1:
+    channelName = serverDecode(params[0]);
+  default:
+    break;
+  }
+  if(!networkConnection()->coreSession()->ircListHelper()->addChannel(network()->networkId(), channelName, userCount, topic))
+    emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Channel %1 has %2 users. Topic is: %3").arg(channelName).arg(userCount).arg(topic));
+}
+
+/* RPL_LISTEND ":End of LIST" */
+void IrcServerHandler::handle323(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix)
+  Q_UNUSED(params)
+
+  if(!networkConnection()->coreSession()->ircListHelper()->endOfChannelList(network()->networkId()))
+    emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("End of channel list"));
+}
+       
+/* RPL_CHANNELMODEIS - "<channel> <mode> <mode params>" */
+void IrcServerHandler::handle324(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix);
+  handleMode(prefix, params);
+}
+
+/* RPL_??? - "<channel> <creation time (unix)>" */
+void IrcServerHandler::handle329(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix);
+  // FIXME implement this... 
+}
+
 /* RPL_NOTOPIC */
 void IrcServerHandler::handle331(const QString &prefix, const QList<QByteArray> &params) {
   Q_UNUSED(prefix);