/* Bot0 - DMS - May 98 - by Sylvain HUET [CRYO] KBot source file - KBot by Vincent CARON [QUAERIS] - July 98 ***** ***** *** THIS PACKAGE IS BROUGHT TO YOU BY QUAERIS *** ** ** *** www.quaeris.com - I-net solutions ! *** ***** *****/ /*************************************/ /* */ /* Variables and constants */ /* */ /*************************************/ /* bot configuration parameters, accessible in kbot cfgfile */ var bot_name =" ";; var scenario_file ="Dms/Bots/KBot/example.sc";; var help_file ="Dms/Bots/KBot/kbot.hlp";; var MSG_unknown ="Sorry ?";; var MSG_bot_reset ="*** RESTARTING ***";; var MSG_already_on ="I'm already here !";; var MSG_loginchg ="So I'll call you now...";; var MSG_stopped ="You can call me back with 'kbot' !";; var MSG_isback ="Welcome back !";; var MSG_log_unkwn ="Can't send message : unknown login";; var COM_start ="kbot";; var COM_stop ="bye";; var COM_reset ="reset";; var COM_help ="help";; var COM_info ="info";; var COM_ans ="ans";; var COM_who ="who";; var COM_say ="say";; var _debug_ =0;; /* debug scenario loading sequence*/ var auto_disp_ans =0;; /* displays possible answer at each part */ var auto_unregister =1;; /* unregister client at deconnection (safer!) */ var auto_reactivate =1;; /* reactivate robot for a known client at reconnection */ var auto_reply =1;; /* robots always reply, even MSG_unknown */ var disp_globals =1;; /* displays global keywords. dependent of auto_disp_ans */ /* config variable names definition */ var CFG_bot_name ="Bot_name";; var CFG_scenario_file ="Scenario_file";; var CFG_help_file ="Help_file";; var CFG_COM_start ="COM_start";; var CFG_COM_stop ="COM_stop";; var CFG_COM_reset ="COM_reset";; var CFG_COM_help ="COM_help";; var CFG_COM_info ="COM_info";; var CFG_COM_ans ="COM_answers";; var CFG_COM_who ="COM_who";; var CFG_COM_say ="COM_say";; var CFG_MSG_unknown ="MSG_no_answer";; var CFG_MSG_bot_reset ="MSG_reset";; var CFG_MSG_already_on ="MSG_already_on";; var CFG_MSG_loginchg ="MSG_login_chg";; var CFG_MSG_stopped ="MSG_stopped";; var CFG_MSG_isback ="MSG_isback";; var CFG_MSG_log_unkwn ="MSG_log_unknown";; var CFG__debug_ ="_debug_";; var CFG_auto_disp_ans ="Auto_display_ans";; var CFG_auto_unregister ="Auto_unregister";; var CFG_auto_reactivate ="Auto_reactivate";; var CFG_auto_reply ="Auto_reply";; var CFG_disp_globals ="Display_globals";; /* error management */ typeof SCerr =I;; typeof SCline =I;; typeof SCmess =S;; var bot_sleep =0;; var MSG_scerr ="Scenario error : ";; var MSG_sc_loaded ="Scenario loaded";; var MSG_errlist = ("no error")::("unexpected tag")::("invalid order parameter"):: ("unexpected enf of file")::("wrong scenario version")::("version not found"):: ("entry not found")::("invalid part reference")::("scenario file not found"):: ("global not found")::nil;; var ERR_unexp_tag = 1;; var ERR_inv_order = 2;; var ERR_unexp_eof = 3;; var ERR_wrong_ver = 4;; var ERR_ver_tag = 5;; var ERR_entry_tag = 6;; var ERR_inv_ref = 7;; var ERR_sc_not_found = 8;; var ERR_global_tag = 9;; var MSG_chk_error ="Scenario check : ";; var MSG_chk_entry ="entry part not defined";; var MSG_chk_global ="global part not defined";; var MSG_chk_link ="part not defined";; /* config file name and location (default) */ typeof dmifile=S;; typeof config_file=S;; var MSG_cfg_not_found ="Config file not found (using default parameters)";; var MSG_cfg_loaded ="Configuration file loaded";; /* scenario defs */ typeof SC_entry =I;; /* scenario entry */ typeof SC_global=I;; /* global part */ var SC_version =3;; /* scenario file version -not configurable!- */ var K_order =1;; var K_cycle =2;; var K_random =3;; var K_order_str ="order";; var K_cycle_str ="cycle";; var K_random_str="random";; /* scenario = list of [reference, message_order, list of message, list of [answer, ref]] */ typeof scenario=[[I I [S r1] [[S I] r1]] r1];; /* bot_clients = list of [login, current_part, active, list of [part_ref, text_ref]] */ typeof bot_clients=[[S I I [[I I] r1]] r1];; /* help window file handle */ typeof hwin=ObjWin;; /*************************************/ /* */ /* Bot events */ /* */ /*************************************/ /* display text to all chat clients. S -> ? */ fun broad(text)=_DMSevent this nil "broad" text nil;; /* display text to client cli only. CLIENT, S -> ? */ fun private(cli,text)=_DMSevent this cli "private" (strcat text "\n") nil;; /* output text to log event. S -> ? */ fun klog(text)=_DMSevent this nil "log" (strcat bot_name text) nil;; /* user defined event with parameter. S, CLIENT, S -> ? */ fun user(event,cli,text)=_DMSevent this cli event text nil;; /*************************************/ /* */ /* Help window display */ /* */ /*************************************/ /* resize function for the help window */ fun _hresize(a,t,x,y)=_SIZEtext t x-2 y-2 1 1;; /* display help window with text from _helpfile */ fun bot_help()= let _CRwindow _channel hwin 150 150 330 340 WN_MENU+WN_MINBOX+WN_SIZEBOX strcat bot_name "Help" -> hwin in _CBwinSize hwin @_hresize (_CRtext _channel hwin 1 1 328 338 ET_VSCROLL+ET_HSCROLL _getpack _checkpack help_file);; /*************************************/ /* */ /* Bot tag processor */ /* */ /*************************************/ /* returns pos of tag b in string a if found (call with pos=0), nil else. S, S, I -> I */ fun subfind(a,b,pos)= if (strlen a)>=(strlen b) then if !strcmpi (substr a 0 strlen b) b then pos else subfind (substr a 1 (strlen a)-1) b pos+1 else nil;; /* replace a tag in a string. S, S, S -> S */ fun replace_tag(l,tag,replace)= let subfind l tag 0 -> _pos in if _pos!=nil then strcatn (substr l 0 _pos)::replace::(substr l (_pos+strlen tag) ((strlen l) - (strlen tag) - _pos))::nil else l;; /* interprets the tag and returns the string without the command */ fun detect_event(cli,line)= if line!=nil then let line -> [_head _tail] in if !strcmpi _head "" then let _tail -> [_head _tail] in (klog strcat "Sending event : " _head; _DMSevent this cli _head nil nil; let _tail -> [_head _tail] in strcat strcat _head " " detect_event cli _tail) else strcat strcat _head " " detect_event cli _tail else nil;; /* tag processor, replaces tags in string. S -> S */ fun process_tags(cli,l)= let detect_event cli (hd strextr l) -> _s in let replace_tag _s "" (_DMSgetLogin cli) -> _s in let replace_tag _s "" (itoa sizelist bot_clients) -> _s in _s;; /* modified broad function, call tag processor before. S -> ? */ fun _broad(text)= broad /*process_tags*/ text;; /* modified private function, call tag processor before. CLIENT, S -> ? */ fun _botprivate(cli,text)= let process_tags cli text -> _txt in if (_txt==nil) || (!strcmp _txt " ") then nil else private cli strcat bot_name _txt;; /*************************************/ /* */ /* Bot clients managing functions */ /* */ /*************************************/ /* search a client from login. [[S _ _ _] r1], S -> [S _ _ _] */ fun search_cli(l,login)= if l!=nil then let l -> [_head _tail] in let _head -> [_log _ _ _] in if !strcmpi _log login then _head else search_cli _tail login else nil;; /* remove a client from login. [[S _ _ _] r1], S -> [[S _ _ _] r1] */ fun remove_cli(l,login)= if l!=nil then let l -> [_head _tail] in let _head -> [_log _ _ _] in if !strcmpi _log login then _tail else _head::(remove_cli _tail login) else nil;; /* check if client known, register if necessary. CLIENT -> I=1 (known),0(new)*/ fun register_client(cli)= let _DMSgetLogin cli -> _login in let search_cli bot_clients _login -> _item in if _item==nil then /* login not found in bot clients list */ (set bot_clients=[_login SC_entry 1 nil]::bot_clients; klog strcatn "New client '"::_login::"' registered ("::(itoa sizelist bot_clients)::" in list)"::nil; 0) else (if auto_reactivate then mutate _item <- [_ _ 1 _] else nil; _botprivate cli MSG_isback; klog strcatn "Known client '"::_login::"' reconnected ("::(itoa sizelist bot_clients)::" in list)"::nil; 1);; /* remove client from bot clients list. S -> I */ fun _unregister_client(_login)= (set bot_clients=remove_cli bot_clients _login; klog strcatn "Client '"::_login::"' removed ("::(itoa sizelist bot_clients)::" left)"::nil);; /* remove client from bot clients list. CLIENT -> I */ fun unregister_client(cli)= _unregister_client (_DMSgetLogin cli);; /* manage login change & remove anonymous logins. CLIENT, S -> ? */ fun change_login(cli,oldlog)= if bot_sleep then nil else (klog strcatn "Login change '"::oldlog::"' -> '"::(_DMSgetLogin cli)::"' :"::nil; register_client cli; _botprivate cli MSG_loginchg; if !strcmpi (substr oldlog 0 5) "guest" then (klog "Auto-remove filter :"; _unregister_client oldlog) else nil; );; /* get bot activity for client. CLIENT -> I */ fun get_activity(cli)= let search_cli bot_clients (_DMSgetLogin cli) -> [_ _ _act _] in _act;; /* set bot activity for client. CLIENT, I -> I */ fun set_activity(cli,act)= let search_cli bot_clients (_DMSgetLogin cli) -> _item in mutate _item <- [_ _ act _];; /*************************************/ /* */ /* Scenario managing functions */ /* */ /*************************************/ /* set client current part. CLIENT I -> I */ fun set_client_part(cli,ref)= let search_cli bot_clients (_DMSgetLogin cli) -> _item in mutate _item <- [_ ref _ _];; /* search for a part in a client history list, returns ref/subref. [[I I] r1], I -> I */ fun search_part(l,ref)= if l!=nil then let l -> [_head _tail] in let _head -> [_ref _subref] in if ref==_ref then _subref else search_part _tail ref else nil;; /* update a subref in history list. [[I I] r1], I, I -> [[I I] r1] */ fun update_his(l,ref,subref)= if l!=nil then let l -> [_head _tail] in let _head -> [_ref _subref] in if ref==_ref then [_ref subref]::update_his _tail ref subref else [_ref _subref]::update_his _tail ref subref else nil;; /* random function, returns integer 1<=i<=parameter. I -> I */ fun my_rand(range)= let rand -> i in if (i>=1) && (i<=range) then i else my_rand range;; /* returns scenario part reference ref */ fun nth_part(l,ref)= if l!=nil then let l -> [_head _tail] in let _head -> [_ref _ _ _] in if ref==_ref then _head else nth_part _tail ref else nil;; /* returns text string and update client history list. CLIENT -> S */ fun get_part_text(cli)= let search_cli bot_clients (_DMSgetLogin cli) -> _client in let _client -> [_log _ref _act _his] in let nth_part scenario _ref -> [_ _order _parts _] in let search_part _his _ref -> _subref in if _subref!=nil then /* this part ref is in history, update _subref */ (if _order==K_cycle then if _subref<(sizelist _parts) then set _subref=_subref+1 else set _subref=1 else if _order==K_order then if _subref<(sizelist _parts) then set _subref=_subref+1 else 0 else if _order==K_random then set _subref=my_rand (sizelist _parts) else 0; mutate _client <- [_ _ _ (update_his _his _ref _subref)]; nth_list _parts (_subref-1)) else /* part not in history. create a history entry */ (mutate _client <- [_ _ _ [_ref 1]::_his]; nth_list _parts 0);; /* submodule (recursive part) of get_anss. [[S I] r1] -> S */ fun _get_anss(l)= if l!=nil then let l -> [_head _tail] in let _head -> [_ans _] in strcat strcat strcat (_get_anss _tail) "[" _ans "] " else nil;; /* returns global keywords. -> S */ fun get_anss_global()= let nth_part scenario SC_global -> [_ _ _ _anss] in _get_anss _anss;; /* returns possible answers. CLIENT -> S */ fun get_anss(cli)= let search_cli bot_clients (_DMSgetLogin cli) -> _client in let _client -> [_ _ref _ _] in let nth_part scenario _ref -> [_ _ _ _anss] in _get_anss _anss;; /* returns known keywords (current part+global) */ fun bot_keywords(cli)= (let get_anss cli -> _anss in if _anss!=nil then private cli (get_anss cli) else nil; let get_anss_global -> _anss in if disp_globals && (_anss!=nil) then private cli strcat "Globals : " _anss else nil; 0);; /* outs bot part text to chat window */ fun bot_talk(cli)= if bot_sleep then nil else let get_part_text cli -> _txt in if _txt!=nil then (_botprivate cli _txt; if auto_disp_ans then bot_keywords cli else nil) else nil;; /* search for a keyword in txt, returns the link or nil. S, [[S I] r1] -> I */ fun find_keyword(keyws,txt)= if keyws!=nil then let keyws -> [_head _tail] in let _head -> [_ans _link] in if (subfind txt _ans 0)!=nil then _link else find_keyword _tail txt else 0;; /* interprets answer if possible, and call get_part_text logic. CLIENT, S -> I */ fun bot_logic(cli,text)= /* current part keywords */ let search_cli bot_clients (_DMSgetLogin cli) -> [_ _ref _ _] in let nth_part scenario _ref -> [_ _order _parts _anss] in let find_keyword _anss text -> _link in if _link!=0 then (set_client_part cli _link; bot_talk cli; 0) else /* global keywords */ let nth_part scenario SC_global -> [_ _ _ _anss] in let find_keyword _anss text -> _link in if _link!=0 then (set_client_part cli _link; bot_talk cli; set_client_part cli _ref; 0) else if auto_reply then (_botprivate cli MSG_unknown; 0) else 0;; /*************************************/ /* */ /* Bot command functions */ /* */ /*************************************/ /* submodule of bot_info */ fun _get_act(act)= if act then "active" else "disabled";; /* submodule of bot_info */ fun _get_his(l)= if l!=nil then let l -> [_head _tail] in let _head -> [_ref _subref] in strcat strcat (_get_his _tail) " " (itoa _ref) else nil;; /* returns info on a client */ fun bot_info(cli,param)= (if param==nil then set param=_DMSgetLogin cli else nil; let search_cli bot_clients param -> _item in if _item!=nil then let _item -> [_ _ref _act _his] in private cli strcatn "Bot is "::(_get_act _act)::", ref. "::(itoa _ref)::"\nHistory :"::(_get_his _his)::nil else private cli "Login not found!");; /* resets the robot for current client */ fun bot_reset(cli)= (_botprivate cli MSG_bot_reset; let search_cli bot_clients (_DMSgetLogin cli) -> _item in mutate _item <- [_ SC_entry 1 nil]; bot_talk cli);; /* stops the bot for current client */ fun bot_stop(cli)= (set_activity cli 0; _botprivate cli MSG_stopped);; /* restarts the bot for current client */ fun bot_start(cli)= (set_activity cli 1; bot_talk cli);; /* lists clients (all registered by server) */ fun bot_who(l)= if l!=nil then let l -> [_head _tail] in strcat strcat _DMSgetLogin _head "\n" bot_who _tail else nil;; /* search client by login. [CLIENT r1], S -> CLIENT */ fun get_by_login(l,login)= if l!=nil then let l -> [_cli _tail] in if !strcmpi login (_DMSgetLogin _cli) then _cli else get_by_login _tail login else nil;; /* sends a message to a designed client */ fun bot_say(cli,text)= let hd strextr text -> [_com _tail] in let _tail -> [_dest _tail] in let get_by_login DMSclients _dest -> _cli in if _cli!=nil then private _cli strcatn "["::(_DMSgetLogin cli)::"] "::(strbuild _tail::nil)::nil else private cli MSG_log_unkwn;; /*************************************/ /* */ /* Scenario file loading functions */ /* */ /*************************************/ /* list concatenation function */ fun listcat(a,b)= if a==nil then b else let a -> [_head _tail] in [_head listcat _tail b];; /* error log function */ fun kerror(err)= (set SCerr=err; set SCmess=nth_list MSG_errlist err);; /* display error message and line number */ fun kerr_disp()= (klog strcatn MSG_scerr::SCmess::" (# "::(itoa SCline)::")"::nil; set bot_sleep=1);; /* sleep only if an error is displayed ! */ /* extracts first and second word from a line. S -> [S S] */ fun get_tag(l)= let hd strextr l -> _line in let _line -> [_head _tail] in [_head (hd _tail)];; /* 0: no tag found, 1: tag found, -1: unexpected tag */ fun check_tag(a,tag)= if !strcmp (substr a 0 1) "[" then if !strcmpi a tag then 1 else (kerror ERR_unexp_tag; -1) else 0;; /* wait for a specific tag. Returns next line, tag parameter and error. [S r1] -> [[S r1] S I] */ fun wait_tag(l,tag)= if l!=nil then let l -> [_head _tail] in let get_tag _head -> [_tag _param] in (set SCline=SCline+1; let check_tag _tag tag -> _check in if _check==0 then wait_tag _tail tag /* tag not found, continue */ else if _check==1 then [_tail _param 0] /* tag found */ else [_tail _param 1]) /* unexpected tag ! */ else (kerror ERR_unexp_eof; [nil nil 1]);; /* end of file ! */ /* interprets order/random parameter. Returns K_xxx constant or -1 if error. S -> I */ fun get_order(_param)= if !strcmp _param K_order_str then K_order else if !strcmp _param K_cycle_str then K_cycle else if !strcmp _param K_random_str then K_random else (kerror ERR_inv_order; -1);; /* check reference validity. Returns 1=error, 0 else. I -> I */ fun check_ref(ref)= if (ref<1) || (ref>31999) then (kerror ERR_inv_ref; 1) else 0;; /* read text lines until [links] tag. [S r1] -> [[S r1] [S r1] I] */ /* (lines -> text_list,lines,error) */ fun get_texts(l)= if l!=nil then let l -> [_line _head] in let get_tag _line -> [_tag _] in let check_tag _tag "[links]" -> _check in (set SCline=SCline+1; if _check==1 then [nil _head 0] /* links tag found */ else if _check==0 then let get_texts(_head) -> [_list _l _err] in [_line::_list _l _err] /* no tag found, add string to list */ else [nil nil 1]) /* unexpected tag */ else (kerror ERR_unexp_eof; [nil nil 1]);; /* read link lines until [endp] tag. [S r1] -> [[[S I] r1] [S r1] I] */ /* (lines -> link_list,lines,error) */ fun get_links(l)= if l!=nil then let l -> [_line _head] in let get_tag _line -> [_tag _param] in let check_tag _tag "[endp]" -> _check in (set SCline=SCline+1; if _check==1 then [nil _head 0] else if _check==0 then let get_links(_head) -> [_list _l _err] in [[_tag (atoi _param)]::_list _l _err] else [nil nil 1]) else (kerror ERR_unexp_eof; [nil nil 1]);; /* load parts recursively. Returns 1 if error, 0 else. [S r1] -> [[S r1] I] */ fun load_part(l)= let wait_tag l "[part]" -> [_l _param _err] in if SCerr==ERR_unexp_eof then 0 /* end of file */ else if _err==1 then 1 /* unexpected tag */ else let atoi _param -> _p_ref in if check_ref _p_ref then 1 /* invalid reference */ else let wait_tag _l "[text]" -> [_l _param _err] in if _err==1 then 1 /* unexpected tag */ else let get_order _param -> _p_order in if _p_order==-1 then 1 /* invalid order parameter */ else let get_texts _l -> [_p_txt _l _err] in if _err==1 then 1 /* text read error */ else let get_links _l -> [_p_links _l _err] in if _err==1 then 1 /* link read error */ else (set scenario=[_p_ref _p_order _p_txt _p_links]::scenario; load_part _l);; /* check for version tag and version number. [S r1] -> [S r1] */ fun load_version(l)= let l -> [_line _tail] in let get_tag _line -> [_tag _param] in if !strcmp _tag "version" then if (atoi _param)==SC_version then (set SCline=SCline+1; _tail) else (kerror ERR_wrong_ver; nil) else (kerror ERR_ver_tag; nil);; /* reads scenario entry part reference. [S r1] -> [S r1] */ fun load_entry(l)= let l -> [_line _tail] in let get_tag _line -> [_tag _param] in if !strcmp _tag "entry" then let atoi _param -> _ref in if check_ref _ref then nil else (set SC_entry=_ref; set SCline=SCline+1; _tail) else (kerror ERR_entry_tag; nil);; /* reads scenario global part reference. [S r1] -> [S r1] */ fun load_global(l)= let l -> [_line _tail] in let get_tag _line -> [_tag _param] in if !strcmp _tag "global" then let atoi _param -> _ref in if check_ref _ref then nil else (set SC_global=_ref; set SCline=SCline+1; _tail) else (kerror ERR_global_tag; nil);; /* loads scenario from file */ fun load_scenario()= (set SCerr=0; set SCline=1; let lineextr _getpack _checkpack scenario_file -> _lines in if _lines==nil then (kerror ERR_sc_not_found; kerr_disp) else let load_version _lines -> _lines in if _lines==nil then kerr_disp /* version error */ else let load_entry _lines -> _lines in if _lines==nil then kerr_disp /* entry error */ else let load_global _lines -> _lines in if _lines==nil then kerr_disp /* global error */ else (set SCline=SCline-1; if (load_part _lines)==0 then klog MSG_sc_loaded else kerr_disp));; /*************************************/ /* */ /* Scenario checking */ /* */ /*************************************/ /* check_links() submodule */ fun _check_links(l,part)= if l!=nil then let l -> [_head _tail] in (let _head -> [_lnk _ref] in if (nth_part scenario _ref)==nil then (klog strcatn MSG_chk_error::MSG_chk_link::" (part "::(itoa part)::", link '"::_lnk::"')"::nil; set bot_sleep=1) else 0; _check_links _tail part) else 0;; /* check links validity */ fun check_links(l)= if l!=nil then let l -> [_head _tail] in (let _head -> [_ref _ _ _links] in _check_links _links _ref; check_links _tail) else 0;; /* assume part references and links are valid */ fun check_scenario()= (if (nth_part scenario SC_entry)==nil then (klog strcat MSG_chk_error MSG_chk_entry; set bot_sleep=1) else if (nth_part scenario SC_global)==nil then (klog strcat MSG_chk_error MSG_chk_global; set bot_sleep=1) else nil; check_links scenario);; /*************************************/ /* */ /* Configuration file managing */ /* */ /*************************************/ fun get_cfgfile(l)= if l!=nil then let l -> [_head _tail] in let get_tag _head -> [_p1 _p2] in if !strcmpi _p1 "cfgfile" then (set config_file=_p2; 0) else (get_cfgfile _tail; 0) else 0;; fun process_cfg(l)= if l!=nil then let l -> [_head _tail] in let get_tag _head -> [_var _param] in (if !strcmpi _var CFG_bot_name then (set bot_name=_param; 0) else if !strcmpi _var CFG_scenario_file then (set scenario_file=_param; 0) else if !strcmpi _var CFG_help_file then (set help_file=_param; 0) else if !strcmpi _var CFG_COM_start then (set COM_start=_param; 0) else if !strcmpi _var CFG_COM_stop then (set COM_stop=_param; 0) else if !strcmpi _var CFG_COM_reset then (set COM_reset=_param; 0) else if !strcmpi _var CFG_COM_help then (set COM_help=_param; 0) else if !strcmpi _var CFG_COM_info then (set COM_info=_param; 0) else if !strcmpi _var CFG_COM_ans then (set COM_ans=_param; 0) else if !strcmpi _var CFG_COM_who then (set COM_who=_param; 0) else if !strcmpi _var CFG_COM_say then (set COM_say=_param; 0) else if !strcmpi _var CFG_MSG_unknown then (set MSG_unknown=_param; 0) else if !strcmpi _var CFG_MSG_bot_reset then (set MSG_bot_reset=_param; 0) else if !strcmpi _var CFG_MSG_already_on then (set MSG_already_on=_param; 0) else if !strcmpi _var CFG_MSG_loginchg then (set MSG_loginchg=_param; 0) else if !strcmpi _var CFG_MSG_stopped then (set MSG_stopped=_param; 0) else if !strcmpi _var CFG_MSG_isback then (set MSG_isback=_param; 0) else if !strcmpi _var CFG_MSG_log_unkwn then (set MSG_log_unkwn=_param; 0) else if !strcmpi _var CFG__debug_ then (set _debug_=atoi _param; 0) else if !strcmpi _var CFG_auto_disp_ans then (set auto_disp_ans=atoi _param; 0) else if !strcmpi _var CFG_auto_unregister then (set auto_unregister=atoi _param; 0) else if !strcmpi _var CFG_auto_reactivate then (set auto_reactivate=atoi _param; 0) else if !strcmpi _var CFG_auto_reply then (set auto_reply=atoi _param; 0) else if !strcmpi _var CFG_disp_globals then (set disp_globals=atoi _param; 0) else 0; process_cfg _tail) else 0;; fun load_config()= (let lineextr _getpack _checkpack dmifile -> _lines in get_cfgfile _lines; let lineextr _getpack _checkpack config_file -> _lines in if _lines==nil then (klog MSG_cfg_not_found; 0) else (process_cfg _lines; klog MSG_cfg_loaded; 0));; /*************************************/ /* */ /* Bot actions */ /* */ /*************************************/ /* this function is called when someone says something */ /* cli = the visitor that have spoken (CLIENT type) */ /* text= the text the visitor said (S) */ fun hear_bot(cli,text)= if bot_sleep then nil else let get_tag text -> [_tag _param] in /* these are commands always available */ if !strcmp _tag COM_help then (bot_help; 0) else if !strcmp _tag COM_info then (bot_info cli _param; 0) else if !strcmp _tag COM_reset then (bot_reset cli; 0) else if !strcmp _tag COM_who then (private cli bot_who DMSclients; 0) else if !strcmp _tag COM_say then (bot_say cli text; 0) else if get_activity cli then /* these are commands available only when the bot is active for cli */ (if !strcmp _tag COM_stop then (bot_stop cli; 0) else if !strcmp _tag COM_start then (_botprivate cli MSG_already_on; 0) else if !strcmp _tag COM_ans then (bot_keywords cli; 0) else (bot_logic cli text; 0)) else /* these are commands available only when the bot is disabled for cli */ (if !strcmp _tag COM_start then (bot_start cli; 0) else nil);; /* this function is called when someone is in */ /* cli = the visitor that have spoken */ fun in_bot(cli)= if bot_sleep then nil else (register_client cli; bot_talk cli);; /* this function is called when someone is out */ /* cli = the visitor that have spoken */ fun out_bot(cli)= if bot_sleep then nil else if auto_unregister then unregister_client cli else nil;; /*******************************************/ /* */ /* PLEASE DO NOT CHANGE THE FOLLOWING CODE */ /* */ /*******************************************/ fun activate(from,cli,action,param,rep)= if !strcmp action "in" then (in_bot cli;0) else if !strcmp action "out" then (out_bot cli;0) else if !strcmp action "hear" then (hear_bot cli param;0) else if !strcmp action "!chglogin" then (change_login cli param; 0) else if !strcmp action "run" then (set_activity cli 1; 0) else if !strcmp action "stop" then (set_activity cli 0; 0) else nil;; fun _debug_ans(l)= if l!=nil then let l -> [_head _tail] in let _head -> [_ans _link] in (klog strcatn "+"::_ans::" -> "::(itoa _link)::nil; _debug_ans _tail) else 0;; fun _debug_part(l)= if l!=nil then let l -> [_head _tail] in (klog strcat "*" _head; _debug_part _tail) else 0;; fun _debug(l)= if l!=nil then let l -> [_head _tail] in let _head -> [_ref _order _parts _anss] in (klog itoa _ref; _debug_part _parts; if _parts==nil then klog "! no text !" else nil; _debug_ans _anss; if _anss==nil then klog "! no keywords !" else nil; _debug _tail) else 0;; fun IniDMI(file)= (set dmifile=file; klog strcat "starting KBot v" (itoa SC_version); load_config; load_scenario; if _debug_ then _debug scenario else 0; if !bot_sleep then check_scenario else 0; _DMSregisterDMI this @activate nil nil nil);;