diff --git a/modules/modperl.cpp b/modules/modperl.cpp index 8ca18210..b405ec66 100644 --- a/modules/modperl.cpp +++ b/modules/modperl.cpp @@ -10,6 +10,14 @@ #include #include +#define NICK( a ) a.GetNickMask().c_str() +#define CHAN( a ) a.GetName().c_str() +#define NUM( a ) CString::ToString( a ).c_str() +#define BOOL( a ) ( a ? "1" : "0" ) +#define CBNONE( a ) CallBack( a, NULL ) +#define CBSINGLE( a, b ) CallBack( a, b, NULL ) +#define CBDOUBLE( a, b, c ) CallBack( a, b, c, NULL ) + class CModPerl; static CModPerl *g_ModPerl = NULL; @@ -46,30 +54,136 @@ public: } virtual bool OnLoad( const CString & sArgs ); + virtual bool OnBoot() { return( CBNONE( "OnLoad" ) ); } + virtual void OnUserAttached() { CBNONE( "OnUserAttached" ); } + virtual void OnUserDetached() { CBNONE( "OnUserDetached" ); } + virtual void OnIRCDisconnected() { CBNONE( "OnIRCDisconnected" ); } + virtual void OnIRCConnected() { CBNONE( "OnIRCConnected" ); } - virtual bool OnChanMsg( const CNick& Nick, const CChan & Channel, CString & sMessage ) + virtual bool OnDCCUserSend(const CNick& RemoteNick, unsigned long uLongIP, unsigned short uPort, + const CString& sFile, unsigned long uFileSize) { - int iRet = CallBack( "OnChanMsg", Nick.GetNickMask().c_str(), Channel.GetName().c_str(), sMessage.c_str(), NULL ); - if ( iRet > 0 ) - return( true ); - - return( false ); + return( CallBack( "OnDCCUserSend", NICK( RemoteNick ), NUM( uLongIP ), NUM( uPort ), sFile.c_str(), NUM( uFileSize ), NULL ) ); } - - void AddZNCHook( const string & sHookName ) { m_mssHookNames.insert( sHookName ); } - void DelZNCHook( const string & sHookName ) + + virtual void OnOp(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) { - set< string >::iterator it = m_mssHookNames.find( sHookName ); + CallBack( "OnOp", NICK( OpNick ), NICK( Nick ), CHAN( Channel ), BOOL( bNoChange ), NULL ); + } + virtual void OnDeop(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) + { + CallBack( "OnDeop", NICK( OpNick ), NICK( Nick ), CHAN( Channel ), BOOL( bNoChange ), NULL ); + } + virtual void OnVoice(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) + { + CallBack( "OnVoice", NICK( OpNick ), NICK( Nick ), CHAN( Channel ), BOOL( bNoChange ), NULL ); + } + virtual void OnDevoice(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) + { + CallBack( "OnDevoice", NICK( OpNick ), NICK( Nick ), CHAN( Channel ), BOOL( bNoChange ), NULL ); + } + virtual void OnRawMode(const CNick& Nick, const CChan& Channel, const CString& sModes, const CString& sArgs) + { + CallBack( "OnRawMode", NICK( Nick ), CHAN( Channel ), sModes.c_str(), sArgs.c_str(), NULL ); + } + virtual bool OnUserRaw(CString& sLine) { return( CBSINGLE( "OnUserRaw", sLine.c_str() ) ); } + virtual bool OnRaw(CString& sLine) { return( CBSINGLE( "OnRaw", sLine.c_str() ) ); } + virtual bool OnStatusCommand(const CString& sCommand) { return( CBSINGLE( "OnStatusCommand", sCommand.c_str() ) ); } + virtual void OnModCommand(const CString& sCommand) { CBSINGLE( "OnModCommand", sCommand.c_str() ); } + virtual void OnModNotice(const CString& sMessage) { CBSINGLE( "OnModNotice", sMessage.c_str() ); } + virtual void OnModCTCP(const CString& sMessage) { CBSINGLE( "OnModCTCP", sMessage.c_str() ); } + + virtual void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) + { + vector< CString > vsArgs; + vsArgs.push_back( Nick.GetNickMask() ); + vsArgs.push_back( sMessage ); + for( vector::size_type a = 0; a < vChans.size(); a++ ) + vsArgs.push_back( vChans[a]->GetName() ); + + CallBackVec( "OnQuit", vsArgs ); + } + + virtual void OnNick(const CNick& Nick, const CString& sNewNick, const vector& vChans) + { + vector< CString > vsArgs; + vsArgs.push_back( Nick.GetNickMask() ); + vsArgs.push_back( sNewNick ); + for( vector::size_type a = 0; a < vChans.size(); a++ ) + vsArgs.push_back( vChans[a]->GetName() ); + + CallBackVec( "OnNick", vsArgs ); + } + + virtual void OnKick(const CNick& Nick, const CString& sOpNick, const CChan& Channel, const CString& sMessage) + { + CallBack( "OnKick", NICK( Nick ), sOpNick.c_str(), CHAN( Channel ), sMessage.c_str(), NULL ); + } + + virtual void OnJoin(const CNick& Nick, const CChan& Channel) { CBDOUBLE( "OnJoin", NICK( Nick ), CHAN( Channel ) ); } + virtual void OnPart(const CNick& Nick, const CChan& Channel) { CBDOUBLE( "OnPart", NICK( Nick ), CHAN( Channel ) ); } + + virtual bool OnUserCTCPReply(const CNick& Nick, CString& sMessage) + { + return CBDOUBLE( "OnUserCTCPReply", NICK( Nick ), sMessage.c_str() ); + } + virtual bool OnCTCPReply(const CNick& Nick, CString& sMessage) + { + return CBDOUBLE( "OnCTCPReply", NICK( Nick ), sMessage.c_str() ); + } + virtual bool OnUserCTCP(const CString& sTarget, CString& sMessage) + { + return CBDOUBLE( "OnUserCTCP", sTarget.c_str(), sMessage.c_str() ); + } + virtual bool OnPrivCTCP(const CNick& Nick, CString& sMessage) + { + return CBDOUBLE( "OnPrivCTCP", NICK( Nick ), sMessage.c_str() ); + } + virtual bool OnChanCTCP(const CNick& Nick, const CChan& Channel, CString& sMessage) + { + return CallBack( NICK( Nick ), CHAN( Channel ), sMessage.c_str(), NULL ); + } + virtual bool OnUserMsg(const CString& sTarget, CString& sMessage) + { + return CBDOUBLE( "OnUserMsg", sTarget.c_str(), sMessage.c_str() ); + } + virtual bool OnPrivMsg(const CNick& Nick, CString& sMessage) + { + return CBDOUBLE( "OnPrivMsg", NICK( Nick ), sMessage.c_str() ); + } + + virtual bool OnChanMsg( const CNick& Nick, const CChan & Channel, CString & sMessage ) + { + return( CallBack( "OnChanMsg", NICK( Nick ), CHAN( Channel ), sMessage.c_str(), NULL ) ); + } + virtual bool OnUserNotice(const CString& sTarget, CString& sMessage) + { + return CBDOUBLE( "OnUserNotice", sTarget.c_str(), sMessage.c_str() ); + } + virtual bool OnPrivNotice(const CNick& Nick, CString& sMessage) + { + return CBDOUBLE( "OnPrivNotice", NICK( Nick ), sMessage.c_str() ); + } + virtual bool OnChanNotice(const CNick& Nick, const CChan& Channel, CString& sMessage) + { + return( CallBack( "OnChanNotice", NICK( Nick ), CHAN( Channel ), sMessage.c_str(), NULL ) ); + } + + void AddZNCHook( const CString & sHookName ) { m_mssHookNames.insert( sHookName ); } + void DelZNCHook( const CString & sHookName ) + { + set< CString >::iterator it = m_mssHookNames.find( sHookName ); if ( it != m_mssHookNames.end() ) m_mssHookNames.erase( it ); } int CallBack( const char *pszHookName, ... ); + int CallBackVec( const CString & sHookName, const vector< CString > & vsArgs ); private: PerlInterpreter *m_pPerl; - set< string > m_mssHookNames; + set< CString > m_mssHookNames; void ModPerlInit() { @@ -117,10 +231,10 @@ XS(XS_AddZNCTimer) { if ( g_ModPerl ) { - string sLabel = (char *)SvPV(ST(0),PL_na); + CString sLabel = (char *)SvPV(ST(0),PL_na); u_int iInterval = (u_int)SvIV(ST(1)); u_int iCycles = (u_int)SvIV(ST(2)); - string sDesc = (char *)SvPV(ST(3),PL_na); + CString sDesc = (char *)SvPV(ST(3),PL_na); CModPerlTimer *pTimer = new CModPerlTimer( g_ModPerl, iInterval, iCycles, sLabel, sDesc ); g_ModPerl->AddZNCHook( sLabel ); @@ -142,7 +256,7 @@ XS(XS_KillZNCTimer) { if ( g_ModPerl ) { - string sLabel = (char *)SvPV(ST(0),PL_na); + CString sLabel = (char *)SvPV(ST(0),PL_na); CTimer *pTimer = g_ModPerl->FindTimer( sLabel ); if ( pTimer ) @@ -155,32 +269,13 @@ XS(XS_KillZNCTimer) /////////// supporting functions from within module -bool CModPerl::OnLoad( const CString & sArgs ) -{ - const char *pArgv[] = - { - sArgs.c_str(), - sArgs.c_str(), - NULL - }; - - perl_parse( m_pPerl, NULL, 2, (char **)pArgv, (char **)NULL ); - PL_exit_flags |= PERL_EXIT_DESTRUCT_END; - - newXS( "AddZNCHook", XS_AddZNCHook, (char *)__FILE__ ); - newXS( "AddZNCTimer", XS_AddZNCTimer, (char *)__FILE__ ); - newXS( "KillZNCTimer", XS_KillZNCTimer, (char *)__FILE__ ); - - ModPerlInit(); - return( true ); -} int CModPerl::CallBack( const char *pszHookName, ... ) { - set< string >::iterator it = m_mssHookNames.find( pszHookName ); + set< CString >::iterator it = m_mssHookNames.find( pszHookName ); if ( it == m_mssHookNames.end() ) - return( -1 ); + return( 1 ); va_list ap; va_start( ap, pszHookName ); @@ -201,7 +296,7 @@ int CModPerl::CallBack( const char *pszHookName, ... ) int iCount = call_pv( it->c_str(), G_SCALAR ); SPAGAIN; - int iRet = 0; + int iRet = 1; if ( iCount == 1 ) iRet = POPi; @@ -214,6 +309,61 @@ int CModPerl::CallBack( const char *pszHookName, ... ) return( iRet ); } +int CModPerl::CallBackVec( const CString & sHookName, const vector< CString > & vsArgs ) +{ + set< CString >::iterator it = m_mssHookNames.find( sHookName ); + + if ( it == m_mssHookNames.end() ) + return( 1 ); + + dSP; + ENTER; + SAVETMPS; + + PUSHMARK( SP ); + for( vector< CString >::size_type a = 0; a < vsArgs.size(); a++ ) + { + XPUSHs( sv_2mortal( newSVpv( vsArgs[a].c_str(), vsArgs[a].length() ) ) ); + } + PUTBACK; + + int iCount = call_pv( it->c_str(), G_SCALAR ); + + SPAGAIN; + int iRet = 1; + + if ( iCount == 1 ) + iRet = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return( iRet ); +} + +////////////////////// Events /////////////////// +bool CModPerl::OnLoad( const CString & sArgs ) +{ + const char *pArgv[] = + { + sArgs.c_str(), + sArgs.c_str(), + NULL + }; + + perl_parse( m_pPerl, NULL, 2, (char **)pArgv, (char **)NULL ); + PL_exit_flags |= PERL_EXIT_DESTRUCT_END; + + newXS( "AddZNCHook", XS_AddZNCHook, (char *)__FILE__ ); + newXS( "AddZNCTimer", XS_AddZNCTimer, (char *)__FILE__ ); + newXS( "KillZNCTimer", XS_KillZNCTimer, (char *)__FILE__ ); + + ModPerlInit(); + return( true ); +} + +/////////////// CModPerlTimer ////////////// void CModPerlTimer::RunJob() { ((CModPerl *)m_pModule)->CallBack( GetName().c_str(), NULL );