// ScriptCommands.C -*- C++ -*- // Copyright (c) 1998 Etienne BERNARD // Copyright (C) 2002,2005 Clinton Ebadi // 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 // 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USESCRIPTS #include "Utils.H" #include "Server.H" #include "ServerList.H" #include "ServerQueue.H" #include "ScriptCommands.H" #include "Interp.H" #include "DCCPerson.H" #include "DCCManager.H" #include "Parser.H" #include "Commands.H" #include "Message.H" #include #define VERIFY_STRING(par) if (!SCM_STRINGP((par))) \ return scm_long2num(-17) #define VERIFY_NUMBER(par) if (!SCM_NUMBERP((par))) \ return scm_long2num(-17) SCM ScriptCommands::Action(SCM channel, SCM message) { VERIFY_STRING(channel); VERIFY_STRING(message); Message m = Commands::Action(Interp::bot, Utils::scm2str(channel), Utils::scm2str(message)); return scm_long2num(m.getCode()); } SCM ScriptCommands::AddUser(SCM who, SCM maskChannel, SCM level, SCM prot, SCM aop, SCM expire, SCM password) { // It segfaults when not online, but otherwise appears to work VERIFY_STRING (who); VERIFY_STRING (maskChannel); VERIFY_NUMBER (level); String wwho = Utils::scm2str (who); String mask = Utils::scm2str (maskChannel); String passwd; std::time_t eexpire; if (SCM_UNBNDP (password)) passwd = ""; else { VERIFY_STRING (password); passwd = Utils::scm2str (password); } if (SCM_UNBNDP (expire)) eexpire = -1; else { VERIFY_STRING (expire); eexpire = Utils::str2time (Utils::scm2str (expire)); if (!eexpire) eexpire = -1; } int protect = scm_num2int (prot, SCM_ARG1, "ScriptCommands::AddUser"); bool aaop = SCM_NFALSEP (aop); int llevel = scm_num2int (level, SCM_ARG1, "ScriptCommands::AddUser"); Message m = Commands::AddUser (Interp::bot, wwho, mask, llevel, protect, aaop, eexpire, passwd); return scm_long2num(m.getCode ()); } SCM ScriptCommands::AddServer(SCM servername, SCM port) { int p = 6667; if (SCM_NUMBERP(port)) p = scm_num2long(port, SCM_ARG1, "ScriptCommands::AddServer"); Message m = Commands::AddServer(Interp::bot, Utils::scm2str(servername), p); return scm_long2num(m.getCode()); } SCM ScriptCommands::AddShit(SCM mask, SCM maskChannel, SCM level, SCM expiration, SCM reason) { // This appears to work...not much testing though VERIFY_STRING (mask); VERIFY_STRING (maskChannel); VERIFY_NUMBER (level); String mmask = Utils::scm2str (mask); String mmaskChannel = Utils::scm2str (maskChannel); int llevel = scm_num2int (level, SCM_ARG1, "ScriptCommands::AddShit"); std::time_t expire; String rreason; if (SCM_UNBNDP (expiration)) expire = -1; else { VERIFY_STRING (expiration); expire = Utils::str2time (Utils::scm2str (expiration)); if (!expire) expire = -1; } if (SCM_UNBNDP (reason)) rreason = "You're on my shitlist, lamer"; else { VERIFY_STRING (reason); rreason = Utils::scm2str (reason); } Message m = Commands::AddShit (Interp::bot, mmask, mmaskChannel, llevel, expire, rreason); return scm_long2num(m.getCode ()); } SCM ScriptCommands::Ban(SCM channel, SCM who) { VERIFY_STRING(channel); VERIFY_STRING(who); Message m = Commands::Ban(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who)); return scm_long2num(m.getCode()); } SCM ScriptCommands::ChangeCommandLevel(SCM command, SCM level) { VERIFY_STRING (command); VERIFY_NUMBER (level); SCM_STRING_COERCE_0TERMINATION_X (command); std::string ccommand = SCM_STRING_CHARS (command); unsigned int llevel = scm_num2uint (level, 0, "ScriptCommands::ChangeCommandLevel"); if (llevel > 4) return SCM_BOOL_F; std::map >::const_iterator uf_iter = Interp::bot->userFunctions.find (ccommand); userFunction * f = 0; if (uf_iter != Interp::bot->userFunctions.end ()) f = uf_iter->second; else return SCM_BOOL_F; f->minLevel = llevel; return SCM_BOOL_T; } SCM ScriptCommands::Cycle(SCM channel) { VERIFY_STRING(channel); Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Deban(SCM channel, SCM who) { VERIFY_STRING(channel); VERIFY_STRING(who); Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who)); return scm_long2num(m.getCode()); } SCM ScriptCommands::DelServer(SCM number) { VERIFY_NUMBER(number); Message m = Commands::DelServer(Interp::bot, scm_num2long(number, SCM_ARG1, "ScriptCommands::DelServer")); return scm_long2num(m.getCode()); } SCM ScriptCommands::DelUser(SCM who, SCM maskChannel) { VERIFY_STRING(who); VERIFY_STRING(maskChannel); Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who), Utils::scm2str(maskChannel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::DelShit(SCM who, SCM maskChannel) { VERIFY_STRING(who); VERIFY_STRING(maskChannel); Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who), Utils::scm2str(maskChannel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Deop(SCM channel, SCM who) { VERIFY_STRING(channel); VERIFY_STRING(who); Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Die(SCM reason) { String r = "Leaving"; if (SCM_STRINGP(reason)) r = Utils::scm2str(reason); Message m = Commands::Die(Interp::bot, r); return scm_long2num(m.getCode()); } SCM ScriptCommands::Do(SCM command) { VERIFY_STRING(command); Message m = Commands::Do(Interp::bot, Utils::scm2str(command)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Invite(SCM channel, SCM who) { VERIFY_STRING(channel); VERIFY_STRING(who); Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Join(SCM channel, SCM key) { VERIFY_STRING(channel); String k = ""; if (SCM_STRINGP(key)) k = Utils::scm2str(key); Message m = Commands::Join(Interp::bot, Utils::scm2str(channel), k); return scm_long2num(m.getCode()); } SCM ScriptCommands::Keep(SCM channel, SCM modes) { VERIFY_STRING(channel); VERIFY_STRING(modes); Message m = Commands::Keep(Interp::bot, Utils::scm2str(channel), Utils::scm2str(modes)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Kick(SCM channel, SCM who, SCM reason) { VERIFY_STRING(channel); VERIFY_STRING(who); String r = ""; if (SCM_STRINGP(reason)) r = Utils::scm2str(reason); Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who), r); return scm_long2num(m.getCode()); } SCM ScriptCommands::KickBan(SCM channel, SCM who, SCM reason) { VERIFY_STRING(channel); VERIFY_STRING(who); String r = ""; if (SCM_STRINGP(reason)) r = Utils::scm2str(reason); Message m = Commands::KickBan(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who), r); return scm_long2num(m.getCode()); } SCM ScriptCommands::Lock(SCM channel) { VERIFY_STRING(channel); Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::LogPort(void) { return Interp::bot->botInterp->logPort; } SCM ScriptCommands::Mode(SCM channel, SCM mode) { VERIFY_STRING(channel); VERIFY_STRING(mode); Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel), Utils::scm2str(mode)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Msg(SCM nick, SCM message) { VERIFY_STRING(nick); VERIFY_STRING(message); Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick), Utils::scm2str(message)); return scm_long2num(m.getCode()); } SCM ScriptCommands::NextServer(void) { Message m = Commands::NextServer(Interp::bot); return scm_long2num(m.getCode()); } SCM ScriptCommands::Nick(SCM nick) { VERIFY_STRING(nick); Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Op(SCM channel, SCM who) { VERIFY_STRING(channel); VERIFY_STRING(who); Message m = Commands::Op(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Part(SCM channel) { VERIFY_STRING(channel); Message m = Commands::Part(Interp::bot, Utils::scm2str(channel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Reconnect(void) { Message m = Commands::Reconnect(Interp::bot); return scm_long2num(m.getCode()); } SCM ScriptCommands::Say(SCM channel, SCM message) { VERIFY_STRING(channel); VERIFY_STRING(message); Message m = Commands::Say(Interp::bot, Utils::scm2str(channel), Utils::scm2str(message)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Server(SCM number) { VERIFY_NUMBER(number); Message m = Commands::Server(Interp::bot, gh_scm2long(number)); return scm_long2num(m.getCode()); } SCM ScriptCommands::SetFloodRate(SCM rate) { VERIFY_NUMBER(rate); Message m = Commands::SetFloodRate(Interp::bot, scm_num2uint (rate, 0, "SetFloodRate")); return scm_long2num(m.getCode()); } SCM ScriptCommands::SetVersion(SCM version) { Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version)); return scm_long2num(m.getCode()); } SCM ScriptCommands::TBan(SCM channel, SCM who, SCM seconds) { VERIFY_STRING(channel); VERIFY_STRING(who); VERIFY_NUMBER(seconds); Message m = Commands::TBan(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who), gh_scm2long(seconds)); return scm_long2num(m.getCode()); } SCM ScriptCommands::TKBan(SCM channel, SCM who, SCM seconds, SCM reason) { VERIFY_STRING(channel); VERIFY_STRING(who); VERIFY_NUMBER(seconds); String r = ""; if (SCM_STRINGP(reason)) r = Utils::scm2str(reason); Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel), Utils::scm2str(who), gh_scm2long(seconds), r); return scm_long2num(m.getCode()); } SCM ScriptCommands::Topic(SCM channel, SCM topic) { VERIFY_STRING(channel); VERIFY_STRING(topic); Message m = Commands::Topic(Interp::bot, Utils::scm2str(channel), Utils::scm2str(topic)); return scm_long2num(m.getCode()); } SCM ScriptCommands::Unlock(SCM channel) { VERIFY_STRING(channel); Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel)); return scm_long2num(m.getCode()); } SCM ScriptCommands::getNickname(void) { return Utils::str2scm(Interp::bot->nickName); } SCM ScriptCommands::getServer(void) { ::Server *serv = Interp::bot->serverList->currentServer(); int serverNumber = Interp::bot->serverList->currentNumber; return gh_list(scm_long2num(serverNumber), Utils::str2scm(serv->getHostName()), scm_long2num(serv->getPort()), Utils::str2scm(serv->getPassword()), SCM_UNDEFINED); } SCM ScriptCommands::getServerList(void) { SCM res = gh_list(SCM_UNDEFINED); ::Server *s; int i = 0; std::vector::iterator it = Interp::bot->serverList->begin(); for ( ; it != Interp::bot->serverList->end(); ++it) { s = (*it); res = gh_append2(res, gh_list(gh_list(scm_long2num(i++), Utils::str2scm(s->getHostName()), scm_long2num(s->getPort()), Utils::str2scm(s->getPassword()), SCM_UNDEFINED), SCM_UNDEFINED)); } return res; } SCM ScriptCommands::flushQueue(void) { if (!Interp::bot->serverConnection) return SCM_BOOL_F; Interp::bot->serverConnection->queue->flush(); return SCM_BOOL_T; } SCM ScriptCommands::flushPort(void) { scm_flush(Interp::bot->botInterp->logPort); return SCM_BOOL_T; } SCM ScriptCommands::random(SCM scm_max) { int max = 0; //srand(time(NULL)); if (SCM_NUMBERP(scm_max)) max = gh_scm2int(scm_max); return scm_long2num(max ? rand() % max : 0); } SCM ScriptCommands::addCommand(SCM scm_commandName, SCM scm_function, SCM scm_needsChannel, SCM scm_args, SCM scm_minLevel) { // We check that commandName is a string if (!SCM_STRINGP(scm_commandName)) return SCM_BOOL_F; // We check that the command does not exist String commandName = Utils::to_upper (Utils::scm2str(scm_commandName)); if (Interp::bot->userFunctions[commandName]) return SCM_BOOL_F; // Next we check that needsChannel is a boolean if (!gh_boolean_p(scm_needsChannel)) return SCM_BOOL_F; bool needsChannel = gh_scm2bool(scm_needsChannel); // We check that minLevel is an integer and that it's // a valid level if (!SCM_NUMBERP(scm_minLevel)) return SCM_BOOL_F; int minLevel = gh_scm2long(scm_minLevel); if (minLevel < User::NONE || minLevel > User::MASTER) return SCM_BOOL_F; // We check that "scm_function" is a Scheme procedure if (!gh_procedure_p(scm_function)) return SCM_BOOL_F; // We check that args is an integer and is between 0 and 20 (arbitrary limit) if (!SCM_NUMBERP(scm_args)) return SCM_BOOL_F; int args = gh_scm2long(scm_args); if (args < 0 || args > 20) return SCM_BOOL_F; // We add the command in the commands list Interp::bot->userFunctions[commandName] = new userFunction(0, minLevel, needsChannel, args, scm_function); return SCM_BOOL_T; } SCM ScriptCommands::delCommand(SCM scm_commandName) { // We check that commandName is a string if (!SCM_STRINGP(scm_commandName)) return SCM_BOOL_F; // We check that the command does exist String commandName = Utils::to_upper (Utils::scm2str(scm_commandName)); if (!Interp::bot->userFunctions[commandName]) return SCM_BOOL_F; // We delete the command Interp::bot->userFunctions.erase(commandName); return SCM_BOOL_T; } SCM ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall, SCM name) { int priority = 0; bool fallt = true; // does this hook fall through? String rname = "DEFAULT"; if (!SCM_UNBNDP (pri)) priority = scm_num2int (pri, SCM_ARG1, "ScriptCommands::AddHook"); if (!SCM_UNBNDP (fall)) fallt = SCM_NFALSEP (fall); if (!SCM_UNBNDP (name)) rname = Utils::scm2str (name); return SCM_BOOL (Interp::bot->botInterp->AddHook(gh_scm2long(type), regex, function, priority, fallt, rname)); } SCM ScriptCommands::AddTimer(SCM when, SCM function) { return Interp::bot->botInterp->AddTimer(gh_scm2long(when), function); } SCM ScriptCommands::DelTimer(SCM timer) { return SCM_BOOL (Interp::bot->botInterp->DelTimer(timer)); } SCM ScriptCommands::sendDCCChatMessage (SCM to, SCM message) { return SCM_BOOL (Interp::bot->dccConnections->sendMessage (Utils::scm2str (to), Utils::scm2str (message))); } // Message sending // FIXME: write these #define IQUEUE Interp::bot->serverConnection->queue SCM ScriptCommands::sendCTCP(SCM to, SCM command , SCM message) { VERIFY_STRING(to); VERIFY_STRING(command); VERIFY_STRING(message); Commands::CTCP (Interp::bot, Utils::scm2str (to), Utils::scm2str (command), Utils::scm2str (message)); return SCM_UNSPECIFIED; } SCM ScriptCommands::sendCTCPReply (SCM to, SCM command , SCM message) { VERIFY_STRING(to); VERIFY_STRING(command); VERIFY_STRING(message); Commands::CTCPReply (Interp::bot, Utils::scm2str (to), Utils::scm2str (command), Utils::scm2str (message)); return SCM_UNSPECIFIED; } SCM ScriptCommands::sendNotice (SCM to, SCM message) { VERIFY_STRING (to); VERIFY_STRING (message); return (scm_long2num (Commands::Notice (Interp::bot, Utils::scm2str (to), Utils::scm2str (message)).getCode ())); } #endif