|
|
|
/*
|
|
|
|
kirc_commands.h - IRC Client
|
|
|
|
|
|
|
|
Copyright (c) 2003-2004 by Michel Hermier <michel.hermier@wanadoo.fr>
|
|
|
|
Copyright (c) 2002 by Nick Betcher <nbetcher@kde.org>
|
|
|
|
Copyright (c) 2003 by Jason Keirstead <jason@keirstead.org>
|
|
|
|
|
|
|
|
Kopete (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>
|
|
|
|
|
|
|
|
*************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
*************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kircengine.h"
|
|
|
|
|
|
|
|
#include <kextsock.h>
|
|
|
|
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
using namespace KIRC;
|
|
|
|
|
|
|
|
void Engine::bindCommands()
|
|
|
|
{
|
|
|
|
bind("ERROR", this, TQT_SLOT(error(KIRC::Message &)), 0, 0);
|
|
|
|
bind("JOIN", this, TQT_SLOT(join(KIRC::Message &)), 0, 1);
|
|
|
|
bind("KICK", this, TQT_SLOT(kick(KIRC::Message &)), 2, 2);
|
|
|
|
bind("NICK", this, TQT_SLOT(nick(KIRC::Message &)), 0, 0);
|
|
|
|
bind("MODE", this, TQT_SLOT(mode(KIRC::Message &)), 1, 1);
|
|
|
|
bind("NOTICE", this, TQT_SLOT(notice(KIRC::Message &)), 1, 1);
|
|
|
|
bind("PART", this, TQT_SLOT(part(KIRC::Message &)), 1, 1);
|
|
|
|
bind("PING", this, TQT_SLOT(ping(KIRC::Message &)), 0, 0);
|
|
|
|
bind("PONG", this, TQT_SLOT(pong(KIRC::Message &)), 0, 0);
|
|
|
|
bind("PRIVMSG", this, TQT_SLOT(privmsg(KIRC::Message &)), 1, 1);
|
|
|
|
bind("QUIT", this, TQT_SLOT(quit(KIRC::Message &)), 0, 0);
|
|
|
|
// bind("SQUIT", this, TQT_SLOT(squit(KIRC::Message &)), 1, 1);
|
|
|
|
bind("TOPIC", this, TQT_SLOT(topic(KIRC::Message &)), 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::away(bool isAway, const TQString &awayMessage)
|
|
|
|
{
|
|
|
|
if(isAway)
|
|
|
|
if( !awayMessage.isEmpty() )
|
|
|
|
writeMessage("AWAY", TQString(), awayMessage);
|
|
|
|
else
|
|
|
|
writeMessage("AWAY", TQString(), TQString::fromLatin1("I'm away."));
|
|
|
|
else
|
|
|
|
writeMessage("AWAY", TQString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Really handle this message
|
|
|
|
void Engine::error(Message &)
|
|
|
|
{
|
|
|
|
setStatus(Closing);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::ison(const TQStringList &nickList)
|
|
|
|
{
|
|
|
|
if (!nickList.isEmpty())
|
|
|
|
{
|
|
|
|
TQString statement = TQString::fromLatin1("ISON");
|
|
|
|
for (TQStringList::ConstIterator it = nickList.begin(); it != nickList.end(); ++it)
|
|
|
|
{
|
|
|
|
if ((statement.length()+(*it).length())>509) // 512(max buf)-2("\r\n")-1(<space separator>)
|
|
|
|
{
|
|
|
|
writeMessage(statement);
|
|
|
|
statement = TQString::fromLatin1("ISON ") + (*it);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
statement.append(TQChar(' ') + (*it));
|
|
|
|
}
|
|
|
|
writeMessage(statement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::join(const TQString &name, const TQString &key)
|
|
|
|
{
|
|
|
|
TQStringList args(name);
|
|
|
|
if ( !key.isNull() )
|
|
|
|
args << key;
|
|
|
|
|
|
|
|
writeMessage("JOIN", args);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::join(Message &msg)
|
|
|
|
{
|
|
|
|
/* RFC say: "( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0""
|
|
|
|
* suspected: ":<channel> *(" "/"," <channel>)"
|
|
|
|
* assumed ":<channel>"
|
|
|
|
* This is the response of someone joining a channel.
|
|
|
|
* Remember that this will be emitted when *you* /join a room for the first time */
|
|
|
|
|
|
|
|
if (msg.argsSize()==1)
|
|
|
|
emit incomingJoinedChannel(Kopete::Message::unescape(msg.arg(0)), msg.nickFromPrefix());
|
|
|
|
else
|
|
|
|
emit incomingJoinedChannel(Kopete::Message::unescape(msg.suffix()), msg.nickFromPrefix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::kick(const TQString &user, const TQString &channel, const TQString &reason)
|
|
|
|
{
|
|
|
|
writeMessage("KICK", TQStringList(channel) << user << reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::kick(Message &msg)
|
|
|
|
{
|
|
|
|
/* The given user is kicked.
|
|
|
|
* "<channel> *( "," <channel> ) <user> *( "," <user> ) [<comment>]"
|
|
|
|
*/
|
|
|
|
emit incomingKick( Kopete::Message::unescape(msg.arg(0)), msg.nickFromPrefix(), msg.arg(1), msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::mode(const TQString &target, const TQString &mode)
|
|
|
|
{
|
|
|
|
writeMessage("MODE", TQStringList(target) << mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::mode(Message &msg)
|
|
|
|
{
|
|
|
|
/* Change the mode of a user.
|
|
|
|
* "<nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )"
|
|
|
|
*/
|
|
|
|
TQStringList args = msg.args();
|
|
|
|
args.pop_front();
|
|
|
|
if( Entity::isChannel( msg.arg(0) ) )
|
|
|
|
emit incomingChannelModeChange( msg.arg(0), msg.nickFromPrefix(), args.join(" "));
|
|
|
|
else
|
|
|
|
emit incomingUserModeChange( msg.nickFromPrefix(), args.join(" "));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::nick(const TQString &newNickname)
|
|
|
|
{
|
|
|
|
m_PendingNick = newNickname;
|
|
|
|
writeMessage("NICK", newNickname);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::nick(Message &msg)
|
|
|
|
{
|
|
|
|
/* Nick name of a user changed
|
|
|
|
* "<nickname>" */
|
|
|
|
TQString oldNick = msg.prefix().section('!', 0, 0);
|
|
|
|
TQString newNick = msg.suffix();
|
|
|
|
|
|
|
|
if( codecs[ oldNick ] )
|
|
|
|
{
|
|
|
|
TQTextCodec *c = codecs[ oldNick ];
|
|
|
|
codecs.remove( oldNick );
|
|
|
|
codecs.insert( newNick, c );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldNick.lower() == m_Nickname.lower())
|
|
|
|
{
|
|
|
|
emit successfullyChangedNick(oldNick, msg.suffix());
|
|
|
|
m_Nickname = msg.suffix();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
emit incomingNickChange(oldNick, msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::part(const TQString &channel, const TQString &reason)
|
|
|
|
{
|
|
|
|
/* This will part a channel with 'reason' as the reason for parting
|
|
|
|
*/
|
|
|
|
writeMessage("PART", channel, reason);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::part(Message &msg)
|
|
|
|
{
|
|
|
|
/* This signal emits when a user parts a channel
|
|
|
|
* "<channel> *( "," <channel> ) [ <Part Message> ]"
|
|
|
|
*/
|
|
|
|
kdDebug(14120) << "User parting" << endl;
|
|
|
|
emit incomingPartedChannel(msg.arg(0), msg.nickFromPrefix(), msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::pass(const TQString &password)
|
|
|
|
{
|
|
|
|
writeMessage("PASS", password);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::ping(Message &msg)
|
|
|
|
{
|
|
|
|
writeMessage("PONG", msg.arg(0), msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::pong(Message &/*msg*/)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::quit(const TQString &reason, bool /*now*/)
|
|
|
|
{
|
|
|
|
kdDebug(14120) << k_funcinfo << reason << endl;
|
|
|
|
|
|
|
|
if (isDisconnected())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (isConnected())
|
|
|
|
writeMessage("QUIT", TQString(), reason);
|
|
|
|
|
|
|
|
setStatus(Closing);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::quit(Message &msg)
|
|
|
|
{
|
|
|
|
/* This signal emits when a user quits irc.
|
|
|
|
*/
|
|
|
|
kdDebug(14120) << "User quiting" << endl;
|
|
|
|
emit incomingQuitIRC(msg.prefix(), msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::user(const TQString &newUserName, const TQString &hostname, const TQString &newRealName)
|
|
|
|
{
|
|
|
|
/* RFC1459: "<username> <hostname> <servername> <realname>"
|
|
|
|
* The USER command is used at the beginning of connection to specify
|
|
|
|
* the username, hostname and realname of a new user.
|
|
|
|
* hostname is usualy set to "127.0.0.1" */
|
|
|
|
m_Username = newUserName;
|
|
|
|
m_realName = newRealName;
|
|
|
|
|
|
|
|
writeMessage("USER", TQStringList(m_Username) << hostname << m_Host, m_realName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::user(const TQString &newUserName, TQ_UINT8 mode, const TQString &newRealName)
|
|
|
|
{
|
|
|
|
/* RFC2812: "<user> <mode> <unused> <realname>"
|
|
|
|
* mode is a numeric value (from a bit mask).
|
|
|
|
* 0x00 normal
|
|
|
|
* 0x04 request +w
|
|
|
|
* 0x08 request +i */
|
|
|
|
m_Username = newUserName;
|
|
|
|
m_realName = newRealName;
|
|
|
|
|
|
|
|
writeMessage("USER", TQStringList(m_Username) << TQString::number(mode) << TQChar('*'), m_realName);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::topic(const TQString &channel, const TQString &topic)
|
|
|
|
{
|
|
|
|
writeMessage("TOPIC", channel, topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::topic(Message &msg)
|
|
|
|
{
|
|
|
|
/* The topic of a channel changed. emit the channel, new topic, and the person who changed it.
|
|
|
|
* "<channel> [ <topic> ]"
|
|
|
|
*/
|
|
|
|
emit incomingTopicChange(msg.arg(0), msg.nickFromPrefix(), msg.suffix());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::list()
|
|
|
|
{
|
|
|
|
writeMessage("LIST", TQString());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::motd(const TQString &server)
|
|
|
|
{
|
|
|
|
writeMessage("MOTD", server);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::privmsg(const TQString &contact, const TQString &message)
|
|
|
|
{
|
|
|
|
writeMessage("PRIVMSG", contact, message, codecForNick( contact ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::privmsg(Message &msg)
|
|
|
|
{
|
|
|
|
/* This is a signal that indicates there is a new message.
|
|
|
|
* This can be either from a channel or from a specific user. */
|
|
|
|
Message m = msg;
|
|
|
|
if (!m.suffix().isEmpty())
|
|
|
|
{
|
|
|
|
TQString user = m.arg(0);
|
|
|
|
TQString message = m.suffix();
|
|
|
|
const TQTextCodec *codec = codecForNick( user );
|
|
|
|
if (codec != defaultCodec) {
|
|
|
|
m.decodeAgain( codec );
|
|
|
|
message = m.suffix();
|
|
|
|
}
|
|
|
|
if (Entity::isChannel(user))
|
|
|
|
emit incomingMessage(m.nickFromPrefix(), Kopete::Message::unescape(m.arg(0)), message );
|
|
|
|
else
|
|
|
|
emit incomingPrivMessage(m.nickFromPrefix(), Kopete::Message::unescape(m.arg(0)), message );
|
|
|
|
// emit receivedMessage(PrivateMessage, msg.entityFrom(), msg.entityTo(), message);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m.hasCtcpMessage() )
|
|
|
|
{
|
|
|
|
invokeCtcpCommandOfMessage(m_ctcpQueries, m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::notice(const TQString &target, const TQString &message)
|
|
|
|
{
|
|
|
|
writeMessage("NOTICE", target, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::notice(Message &msg)
|
|
|
|
{
|
|
|
|
if(!msg.suffix().isEmpty())
|
|
|
|
emit incomingNotice(msg.prefix(), msg.suffix());
|
|
|
|
|
|
|
|
if(msg.hasCtcpMessage())
|
|
|
|
invokeCtcpCommandOfMessage(m_ctcpReplies, msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::whois(const TQString &user)
|
|
|
|
{
|
|
|
|
writeMessage("WHOIS", user);
|
|
|
|
}
|