Some new features like Login, Config.h and Idle message

svn path=/trunk/; revision=15752
This commit is contained in:
Maarten Bosma 2005-06-03 17:28:53 +00:00
parent 525d26d031
commit 5fd1b3d346
7 changed files with 321 additions and 161 deletions

View file

@ -12,18 +12,11 @@
#include "trim.h" #include "trim.h"
#include "IRCClient.h" #include "IRCClient.h"
#include "config.h"
using std::string; using std::string;
using std::vector; using std::vector;
#if defined(_DEBUG) && 0
const char* BOTNAME = "RoyBot";
const char* CHANNEL = "#RoyBotTest";
#else
const char* BOTNAME = "ArchBlackmann";
const char* CHANNEL = "#ReactOS";
#endif
//vector<string> tech, module, dev, stru, period, status, type, func, irql, curse, cursecop; //vector<string> tech, module, dev, stru, period, status, type, func, irql, curse, cursecop;
class List class List
@ -157,14 +150,46 @@ bool isop ( const string& who )
return false; return false;
} }
// do custom stuff with the IRCClient from your subclass via the provided callbacks... // do custom stuff with the IRCClient from your subclass via the provided callbacks...
class MyIRCClient : public IRCClient class MyIRCClient : public IRCClient
{ {
File flog; File flog;
clock_t brake_silence;
// wait another 30 mins to brake the silence
#define NOIDLE brake_silence = clock () + 30 * CLK_TCK * 60
void CheckIdle ( void )
{
while (true) // _inRun
{
while (clock() < brake_silence)
Sleep(10000);
string out = TaggedReply("idle");
if ( !strnicmp ( out.c_str(), "/me ", 4 ) )
Action ( CHANNEL, &out[4] );
else
PrivMsg ( CHANNEL, out );
NOIDLE;
}
}
static void THREADAPI CallMe ( MyIRCClient* irc )
{
irc->CheckIdle();
}
public: public:
MyIRCClient() MyIRCClient()
{ {
flog.open ( "arch.log", "w+" ); NOIDLE;
ThreadPool::Instance().Launch ( (ThreadPoolFunc*)MyIRCClient::CallMe, this );
flog.open ( "arch.log", "r+" );
} }
// see IRCClient.h for documentation on these callbacks... // see IRCClient.h for documentation on these callbacks...
bool OnConnected() bool OnConnected()
@ -173,7 +198,7 @@ public:
} }
bool OnJoin ( const string& user, const string& channel ) bool OnJoin ( const string& user, const string& channel )
{ {
printf ( "user '%s' joined channel '%s'\n", user.c_str(), channel.c_str() ); //printf ( "user '%s' joined channel '%s'\n", user.c_str(), channel.c_str() );
return true; return true;
} }
bool OnPart ( const std::string& user, const std::string& channel ) bool OnPart ( const std::string& user, const std::string& channel )
@ -207,11 +232,18 @@ public:
} }
bool OnPrivMsg ( const string& from, const string& text ) bool OnPrivMsg ( const string& from, const string& text )
{ {
//flog.flush();
printf ( "<%s> %s\n", from.c_str(), text.c_str() ); printf ( "<%s> %s\n", from.c_str(), text.c_str() );
flog.printf ( "<%s> %s\n", from.c_str(), text.c_str() ); flog.printf ( "<%s> %s\n", from.c_str(), text.c_str() );
if ( strnicmp ( text.c_str(), "!say ", 5 ) || !isop(from) )
if ( !isop(from) )
return PrivMsg ( from, "hey, your tongue doesn't belong there!" ); return PrivMsg ( from, "hey, your tongue doesn't belong there!" );
else if ( strnicmp ( text.c_str(), "!say ", 5 ) )
return PrivMsg ( from, "Talk to me on normal Chanel" );
string say = trim(&text[5]); string say = trim(&text[5]);
if ( !strnicmp ( say.c_str(), "/me ", 4 ) ) if ( !strnicmp ( say.c_str(), "/me ", 4 ) )
return Action ( CHANNEL, trim(&say[4]) ); return Action ( CHANNEL, trim(&say[4]) );
else else
@ -219,27 +251,37 @@ public:
} }
bool OnChannelMsg ( const string& channel, const string& from, const string& text ) bool OnChannelMsg ( const string& channel, const string& from, const string& text )
{ {
fflush ( flog );
printf ( "%s <%s> %s\n", channel.c_str(), from.c_str(), text.c_str() ); printf ( "%s <%s> %s\n", channel.c_str(), from.c_str(), text.c_str() );
flog.printf ( "%s <%s> %s\n", channel.c_str(), from.c_str(), text.c_str() ); flog.printf ( "%s <%s> %s\n", channel.c_str(), from.c_str(), text.c_str() );
NOIDLE; // add 30 mins till idle
bool found_name = false; bool found_name = false;
string text2 ( text ); string text2 ( text );
strlwr ( &text2[0] ); strlwr ( &text2[0] );
if ( !strnicmp ( text.c_str(), BOTNAME, strlen(BOTNAME) ) ) if ( !strnicmp ( text.c_str(), BOTNAME, strlen(BOTNAME) ) )
found_name = true; found_name = true;
else if ( !strnicmp ( text.c_str(), "arch ", 5 ) )
found_name = true; string s ( text );
if ( found_name ) if ( found_name )
{
string s ( text );
gobble ( s, " \t" ); // remove bot name gobble ( s, " \t" ); // remove bot name
found_name = true;
// command
if ( s[0] == '!' ) if ( s[0] == '!' )
{ {
bool from_op = isop(from); bool from_op = isop(from);
string cmd = gobble ( s, " \t" ); string cmd = gobble ( s, " \t" );
if ( !from_op )
// from all
if ( false && cmd == "!svn" && from == "TechBot" ) // || cmd == "!help" && !TechBotOnline
{
PrivMsg ( channel, "For my help try !what." );
}
// from normel user
else if ( !from_op )
{ {
if ( cmd == "!grovel" ) if ( cmd == "!grovel" )
{ {
@ -249,9 +291,63 @@ public:
else else
return PrivMsg ( channel, out ); return PrivMsg ( channel, out );
} }
return PrivMsg ( channel, ssprintf("%s: I don't take commands from non-ops",from.c_str()) );
else if ( cmd == "!what" )
{
return PrivMsg ( channel, ssprintf("For you, %s, I only support the \"!grovel\" command.", from.c_str()).c_str() );
} }
if ( cmd == "!add" )
else if ( cmd == "!grovel" || cmd == "!kiss" || cmd == "!hug"
|| cmd == "!give" || cmd == "!what" || cmd == "!add" || cmd == "!remove" )
{
PrivMsg ( channel, ssprintf("%s: I only take commands from ops",from.c_str()) );
}
}
// from op
else if ( cmd == "!grovel" )
{
string out = ssprintf(TaggedReply("grovel").c_str(),from.c_str());
if ( !strnicmp ( out.c_str(), "/me ", 4 ) )
return Action ( channel, &out[4] );
else
return PrivMsg ( channel, out );
}
else if ( cmd == "!kiss" )
{
if ( s.size() )
return Action ( channel, ssprintf("kisses %s",s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
else if ( cmd == "!hug" )
{
if ( s.size() )
return Action ( channel, ssprintf("hugs %s",s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
else if ( cmd == "!give" )
{
string who = gobble(s," \t");
if ( who.size() && s.size() )
return Action ( channel, ssprintf("gives %s a %s",who.c_str(),s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
else if ( cmd == "!what" )
{
PrivMsg ( channel, "For ops I support the following commands:" );
PrivMsg ( channel, "!grovel" );
PrivMsg ( channel, "!kiss" );
PrivMsg ( channel, "!hug" );
PrivMsg ( channel, "!give" );
PrivMsg ( channel, "!say (the input is a private message)" );
PrivMsg ( channel, "!add" );
PrivMsg ( channel, "!remove" );
PrivMsg ( channel, " - for more info see wiki" );
}
else if ( cmd == "!add" )
{ {
string listname = gobble ( s, " \t" ); string listname = gobble ( s, " \t" );
int i = GetListIndex ( listname.c_str() ); int i = GetListIndex ( listname.c_str() );
@ -313,46 +409,18 @@ public:
} }
return PrivMsg ( channel, ssprintf("%s: entry doesn't exist in list '%s'",from.c_str(),listname.c_str()) ); return PrivMsg ( channel, ssprintf("%s: entry doesn't exist in list '%s'",from.c_str(),listname.c_str()) );
} }
else if ( cmd == "!grovel" )
{
string out = ssprintf(TaggedReply("grovel").c_str(),from.c_str());
if ( !strnicmp ( out.c_str(), "/me ", 4 ) )
return Action ( channel, &out[4] );
else else
return PrivMsg ( channel, out );
}
else if ( cmd == "!kiss" )
{ {
if ( s.size() ) if (found_name)
return Action ( channel, ssprintf("kisses %s",s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) ); return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
} }
else if ( cmd == "!hug" )
{ } // if (command)
if ( s.size() )
return Action ( channel, ssprintf("hugs %s",s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
else if ( cmd == "!give" )
{
string who = gobble(s," \t");
if ( who.size() && s.size() )
return Action ( channel, ssprintf("gives %s a %s",who.c_str(),s.c_str()) );
else
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
else
{
return PrivMsg ( channel, ssprintf("%s: huh?",from.c_str()) );
}
}
}
bool found_curse = false; bool found_curse = false;
static vector<string>& curse = GetList("curse").list; static vector<string>& curse = GetList("curse").list;
text2 = ssprintf(" %s ",text2.c_str()); text2 = " " + text2 + " ";
for ( int i = 0; i < curse.size() && !found_curse; i++ ) for ( int i = 0; i < curse.size() && !found_curse; i++ )
{ {
if ( strstr ( text2.c_str(), curse[i].c_str() ) ) if ( strstr ( text2.c_str(), curse[i].c_str() ) )
@ -363,7 +431,12 @@ public:
static List& cursecop = GetList("cursecop"); static List& cursecop = GetList("cursecop");
return PrivMsg ( channel, ssprintf("%s: %s", from.c_str(), ListRand(cursecop)) ); return PrivMsg ( channel, ssprintf("%s: %s", from.c_str(), ListRand(cursecop)) );
} }
else if ( found_name )
string botname (BOTNAME);
strlwr ( &botname[0] );
//botname = " " + botname + " ";
if ( strstr(text2.c_str(), botname.c_str()) || strstr(text2.c_str(), " arch ") || found_name )
{ {
string out = ssprintf("%s: %s", from.c_str(), TaggedReply("tech").c_str()); string out = ssprintf("%s: %s", from.c_str(), TaggedReply("tech").c_str());
flog.printf ( "TECH-REPLY: %s\n", out.c_str() ); flog.printf ( "TECH-REPLY: %s\n", out.c_str() );
@ -373,7 +446,9 @@ public:
return PrivMsg ( channel, out ); return PrivMsg ( channel, out );
} }
return true; return true;
}
} // On Chanel Message
bool OnChannelMode ( const string& channel, const string& mode ) bool OnChannelMode ( const string& channel, const string& mode )
{ {
//printf ( "OnChannelMode(%s,%s)\n", channel.c_str(), mode.c_str() ); //printf ( "OnChannelMode(%s,%s)\n", channel.c_str(), mode.c_str() );
@ -439,6 +514,16 @@ public:
//printf ( "\n" ); //printf ( "\n" );
return true; return true;
} }
bool OnKick ( void )
{
Join(CHANNEL);
return true;
}
bool OnBanned ( const std::string& channel )
{
Sleep(10000);
return Join(CHANNEL);
}
}; };
int main ( int argc, char** argv ) int main ( int argc, char** argv )
@ -461,50 +546,59 @@ int main ( int argc, char** argv )
ImportList ( "cursecop", false ); ImportList ( "cursecop", false );
ImportList ( "grovel", false ); ImportList ( "grovel", false );
ImportList ( "nogrovel", false ); ImportList ( "nogrovel", false );
ImportList ( "idle", false );
#ifdef _DEBUG #ifdef _DEBUG
printf ( "initializing IRCClient debugging\n" ); printf ( "initializing IRCClient debugging\n" );
IRCClient::SetDebug ( true ); IRCClient::SetDebug ( true );
#endif//_DEBUG #endif//_DEBUG
while (true)
{
printf ( "calling suStartup()\n" ); printf ( "calling suStartup()\n" );
suStartup(); suStartup();
printf ( "creating IRCClient object\n" ); printf ( "creating IRCClient object\n" );
MyIRCClient irc; MyIRCClient irc;
printf ( "connecting to freenode\n" ); printf ( "connecting to freenode\n" );
//const char* server = "212.204.214.114"; if ( !irc.Connect ( SERVER ) ) // irc.freenode.net
const char* server = "irc.freenode.net";
if ( !irc.Connect ( server ) ) // irc.freenode.net
{ {
printf ( "couldn't connect to server\n" ); printf ( "couldn't connect to server\n" );
return -1; Sleep(10000);
continue;
} }
printf ( "sending user command\n" ); printf ( "sending user command\n" );
if ( !irc.User ( BOTNAME, "", "irc.freenode.net", BOTNAME ) ) if ( !irc.User ( BOTNAME, "reactos.com", SERVER, "ArchBlackmann" ) )
{ {
printf ( "USER command failed\n" ); printf ( "USER command failed, retying ...\n" );
return -1; Sleep(10000);
continue;
} }
printf ( "sending nick\n" ); printf ( "sending nick\n" );
if ( !irc.Nick ( BOTNAME ) ) if ( !irc.Nick ( BOTNAME ) )
{ {
printf ( "NICK command failed\n" ); printf ( "NICK command failed, retying ...\n" );
return -1; Sleep(10000);
continue;
} }
printf ( "setting mode\n" ); printf ( "setting mode\n" );
if ( !irc.Mode ( "+i" ) ) if ( !irc.Mode ( MODE ) )
{ {
printf ( "MODE command failed\n" ); printf ( "MODE command failed, retying ...\n" );
return -1; Sleep(10000);
continue;
} }
printf ( "joining channel\n" ); printf ( "joining channel\n" );
if ( !irc.Join ( CHANNEL ) ) if ( !irc.Join ( CHANNEL ) )
{ {
printf ( "JOIN command failed\n" ); printf ( "JOIN command failed, retying ...\n" );
return -1; Sleep(10000);
continue;
} }
printf ( "entering irc client processor\n" ); printf ( "entering irc client processor\n" );
irc.Run ( false ); // do the processing in this thread... irc.Run ( false ); // do the processing in this thread...
}
return 0; return 0;
} }

View file

@ -110,6 +110,10 @@ SOURCE=.\chomp.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\config.h
# End Source File
# Begin Source File
SOURCE=.\cram_md5.cpp SOURCE=.\cram_md5.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View file

@ -16,6 +16,7 @@
#include "chomp.h" #include "chomp.h"
#include "SplitJoin.h" #include "SplitJoin.h"
#include "base64.h" #include "base64.h"
#include "config.h"
using std::string; using std::string;
using std::stringstream; using std::stringstream;
@ -23,6 +24,8 @@ using std::vector;
bool IRCClient::_debug = true; bool IRCClient::_debug = true;
// see rfc1459 for IRC-Protocoll Reference
IRCClient::IRCClient() IRCClient::IRCClient()
: _timeout(10*60*1000), _inRun(false) : _timeout(10*60*1000), _inRun(false)
{ {
@ -51,7 +54,9 @@ bool
IRCClient::Nick ( const string& nick ) IRCClient::Nick ( const string& nick )
{ {
_nick = nick; _nick = nick;
return Send ( "NICK " + _nick + "\n" ); Send ( "NICK " + _nick + "\n" );
PrivMsg ("NickServ", "IDENTIFY " + (string)PASS);
return true;
} }
bool bool
@ -296,6 +301,7 @@ int IRCClient::Run ( bool launch_thread )
} }
else if ( cmd == "join" ) else if ( cmd == "join" )
{ {
mychannel = text;
OnJoin ( src, text ); OnJoin ( src, text );
} }
else if ( cmd == "part" ) else if ( cmd == "part" )
@ -306,14 +312,20 @@ int IRCClient::Run ( bool launch_thread )
{ {
OnNick ( src, text ); OnNick ( src, text );
} }
else if ( cmd == "kick" )
{
OnKick ();
}
else if ( isdigit(cmd[0]) ) else if ( isdigit(cmd[0]) )
{ {
int i = atoi(cmd.c_str()); int i = atoi(cmd.c_str());
switch ( i ) switch ( i )
{ {
case 1: // "Welcome!" - i.e. it's okay to issue commands now... case 1: // "Welcome!" - i.e. it's okay to issue commands now...
OnConnected(); OnConnected();
break; break;
case 353: // user list for channel.... case 353: // user list for channel....
{ {
p = text.c_str(); p = text.c_str();
@ -336,6 +348,7 @@ int IRCClient::Run ( bool launch_thread )
OnChannelUsers ( channel, users ); OnChannelUsers ( channel, users );
} }
break; break;
case 366: // END of user list for channel case 366: // END of user list for channel
{ {
p = text.c_str(); p = text.c_str();
@ -345,6 +358,38 @@ int IRCClient::Run ( bool launch_thread )
OnEndChannelUsers ( channel ); OnEndChannelUsers ( channel );
} }
break; break;
case 474: // You are banned
{
p = text.c_str();
p2 = strpbrk ( p, " :" );
if ( !p2 ) continue;
string channel ( p, p2-p );
OnBanned ( channel );
}
break;
case 433: // Nick in Use
{
string nick = _nick;
Nick (nick + "_");
PrivMsg ("NickServ", "GHOST " + nick + " " + PASS);
// HACK HACK HACK
Mode ( "+i" );
Join ( CHANNEL ); // this is because IRC client does not review if his commands were sucessfull
Sleep ( 1000 );
Nick ( nick );
}
break;
case 2: //MOTD
case 376: //MOTD
case 372:
break;
default: default:
if ( _debug ) printf ( "unknown command %i: %s", i, buf.c_str() ); if ( _debug ) printf ( "unknown command %i: %s", i, buf.c_str() );
break; break;

View file

@ -12,9 +12,11 @@
class IRCClient : public suBufferedRecvSocket class IRCClient : public suBufferedRecvSocket
{ {
public: public:
IRCClient(); IRCClient();
std::string mychannel;
static bool GetDebug() { return _debug; } static bool GetDebug() { return _debug; }
static bool SetDebug ( bool debug ) { bool old = _debug; _debug = debug; return old; } static bool SetDebug ( bool debug ) { bool old = _debug; _debug = debug; return old; }
@ -99,6 +101,12 @@ public:
virtual bool OnChannelUsers ( const std::string& channel, const std::vector<std::string>& users ) virtual bool OnChannelUsers ( const std::string& channel, const std::vector<std::string>& users )
{ return true; } { return true; }
// OnKick: if the client has been kicked
virtual bool OnKick ( void ) { return true; }
// OnKick: if the client has been kicked
virtual bool OnBanned ( const std::string& channel ) { return true; }
// notification that you have received the entire list of users for a channel // notification that you have received the entire list of users for a channel
virtual bool OnEndChannelUsers ( const std::string& channel ) { return true; } virtual bool OnEndChannelUsers ( const std::string& channel ) { return true; }

View file

@ -0,0 +1,7 @@
#define SERVER "irc.freenode.net"
#define BOTNAME "ArchBlackmann"
#define CHANNEL "#ReactOS"
#define MODE "+i"
#define PASS "ilovebunnies"

View file

@ -24,3 +24,4 @@ goat.cx
ekush ekush
akshor akshor
poop poop
guten morgen

View file

@ -0,0 +1 @@
/me is bored