4 #pragma warning ( disable : 4786 )
14 #include "IRCClient.h"
20 //vector<string> tech, module, dev, stru, period, status, type, func, irql, curse, cursecop;
27 std::vector
<std::string
> list
;
31 List ( const char* _name
, bool _macro
) : name(_name
), macro(_macro
)
33 tag
= ssprintf("%%%s%%",_name
);
41 void ImportList ( const char* listname
, bool macro
)
43 lists
.push_back ( List ( listname
, macro
) );
44 List
& list
= lists
.back();
45 File
f ( ssprintf("%s.txt",listname
).c_str(), "r" );
47 while ( f
.next_line ( line
, true ) )
48 list
.list
.push_back ( line
);
51 const char* ListRand ( List
& list
)
53 vector
<string
>& l
= list
.list
;
56 static string nothing
;
57 nothing
= ssprintf ( "<list '%s' empty>", list
.name
.c_str() );
58 return nothing
.c_str();
60 else if ( l
.size() == 1 )
63 while ( sel
== list
.last
)
64 sel
= rand()%l
.size();
66 return l
[sel
].c_str();
69 const char* ListRand ( int i
)
71 return ListRand ( lists
[i
] );
74 int GetListIndex ( const char* listname
)
76 for ( int i
= 0; i
< lists
.size(); i
++ )
78 if ( !stricmp ( lists
[i
].name
.c_str(), listname
) )
84 List
& GetList ( const char* listname
)
86 return lists
[GetListIndex(listname
)];
89 const char* ListRand ( const char* list
)
91 int i
= GetListIndex ( list
);
97 string
TaggedReply ( const char* listname
)
99 string t
= ListRand(listname
);
101 const char* p
= t
.c_str();
107 for ( int i
= 0; i
< lists
.size() && !found
; i
++ )
109 if ( lists
[i
].macro
&& !strnicmp ( p
, lists
[i
].tag
.c_str(), lists
[i
].tag
.size() ) )
112 p
+= lists
[i
].tag
.size();
119 const char* p2
= strchr ( p
, '%' );
124 out
+= string ( p
, p2
-p
);
131 string
gobble ( string
& s
, const char* delim
)
133 const char* p
= s
.c_str();
134 p
+= strspn ( p
, delim
);
135 const char* p2
= strpbrk ( p
, delim
);
136 if ( !p2
) p2
= p
+ strlen(p
);
137 string
out ( p
, p2
-p
);
138 p2
+= strspn ( p2
, delim
);
143 bool isop ( const string
& who
)
145 for ( int i
= 0; i
< ops
.size(); i
++ )
154 // do custom stuff with the IRCClient from your subclass via the provided callbacks...
155 class MyIRCClient
: public IRCClient
158 clock_t brake_silence
;
160 // wait another 30 mins to brake the silence
161 #define NOIDLE brake_silence = clock () + 30 * CLK_TCK * 60
163 void CheckIdle ( void )
165 while (true) // _inRun
167 while (clock() < brake_silence
)
170 string out
= TaggedReply("idle");
172 if ( !strnicmp ( out
.c_str(), "/me ", 4 ) )
173 Action ( CHANNEL
, &out
[4] );
175 PrivMsg ( CHANNEL
, out
);
181 static void THREADAPI
CallMe ( MyIRCClient
* irc
)
191 ThreadPool::Instance().Launch ( (ThreadPoolFunc
*)MyIRCClient::CallMe
, this );
192 flog
.open ( "arch.log", "r+" );
194 // see IRCClient.h for documentation on these callbacks...
199 bool OnJoin ( const string
& user
, const string
& channel
)
201 //printf ( "user '%s' joined channel '%s'\n", user.c_str(), channel.c_str() );
204 bool OnPart ( const std::string
& user
, const std::string
& channel
)
206 for ( int i
= 0; i
< ops
.size(); i
++ )
208 if ( ops
[i
] == user
)
210 printf ( "remove '%s' to ops list\n", user
.c_str() );
211 ops
.erase ( &ops
[i
] );
216 bool OnNick ( const std::string
& oldNick
, const std::string
& newNick
)
218 for ( int i
= 0; i
< ops
.size(); i
++ )
220 if ( ops
[i
] == oldNick
)
222 printf ( "op '%s' changed nick to '%s'\n", oldNick
.c_str(), newNick
.c_str() );
229 bool OnEndChannelUsers ( const string
& channel
)
233 bool OnPrivMsg ( const string
& from
, const string
& text
)
236 printf ( "<%s> %s\n", from
.c_str(), text
.c_str() );
237 flog
.printf ( "<%s> %s\n", from
.c_str(), text
.c_str() );
240 return PrivMsg ( from
, "hey, your tongue doesn't belong there!" );
242 else if ( strnicmp ( text
.c_str(), "!say ", 5 ) )
243 return PrivMsg ( from
, "Talk to me on normal Chanel" );
245 string say
= trim(&text
[5]);
247 if ( !strnicmp ( say
.c_str(), "/me ", 4 ) )
248 return Action ( CHANNEL
, trim(&say
[4]) );
250 return PrivMsg ( CHANNEL
, trim(say
) );
252 bool OnChannelMsg ( const string
& channel
, const string
& from
, const string
& text
)
255 printf ( "%s <%s> %s\n", channel
.c_str(), from
.c_str(), text
.c_str() );
256 flog
.printf ( "%s <%s> %s\n", channel
.c_str(), from
.c_str(), text
.c_str() );
257 NOIDLE
; // add 30 mins till idle
259 bool found_name
= false;
260 string
text2 ( text
);
261 strlwr ( &text2
[0] );
263 if ( !strnicmp ( text
.c_str(), BOTNAME
, strlen(BOTNAME
) ) )
269 gobble ( s
, " \t" ); // remove bot name
274 bool from_op
= isop(from
);
275 string cmd
= gobble ( s
, " \t" );
278 if ( false && cmd
== "!svn" && from
== "TechBot" ) // || cmd == "!help" && !TechBotOnline
280 PrivMsg ( channel
, "For my help try !what." );
286 if ( cmd
== "!grovel" )
288 string out
= ssprintf(TaggedReply("nogrovel").c_str(),from
.c_str());
289 if ( !strnicmp ( out
.c_str(), "/me ", 4 ) )
290 return Action ( channel
, &out
[4] );
292 return PrivMsg ( channel
, out
);
295 else if ( cmd
== "!what" )
297 return PrivMsg ( channel
, ssprintf("For you, %s, I only support the \"!grovel\" command.", from
.c_str()).c_str() );
300 else if ( cmd
== "!grovel" || cmd
== "!kiss" || cmd
== "!hug"
301 || cmd
== "!give" || cmd
== "!what" || cmd
== "!add" || cmd
== "!remove" )
303 PrivMsg ( channel
, ssprintf("%s: I only take commands from ops",from
.c_str()) );
308 else if ( cmd
== "!grovel" )
310 string out
= ssprintf(TaggedReply("grovel").c_str(),from
.c_str());
311 if ( !strnicmp ( out
.c_str(), "/me ", 4 ) )
312 return Action ( channel
, &out
[4] );
314 return PrivMsg ( channel
, out
);
316 else if ( cmd
== "!kiss" )
319 return Action ( channel
, ssprintf("kisses %s",s
.c_str()) );
321 return PrivMsg ( channel
, ssprintf("%s: huh?",from
.c_str()) );
323 else if ( cmd
== "!hug" )
326 return Action ( channel
, ssprintf("hugs %s",s
.c_str()) );
328 return PrivMsg ( channel
, ssprintf("%s: huh?",from
.c_str()) );
330 else if ( cmd
== "!give" )
332 string who
= gobble(s
," \t");
333 if ( who
.size() && s
.size() )
334 return Action ( channel
, ssprintf("gives %s a %s",who
.c_str(),s
.c_str()) );
336 return PrivMsg ( channel
, ssprintf("%s: huh?",from
.c_str()) );
338 else if ( cmd
== "!what" )
340 PrivMsg ( channel
, "For ops I support the following commands:" );
341 PrivMsg ( channel
, "!grovel" );
342 PrivMsg ( channel
, "!kiss" );
343 PrivMsg ( channel
, "!hug" );
344 PrivMsg ( channel
, "!give" );
345 PrivMsg ( channel
, "!say (the input is a private message)" );
346 PrivMsg ( channel
, "!add" );
347 PrivMsg ( channel
, "!remove" );
348 PrivMsg ( channel
, " - for more info see wiki" );
350 else if ( cmd
== "!add" )
352 string listname
= gobble ( s
, " \t" );
353 int i
= GetListIndex ( listname
.c_str() );
355 return PrivMsg ( channel
, ssprintf("%s: I don't have a list named '%s'",from
.c_str(),listname
.c_str()) );
356 List
& list
= lists
[i
];
357 if ( s
[0] == '\"' || s
[0] == '\'' )
360 const char* p
= &s
[1];
361 const char* p2
= strchr ( p
, delim
);
363 return PrivMsg ( channel
, ssprintf("%s: Couldn't add, unmatched quotes",from
.c_str()) );
364 s
= string ( p
, p2
-p
);
366 for ( i
= 0; i
< list
.list
.size(); i
++ )
368 if ( list
.list
[i
] == s
)
369 return PrivMsg ( channel
, ssprintf("%s: entry already exists in list '%s'",from
.c_str(),listname
.c_str()) );
371 if ( !stricmp ( listname
.c_str(), "curse" ) )
373 list
.list
.push_back ( s
);
375 File
f ( ssprintf("%s.txt",list
.name
.c_str()), "w" );
376 for ( i
= 0; i
< list
.list
.size(); i
++ )
377 f
.printf ( "%s\n", list
.list
[i
].c_str() );
379 return PrivMsg ( channel
, ssprintf("%s: entry added to list '%s'",from
.c_str(),listname
.c_str()) );
381 else if ( cmd
== "!remove" )
383 string listname
= gobble ( s
, " \t" );
384 int i
= GetListIndex ( listname
.c_str() );
386 return PrivMsg ( channel
, ssprintf("%s: I don't have a list named '%s'",from
.c_str(),listname
.c_str()) );
387 List
& list
= lists
[i
];
388 if ( s
[0] == '\"' || s
[0] == '\'' )
391 const char* p
= &s
[1];
392 const char* p2
= strchr ( p
, delim
);
394 return PrivMsg ( channel
, ssprintf("%s: Couldn't add, unmatched quotes",from
.c_str()) );
395 s
= string ( p
, p2
-p
);
397 for ( i
= 0; i
< list
.list
.size(); i
++ )
399 if ( list
.list
[i
] == s
)
401 list
.list
.erase ( &list
.list
[i
] );
403 File
f ( ssprintf("%s.txt",list
.name
.c_str()), "w" );
404 for ( i
= 0; i
< list
.list
.size(); i
++ )
405 f
.printf ( "%s\n", list
.list
[i
].c_str() );
407 return PrivMsg ( channel
, ssprintf("%s: entry removed from list '%s'",from
.c_str(),listname
.c_str()) );
410 return PrivMsg ( channel
, ssprintf("%s: entry doesn't exist in list '%s'",from
.c_str(),listname
.c_str()) );
415 return PrivMsg ( channel
, ssprintf("%s: huh?",from
.c_str()) );
420 bool found_curse
= false;
421 static vector
<string
>& curse
= GetList("curse").list
;
422 text2
= " " + text2
+ " ";
424 for ( int i
= 0; i
< curse
.size() && !found_curse
; i
++ )
426 if ( strstr ( text2
.c_str(), curse
[i
].c_str() ) )
431 static List
& cursecop
= GetList("cursecop");
432 return PrivMsg ( channel
, ssprintf("%s: %s", from
.c_str(), ListRand(cursecop
)) );
435 string
botname (BOTNAME
);
436 strlwr ( &botname
[0] );
437 //botname = " " + botname + " ";
439 if ( strstr(text2
.c_str(), botname
.c_str()) || strstr(text2
.c_str(), " arch ") || found_name
)
441 string out
= ssprintf("%s: %s", from
.c_str(), TaggedReply("tech").c_str());
442 flog
.printf ( "TECH-REPLY: %s\n", out
.c_str() );
443 if ( !strnicmp ( out
.c_str(), "/me ", 4 ) )
444 return Action ( channel
, &out
[4] );
446 return PrivMsg ( channel
, out
);
450 } // On Chanel Message
452 bool OnChannelMode ( const string
& channel
, const string
& mode
)
454 //printf ( "OnChannelMode(%s,%s)\n", channel.c_str(), mode.c_str() );
457 bool OnUserModeInChannel ( const string
& src
, const string
& channel
, const string
& mode
, const string
& target
)
459 printf ( "OnUserModeInChannel(%s,%s,%s,%s)\n", src
.c_str(), channel
.c_str(), mode
.c_str(), target
.c_str() );
460 const char* p
= mode
.c_str();
468 while ( *p
!= 0 && *p
!= ' ' )
472 printf ( "adding '%s' to ops list\n", target
.c_str() );
473 ops
.push_back ( target
);
479 while ( *p
!= 0 && *p
!= ' ' )
483 for ( int i
= 0; i
< ops
.size(); i
++ )
485 if ( ops
[i
] == target
)
487 printf ( "remove '%s' to ops list\n", target
.c_str() );
488 ops
.erase ( &ops
[i
] );
498 bool OnMode ( const string
& user
, const string
& mode
)
500 //printf ( "OnMode(%s,%s)\n", user.c_str(), mode.c_str() );
503 bool OnChannelUsers ( const string
& channel
, const vector
<string
>& users
)
505 //printf ( "[%s has %i users]: ", channel.c_str(), users.size() );
506 for ( int i
= 0; i
< users
.size(); i
++ )
508 if ( users
[i
][0] == '@' )
509 ops
.push_back ( &users
[i
][1] );
512 printf ( "%s", users[i].c_str() );*/
522 bool OnBanned ( const std::string
& channel
)
525 return Join(CHANNEL
);
529 int main ( int argc
, char** argv
)
531 srand ( time(NULL
) );
533 ImportList ( "dev", true );
534 ImportList ( "func", true );
535 ImportList ( "dev", true );
536 ImportList ( "func", true );
537 ImportList ( "irql", true );
538 ImportList ( "module", true );
539 ImportList ( "period", true );
540 ImportList ( "status", true );
541 ImportList ( "stru", true );
542 ImportList ( "type", true );
544 ImportList ( "tech", false );
545 ImportList ( "curse", false );
546 ImportList ( "cursecop", false );
547 ImportList ( "grovel", false );
548 ImportList ( "nogrovel", false );
549 ImportList ( "idle", false );
552 printf ( "initializing IRCClient debugging\n" );
553 IRCClient::SetDebug ( true );
558 printf ( "calling suStartup()\n" );
560 printf ( "creating IRCClient object\n" );
562 printf ( "connecting to freenode\n" );
564 if ( !irc
.Connect ( SERVER
) ) // irc.freenode.net
566 printf ( "couldn't connect to server\n" );
570 printf ( "sending user command\n" );
571 if ( !irc
.User ( BOTNAME
, "reactos.com", SERVER
, "ArchBlackmann" ) )
573 printf ( "USER command failed, retying ...\n" );
577 printf ( "sending nick\n" );
578 if ( !irc
.Nick ( BOTNAME
) )
580 printf ( "NICK command failed, retying ...\n" );
584 printf ( "setting mode\n" );
585 if ( !irc
.Mode ( MODE
) )
587 printf ( "MODE command failed, retying ...\n" );
591 printf ( "joining channel\n" );
592 if ( !irc
.Join ( CHANNEL
) )
594 printf ( "JOIN command failed, retying ...\n" );
599 printf ( "entering irc client processor\n" );
600 irc
.Run ( false ); // do the processing in this thread...