2009-08-20 11:02:05 +00:00
/***************************************************************************
2009-08-20 15:19:41 +00:00
* Copyright (C) 2009 by Lothar May *
2009-08-20 11:02:05 +00:00
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
2009-08-20 15:19:41 +00:00
#include <net/serveradminbot.h>
2009-08-20 11:02:05 +00:00
#include <net/ircthread.h>
#include <net/serverlobbythread.h>
#include <net/serverbanmanager.h>
#include <net/serverexception.h>
#include <net/socket_msg.h>
#include <net/socket_startup.h>
#include <core/loghelper.h>
#include <boost/bind.hpp>
#include <boost/algorithm/string/predicate.hpp>
#define SERVER_RESTART_IRC_BOT_INTERVAL_SEC 86400 // 1 day
using namespace std ;
2009-08-20 15:19:41 +00:00
ServerAdminBot :: ServerAdminBot ()
2011-02-10 13:54:53 +00:00
: m_ircRestartTimer ( boost :: posix_time :: time_duration ( 0 , 0 , 0 ), boost :: timers :: portable :: microsec_timer :: auto_start )
2009-08-20 11:02:05 +00:00
{
}
2009-08-20 15:19:41 +00:00
ServerAdminBot ::~ ServerAdminBot ()
2009-08-20 11:02:05 +00:00
{
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: Init ( boost :: shared_ptr < ServerLobbyThread > lobbyThread , boost :: shared_ptr < IrcThread > ircAdminThread )
2009-08-20 11:02:05 +00:00
{
m_lobbyThread = lobbyThread ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread = ircAdminThread ;
2009-08-20 11:02:05 +00:00
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalIrcConnect ( const std :: string & server )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
LOG_MSG ( "Admin bot: Connected to IRC server " << server << "." );
2009-08-20 11:02:05 +00:00
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalIrcSelfJoined ( const std :: string & nickName , const std :: string & channel )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
LOG_MSG ( "Admin bot: Joined IRC channel " << channel << " as user " << nickName << "." );
2009-08-20 11:02:05 +00:00
m_ircNick = nickName ;
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalIrcChatMsg ( const std :: string & nickName , const std :: string & msg )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
if ( m_ircAdminThread )
2009-08-20 11:02:05 +00:00
{
try
{
istringstream msgStream ( msg );
string target ;
msgStream >> target ;
if ( boost :: algorithm :: iequals ( target , m_ircNick + ":" ))
{
string command ;
msgStream >> command ;
if ( command == "kick" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerName ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! playerName . empty ())
{
if ( GetLobbyThread (). KickPlayerByName ( playerName ))
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Successfully kicked player \" " + playerName + " \" from the server." );
2009-08-20 11:02:05 +00:00
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Player \" " + playerName + " \" was not found on the server." );
2009-08-20 11:02:05 +00:00
}
}
else if ( command == "cleaner-reconnect" )
{
GetLobbyThread (). ReconnectChatBot ();
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Cleaner bot reconnect initiated." );
2009-08-20 11:02:05 +00:00
}
else if ( command == "showip" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerName ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! playerName . empty ())
{
string ipAddress ( GetLobbyThread (). GetPlayerIPAddress ( playerName ));
if ( ! ipAddress . empty ())
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": The IP address of player \" " + playerName + " \" is: \" " + ipAddress + " \" " );
2009-08-20 11:02:05 +00:00
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": The IP address of player \" " + playerName + " \" is unknown." );
2009-08-20 11:02:05 +00:00
}
}
else if ( command == "bannick" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerRegex ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! playerRegex . empty ())
{
GetLobbyThread (). GetBanManager (). BanPlayerRegex ( playerRegex );
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": The regex \" " + playerRegex + " \" was added to the player ban list." );
2009-08-20 11:02:05 +00:00
}
}
else if ( command == "banip" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string ipAddress ;
unsigned durationHours = 12 ;
msgStream >> ipAddress ;
while ( msgStream . peek () == ' ' )
msgStream . get ();
if ( ! msgStream . eof ())
msgStream >> durationHours ;
if ( ! ipAddress . empty ())
{
ostringstream durationStr ;
durationStr << durationHours ;
GetLobbyThread (). GetBanManager (). BanIPAddress ( ipAddress , durationHours );
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": The IP address \" " + ipAddress + " \" was added to the IP address ban list for " + durationStr . str () + ( durationHours == 1 ? " hour." : " hours." ));
2009-08-20 11:02:05 +00:00
}
}
else if ( command == "listban" )
{
list < string > banList ;
GetLobbyThread (). GetBanManager (). GetBanList ( banList );
list < string >:: const_iterator i = banList . begin ();
list < string >:: const_iterator end = banList . end ();
while ( i != end )
{
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( * i );
2009-08-20 11:02:05 +00:00
++ i ;
}
ostringstream banListStream ;
banListStream
<< nickName << ": Total count of bans: " << banList . size ();
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( banListStream . str ());
2009-08-20 11:02:05 +00:00
}
else if ( command == "removeban" )
{
unsigned banId = 0 ;
msgStream >> banId ;
if ( GetLobbyThread (). GetBanManager (). UnBan ( banId ))
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": The ban was successfully removed." );
2009-08-20 11:02:05 +00:00
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": This ban does not exist." );
2009-08-20 11:02:05 +00:00
}
else if ( command == "clearban" )
{
GetLobbyThread (). GetBanManager (). ClearBanList ();
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": All ban lists were cleared." );
2009-08-20 11:02:05 +00:00
}
else if ( command == "stat" )
{
ServerStats tmpStats = GetLobbyThread (). GetStats ();
{
boost :: posix_time :: time_duration timeDiff ( boost :: posix_time :: second_clock :: local_time () - GetLobbyThread (). GetStartTime ());
ostringstream statStream ;
statStream
<< "Server uptime................ " << timeDiff . hours () / 24 << " days " << timeDiff . hours () % 24 << " hours " << timeDiff . minutes () << " minutes " << timeDiff . seconds () << " seconds" ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( statStream . str ());
2009-08-20 11:02:05 +00:00
}
{
ostringstream statStream ;
statStream
<< "Players currently on Server.. " << tmpStats . numberOfPlayersOnServer ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( statStream . str ());
2009-08-20 11:02:05 +00:00
}
{
ostringstream statStream ;
statStream
<< "Games currently open......... " << tmpStats . numberOfGamesOpen ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( statStream . str ());
2009-08-20 11:02:05 +00:00
}
{
ostringstream statStream ;
statStream
<< "Total players ever logged in. " << tmpStats . totalPlayersEverLoggedIn
<< " (Max at a time: " << tmpStats . maxPlayersLoggedIn << ")" ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( statStream . str ());
2009-08-20 11:02:05 +00:00
}
{
ostringstream statStream ;
statStream
<< "Total games ever open........ " << tmpStats . totalGamesEverCreated
<< " (Max at a time: " << tmpStats . maxGamesOpen << ")" ;
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( statStream . str ());
2009-08-20 11:02:05 +00:00
}
}
else if ( command == "chat" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string chat ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! chat . empty () && chat . size () < MAX_CHAT_TEXT_SIZE )
{
GetLobbyThread (). SendGlobalChat ( chat );
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Global chat message sent." );
2009-08-20 11:02:05 +00:00
}
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Invalid message." );
2009-08-20 11:02:05 +00:00
}
else if ( command == "msg" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string message ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! message . empty () && message . size () < MAX_CHAT_TEXT_SIZE )
{
GetLobbyThread (). SendGlobalMsgBox ( message );
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Global message box sent." );
2009-08-20 11:02:05 +00:00
}
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Invalid message." );
2009-08-20 11:02:05 +00:00
}
else
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Invalid command \" " + command + " \" ." );
2009-08-20 11:02:05 +00:00
}
} catch (...)
{
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SendChatMessage ( nickName + ": Syntax error. Please check the command." );
2009-08-20 11:02:05 +00:00
}
}
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalIrcError ( int errorCode )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
LOG_MSG ( "Admin bot: IRC error " << errorCode << "." );
2009-08-20 11:02:05 +00:00
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalIrcServerError ( int errorCode )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
LOG_MSG ( "Admin bot: IRC server error " << errorCode << "." );
2009-08-20 11:02:05 +00:00
}
2009-08-20 11:42:13 +00:00
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: Run ()
2009-08-20 11:42:13 +00:00
{
2009-08-20 15:19:41 +00:00
if ( m_ircAdminThread )
m_ircAdminThread -> Run ();
2009-08-20 11:42:13 +00:00
}
2009-08-20 11:02:05 +00:00
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: Process ()
2009-08-20 11:02:05 +00:00
{
if ( m_ircRestartTimer . elapsed (). total_seconds () > SERVER_RESTART_IRC_BOT_INTERVAL_SEC )
{
2009-08-20 15:19:41 +00:00
if ( m_ircAdminThread )
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
m_ircAdminThread -> SignalTermination ();
if ( m_ircAdminThread -> Join ( NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC ))
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
boost :: shared_ptr < IrcThread > tmpIrcThread ( new IrcThread ( * m_ircAdminThread ));
2009-08-20 11:02:05 +00:00
tmpIrcThread -> Run ();
2009-08-20 15:19:41 +00:00
m_ircAdminThread = tmpIrcThread ;
2009-08-20 11:02:05 +00:00
}
}
m_ircRestartTimer . reset ();
m_ircRestartTimer . start ();
}
}
void
2009-08-20 15:19:41 +00:00
ServerAdminBot :: SignalTermination ()
2009-08-20 11:02:05 +00:00
{
2009-08-20 15:19:41 +00:00
if ( m_ircAdminThread )
m_ircAdminThread -> SignalTermination ();
2009-08-20 11:02:05 +00:00
}
bool
2009-08-20 15:19:41 +00:00
ServerAdminBot :: Join ( bool wait )
2009-08-20 11:02:05 +00:00
{
bool terminated = true ;
2009-08-20 15:19:41 +00:00
if ( m_ircAdminThread )
terminated = m_ircAdminThread -> Join ( wait ? NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC : 0 );
2009-08-20 11:02:05 +00:00
return terminated ;
}
ServerLobbyThread &
2009-08-20 15:19:41 +00:00
ServerAdminBot :: GetLobbyThread ()
2009-08-20 11:02:05 +00:00
{
assert ( m_lobbyThread . get ());
return * m_lobbyThread ;
}