[[project @ 2002-08-02 04:31:30 by unknown_lamer] unknown_lamer**20020802043130 A few things this time. Hooks can be named (really cool), a few bug fixes (logs work again now), the docs were worked on a little, Socket::readLine now automatically expands the buffer when the length gets over 512 (it uses a static std::string that will _not_ have to be expanded for most uses, but _might_ need to be expanded when I get DCC to work), the bot now runs hooks on its own text so you have to protect against your hooks triggering other hooks by their output; this can be done using the new (not-from-me) syntax (see the manual for how it works). I think that is it. ] { hunk ./ChangeLog 1 +2002-08-01 Clinton Ebadi + + * source/Bot.C (set_log_file): Oops! Fixed logging. Now the bot + logs again. + + * source/Socket.C (readLine): Now uses a static std::string that + starts out with 512 chars. This will never need to be resized for + usualy IRC messages, but might be for DCC messages + +2002-07-31 Clinton Ebadi + + * scripts/bobot-utils.scm (not-from-me): New syntax. + + * source/ScriptCommands.C (AddHook): Now takes another optional + arg--name that will name the hook (see the hooks section in the + manual for what this does). + + * source/BotInterp.H: Added name field to Hook + +2002-07-29 Clinton Ebadi + + * source/ServerQueue.C (sendPrivmsg): Now calls hooks on own + PRIVMSGes because the IRC server doesn't echo them back to the + bot. This could be useful for something (e.g. log script). + hunk ./NEWS 12 + +Version 2.1.1: foom +- Hooks are now executed when the bot sends a privmsg. This now makes + log scripts able to log what the bot said. This probably has other + uses too and shouldn't have any real impact on performance (since it + has to execute hooks on all incoming messages anyway, and there are + probably a lot more incoming than outgoing). +- You can now "name" a hook using an extra arg to bot:addhook. This + name can be used to have multiple hooks of the same type with the + same regexp. The default name is "DEFAULT" so don't use that as the + name for your hooks. +- There is a new macro for scripts--"not-from-me". This allows you to + protect your hooks from calling themselves because they trigger + themselves. See the manual for more about what it does + (Scripting->Misc Scripting Stuff). +- Logging now works again (oops, I didn't realize I broke it until I + started to work on DCC). hunk ./TODO 23 -* Call hooks/public when bot sends a privmsg to a channel (read IRC - protocol spec for other stuff that might need this) hunk ./TODO 38 -* Add Channel logging (log full text of channel if enabled) script hunk ./bobot++.info 202 -is prototyped as `(bot:addhook type regex function pri fall)'. `type' -specifies the type of hook (the types of hooks are listed in *Note Hook -Types::). `regex' is a standard regular expression. If `regex' is -matched, `function' will be called. `function' will take a different -number of args depending on the hook type. `pri' specifies the priority -of the hook---higher priority hooks are executed first. This argument is -optional and defaults to `0'. `fall' is `#t' if the hook is a -fallthrough hook and `#f' is the hook is not a fallthrough hook. This -arg is also optional and default to `#t'. +is prototyped as `(bot:addhook type regex function pri fall name)'. +`type' specifies the type of hook (the types of hooks are listed in +*Note Hook Types::). `regex' is a standard regular expression. If +`regex' is matched, `function' will be called. `function' will take a +different number of args depending on the hook type. `pri' specifies +the priority of the hook---higher priority hooks are executed first. +This argument is optional and defaults to `0'. `fall' is `#t' if the +hook is a fallthrough hook and `#f' is the hook is not a fallthrough +hook. This arg is also optional and default to `#t'. `name' is the +optional name of the hook that defaults to ``DEFAULT''. If you set the +name then you can have more than one hook that matches the same regexp, +as long as they have the same name. E.g. in a log script you could have +the regexps for the log function all be `".*"' and set their names to +`"log"' to avoid a conflict with other hooks. hunk ./bobot++.info 435 + Since a bot calls hooks on things it says, you have to be careful +about hooks that output text that might match itself. E.g. if you have +a hook that matches `"foo"' and the hook displays `"foo to the +whatsit?"', then the hook will call itself over and over until the +stack overflows! To protect against this I wrote the macro +`not-from-me'. You call it like this: `(not-from-me from (stmts if not +from bot) (stmts if from bot))'. E.g. + + (bot:addhook hooks/public "foo" + (lambda (f t p) + (not-from-me f ((bot:say t "foo to the what!"))))) + + This say ``foo to the what!'' to the channel that ``foo'' was said in +and do nothing otherwise. You can optionally specify an action to be +executed if the message is from the bot: + + (bot:addhook hooks/public "foo" + (lambda (f t p) + (not-from-me f ((bot:say t "foo to the what!")) + ((bot:say t "moof"))))) + + That will do the same thing as the first example, but the bot will +say ``moof'' if it said ``foo'' before. That probably isn't a very nice +thing to do, but it works as an example. You can have as many staments +as you want in the clauses. + hunk ./bobot++.info 529 -Node: Hook Types7558 -Node: Scheme User Levels10031 -Node: Sending Messages11160 -Node: High Level Message Functions11757 -Node: Low Level Message Functions11975 -Node: Misc Scripting Stuff12734 -Node: Concept Index13153 -Node: Function Index13335 -Node: Variable Index13596 +Node: Hook Types7908 +Node: Scheme User Levels10381 +Node: Sending Messages11510 +Node: High Level Message Functions12107 +Node: Low Level Message Functions12325 +Node: Misc Scripting Stuff13084 +Node: Concept Index14710 +Node: Function Index14892 +Node: Variable Index15153 hunk ./bobot++.texinfo 209 -@code{(bot:addhook type regex function pri fall)}. @code{type} +@code{(bot:addhook type regex function pri fall name)}. @code{type} hunk ./bobot++.texinfo 218 -fallthrough hook. This arg is also optional and default to @code{#t}. +fallthrough hook. This arg is also optional and default to +@code{#t}. @code{name} is the optional name of the hook that defaults +to ``DEFAULT''. If you set the name then you can have more than one +hook that matches the same regexp, as long as they have the same +name. E.g. in a log script you could have the regexps for the log +function all be @code{".*"} and set their names to @code{"log"} to +avoid a conflict with other hooks. hunk ./bobot++.texinfo 603 +Since a bot calls hooks on things it says, you have to be careful +about hooks that output text that might match itself. E.g. if you have +a hook that matches @code{"foo"} and the hook displays @code{"foo to +the whatsit?"}, then the hook will call itself over and over until the +stack overflows! To protect against this I wrote the macro +@code{not-from-me}. You call it like this: @code{(not-from-me from +(stmts if not from bot) (stmts if from bot))}. E.g. + +@example +(bot:addhook hooks/public "foo" + (lambda (f t p) + (not-from-me f ((bot:say t "foo to the what!"))))) +@end example + +This say ``foo to the what!'' to the channel that ``foo'' was said in +and do nothing otherwise. You can optionally specify an action to be +executed if the message is from the bot: + +@example +(bot:addhook hooks/public "foo" + (lambda (f t p) + (not-from-me f ((bot:say t "foo to the what!")) + ((bot:say t "moof"))))) +@end example + +That will do the same thing as the first example, but the bot will +say ``moof'' if it said ``foo'' before. That probably isn't a very +nice thing to do, but it works as an example. You can have as many +staments as you want in the clauses. + hunk ./scripts/bobot-utils.scm 11 +(use-modules (ice-9 syncase)) + hunk ./scripts/bobot-utils.scm 66 +;;; executes body if not from the bot +(define-syntax not-from-me + (syntax-rules () + ((_ from (not-body1 ...) + (from-body1 ...)) + (cond ((not (string=? from (bot:getnickname))) + not-body1 ...) + (else from-body1 ...))) + ((_ from (not-body1 ...)) + (cond ((not (string=? from (bot:getnickname))) + not-body1 ...))))) + + hunk ./source/Bot.C 250 - if (parameters[0] == '/') + if (parameters != logFileName) hunk ./source/Bot.C 252 - set_log_dir ("/"); - set_log_file (parameters.subString (1)); + if (parameters[0] == '/') + { + set_log_dir ("/"); + set_log_file (parameters.subString (1)); + } + else + set_log_file (parameters); hunk ./source/Bot.C 260 - else - set_log_file (parameters); hunk ./source/Bot.C 531 - return; - + { + logLine ("DCC Connection failed from " + from->getAddress ()); + return; + } + logLine ("DCC Connection worked!"); hunk ./source/Bot.C 688 + logFile.close (); + logFile.clear (); hunk ./source/Bot.H 92 - // std::list userFunctions; hunk ./source/BotInterp.C 73 -BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall) { +BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall, + String name) { hunk ./source/BotInterp.C 89 - if ((*it)->regex_str == rx) { + if ((*it)->regex_str == rx && (*it)->name == name) { hunk ./source/BotInterp.C 100 - function, pri, fall)); + function, pri, fall, name)); hunk ./source/BotInterp.H 40 + String name; hunk ./source/BotInterp.H 44 - Hook(int t, String rs, SCM r, SCM f, int p, bool ft) + Hook(int t, String rs, SCM r, SCM f, int p, bool ft, String n="DEFAULT") hunk ./source/BotInterp.H 46 - regex(r), function(f) { } + name (n), regex(r), function(f) { } hunk ./source/BotInterp.H 94 - bool AddHook(int, SCM, SCM, int, bool); + bool AddHook(int, SCM, SCM, int, bool, String); hunk ./source/Commands.C 65 - QUEUE->sendPrivmsg(channel, String("\001ACTION ") + - message + "\001"); + QUEUE->sendCTCP (channel, "ACTION", message); hunk ./source/Interp.C 150 - 3, 2, 0); + 3, 3, 0); hunk ./source/Parser.C 855 - // FIXME: Re-activate and debug DCC + // FIXME: debug DCC hunk ./source/Parser.C 862 + else + cnx->bot->logLine ("DCC Chat Failed in Parser"); hunk ./source/ScriptCommands.C 558 -ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall) +ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall, + SCM name) hunk ./source/ScriptCommands.C 563 + String rname = "DEFAULT"; hunk ./source/ScriptCommands.C 569 + if (!SCM_UNBNDP (name)) + rname = Utils::scm2String (name); hunk ./source/ScriptCommands.C 573 - priority, fallt)); + priority, fallt, rname)); hunk ./source/ScriptCommands.H 77 - static SCM AddHook(SCM, SCM, SCM, SCM, SCM); + static SCM AddHook(SCM, SCM, SCM, SCM, SCM, SCM); hunk ./source/ServerQueue.C 25 +#include "Utils.H" hunk ./source/ServerQueue.C 88 +#define MNICK (Interp::bot->nickName + "!" + Interp::bot->userHost) hunk ./source/ServerQueue.C 94 + // hook stuff (only get action for now) + + // I don't think it is useful to generate messages for other types + // of CTCP stuff. + puts (command); +#ifdef USESCRIPTS + if (command == "ACTION") + { + Interp::bot->botInterp->RunHooks (Hook::ACTION, + MNICK+ " " + to + + " " + message, + scm_listify (Utils:: + string2SCM (MNICK), + Utils:: + string2SCM (to), + Utils:: + string2SCM (message), + SCM_UNDEFINED)); + } +#endif + hunk ./source/ServerQueue.C 116 +#undef MNICK hunk ./source/ServerQueue.C 211 + // hook stuff +#ifdef USESCRIPTS + if (message[0] != '\001') + if (Utils::isChannel (dest)) + Interp::bot->botInterp->RunHooks (Hook::PUBLIC, + Interp::bot->nickName + " " + dest + + " " + message, + scm_listify (Utils:: + string2SCM (Interp::bot->nickName), + Utils:: + string2SCM (dest), + Utils:: + string2SCM + (message), SCM_UNDEFINED)); + else + Interp::bot->botInterp->RunHooks (Hook::MESSAGE, + Interp::bot->nickName + " " + + message, + scm_listify (Utils:: + string2SCM (Interp::bot->nickName), + Utils:: + string2SCM + (message), SCM_UNDEFINED)); +#endif hunk ./source/Socket.C 20 +#include hunk ./source/Socket.C 194 - return false; + { + // I'd rather log this to the log file + std::cerr << strerror (errno) << std::endl; + return false; + } hunk ./source/Socket.C 251 - static char buf[512]; + static std::string buf (512, ' '); hunk ./source/Socket.C 254 - + std::size_t length = buf.length (); + hunk ./source/Socket.C 269 - buf[pos++] = r; + if (pos < length) + buf[pos++] = r; + else + { + buf.resize (length * 2); + length = buf.length (); + buf[pos++] = r; + } }