% Standard Pack script for SLirc. % No luser serviceable parts here. % You're welcome to change things if you're not a luser, though. irc_log("[STD-Pack] Version 0.11.7 loading."); irc_update_display(); add_cmnd("msg"); % want this 1st so /m expands to it private variable server_recv_time; private variable s_pinged = 0; % Joinbots detection... private variable joinbots = -1; %define PUhandler(key,n,s) %{ % irc_Inff("key=%.2x, n=%d, \"%s\"",key,n,s); % if (key == 'q') irc_destroy_popup(); %} %irc_create_popup("STANDARD.SL", "item1\nitem2\nitem3", "PUhandler"); %irc_update_display(); define close_server() { () = clr_action(irc_server); () = vf_close(irc_server); irc_log("[STD-Pack] Closing..."); irc_update_display(); if (resolver != NULL) { () = clr_action(irc_server); () = vf_close(resolver); } irc_exit("User Quit."); } add_cmnd("discon"); define command_DISCON(s) { variable b,n; s = strcompress(s," "); !if (int(s)) s = "SLirc"; irc_send_string("QUIT: %s\r\n"); () = clr_action(irc_server); () = vf_close(irc_server); irc_server = NULL; irc_Inff("Disconnecting from %s: %s",irc_servername,s); irc_set_servername("*"); nick_chan = make_list(); nick_act = make_list(); chan_on_connect = on_chans; on_chans = NullString; join_chans = NullString; } % And now some (A few) command handlers. % /NICK also changes the client's idea of what the Nick is... add_cmnd("nick"); define command_NICK(s) { irc_set_nickname(s); irc_send_string(sprintf("NICK %s\r\n", irc_nickname)); } add_cmnd("showinfo"); define command_SHOWINFO(p) { variable y = irc_showinfo; irc_set_showinfo(1 - y); variable s = "OFF"; if (irc_showinfo) s = "ON"; irc_Logf("showinfo is now %s",s); } add_cmnd("time"); define command_TIME(p) { irc_send_string("TIME\r\n"); } add_cmnd("invite"); define command_INVITE(p) { p = strcompress(p," ,"); irc_send_string(sprintf("INVITE %s\r\n",p)); irc_Inff("Inviting %s to %s",v_split(p," ")); } add_cmnd("version"); define command_VERSION(p) { p = strcompress(p," ,"); irc_send_string(sprintf("VERSION %s\r\n",p)); } add_cmnd("userhost"); define command_USERHOST(p) { % rfc says up to 5 nicks separated by ' ' p = strcompress(p," ,"); irc_send_string(sprintf("USERHOST %s\r\n",p)); } private define func_help(pfx,s) { variable a,b,n,i,text; n = 1 + strlen(pfx); a = _apropos("Global", pfx + strup(s), 0x2); b = array_sort(a,&strcmp); a = a[b]; for (i=0; i (%s)",uhost,Rpms[R_trailing]); savewhoisline(nick); nick_chan_add(nick,uhost,NullString); } % 312 RPL_WHOSERVER define SrvN_312() { !if(Twhois) return; sprintf(". IRC-Server [%s] (%s)",Rpms[4],Rpms[R_trailing]); savewhoisline(Rpms[3]); } % 317 RPL_WHOIDLE define SrvN_317() { !if(Twhois) return; %sprintf(". idle for %s secs, signed on at %s", Rpms[4],ctime(Rpms[5])); variable utm = integer(Rpms[5]); sprintf(". idle for %s secs, signed on at %s", Rpms[4],ctime(utm)); savewhoisline(Rpms[3]); } % 319 RPL_WHOISCHANNELS define SrvN_319() { !if(Twhois) return; sprintf(". on channels: %s",Rpms[R_trailing]); savewhoisline(Rpms[3]); nick_chan_add_chans(Rpms[3],Rpms[R_trailing]); } % 401 ERR_NOSUCHNICK define SrvN_401() { if(Twhois) { sprintf(". %s",Rpms[R_trailing]); savewhoisline(Rpms[3]); }else irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } % 402 ERR_NOSUCHSERVER define SrvN_402() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); if(Twhois) if (is_prefix(Pwhois,Rpms[3])) Twhois = 0; if(Tlist) Tlist = 0; } % 403 ERR_NOSUCHCHANNEL define SrvN_403() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } % 404 ERR_CANNOTSENDTOCHANNEL define SrvN_404() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } % 405 ERR_TOOMANYCHANNELS define SrvN_405() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } % 406 ERR_WASNOSUCHNICK define SrvN_406() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } % 421 ERR_UNKNOWNCOMMAND define SrvN_421() { irc_Inff("%s: %s",Rpms[3],Rpms[R_trailing]); } private define irc_infol(ls,targ) { variable p0,p; p0 = ls.f; if (p0 != NULL) { p = p0; do { irc_info(p.v,targ); p = p.n; }while (p != p0); } } private define prf318(p,i) { irc_info(sprintf("[%s] Whois Response:",p.v.nick),Wwhois); irc_infol(p.v.ls,Wwhois); } % 318 RPL_ENDOFWHOIS define SrvN_318() { !if(Twhois) return; s_dofunc(Lwhois,&prf318); Twhois = 0; Lwhois = NULL; % destroy it } % 314 RPL_WHOWASUSER define SrvN_314() { irc_info( sprintf("[%s] was <%s@%s> (%s)",Rpms[3],Rpms[4],Rpms[5],Rpms[R_trailing]), Wwhowas); } % 321 RPL_LISTSTART define SrvN_321() { !if (Tlist) return; Tlist = unix_time; } % 322 RPL_LISTSTART define SrvN_322() { % channel,#visible,topic !if (Tlist) return; () = s_putlast(Llist,sprintf("%-11s%4s %s",Rpms[3],Rpms[4],Rpms[5])); Tlist = unix_time; } private define prf323(p,i) { irc_info(p.v,Wlist); } % 323 RPL_LISTEND define SrvN_323() { !if (Tlist) return; irc_info(sprintf("List Response [%s] : %d",Plist,Llist.ct),Wlist); if (Llist.ct) { irc_info("CHANNEL USERS --TOPIC----",Wlist); s_dofunc(Llist,&prf323); } Llist = NULL; % destroy list Tlist = 0; } % 369 RPL_ENDOFWHOWAS define SrvN_369() { Wwhowas = "*"; } % 315 RPL_ENDOFWHO define SrvN_315() { variable nklo = strlow(Rpms[3]); if (is_list_element(igh_nicks,nklo,' ')) igh_nicks = cut_list_element(igh_nicks,nklo,' '); % irc_Logf("%s: %s", Rpms[3], Rpms[R_trailing]); } % 331 RPL_NOTOPIC define SrvN_331() { irc_info(sprintf("%s: ", Rpms[3], Rpms[R_trailing]),Rpms[3]); } % 332 RPL_TOPIC define SrvN_332() { irc_info(sprintf("Topic for %s: %s", Rpms[3], Rpms[R_trailing]),Rpms[3]); } % 333 says who set topic & when define SrvN_333() { variable secs = integer(Rpms[5]); irc_info(sprintf("Topic for %s set by: %s on %s", Rpms[3], Rpms[4], ctime(secs)),Rpms[3]); } % 352 RPL_WHO define SrvN_352() { variable p,nklo,uhost; nklo = strlow(Rpms[7]); uhost = sprintf("%s@%s",Rpms[4],Rpms[5]); if (is_list_element(igh_nicks,nklo,' ')) igh_who_tail(nklo,uhost); else irc_info(sprintf("%-10s%-10s%-3s <%s>:%s", Rpms[3],Rpms[7],Rpms[8], uhost,Rpms[R_trailing]),Wwho); % now cache the uhost info to nick_chan list, if it's a known nick: p = s_find_n1(nick_chan.f,&NC0_cmp,Rpms[7]); if (p != NULL) nick_chan_add_uhost(p,uhost); } % 353 RPL_NAMREPLY define SrvN_353() { % irc_Logf("[%s] (%s) (%s) (%s) (%s) (%s)", Rpms[0], Rpms[1], Rpms[2], Rpms[3], Rpms[4], Rpms[5]); % Rpms[4] is the channel if (R_trailing) { variable b,nick; if (is_list_element(on_chans,strlow(Rpms[4]),' ')) { b = strchop(Rpms[R_trailing],' ',0); foreach (b) { nick = (); !if (int(nick)) continue; nick_chan_add(nick,NullString,Rpms[4]); } } chan_name_list = chan_name_list + Rpms[R_trailing]; } } % 366 RPL_ENDOFNAMES define SrvN_366() { % irc_Logf("[%s] (%s) (%s) (%s) (%s)", Rpms[0], Rpms[1], Rpms[2], Rpms[3], Rpms[4]); % Rpms[3] is the channel irc_info(sprintf("NAMES: %s",chan_name_list),Wnames); } % 433 ERR_NICKNAMEINUSE define SrvN_433() { command_NICK(sprintf("%s_", irc_nickname)); irc_set_status("Duplicate Nick..."); } % 451 ERR_ server 451 nick COMM "Register First" define SrvN_451() { if (Rpms[2] == irc_nickname) irc_set_status("Not Yet Registered"); } % 471 ERR_CHANNELISFULL server 471 nick chan "Cannot join channel (+l)" % 473 ERR_INVITEONLYCHAN server 473 nick chan "Cannot join channel (+i)" % 474 ERR_BANNEDFROMCHAN server 474 nick chan "Cannot join channel (+b)" % 475 ERR_BADCHANNELKEY " server 475 nick chan Cannot join channel (+k)" define SrvN_47x() { variable chan = Rpms[3]; if (Rpms[2] == irc_nickname) { irc_info(sprintf("[%s] %s: %s",Rpms[1],chan,Rpms[R_trailing]),chan); join_chans = cut_list_element(join_chans,chan,' '); % cut from pending } } % 513 uhm, define SrvN_513() { variable tail = Rpms[R_trailing]; variable i = is_substr(tail," PONG "); irc_Logf("513: (%d)%s", i, tail); if (i) { i += 6; tail = substr(tail,i,strlen(tail) + 1 - i); irc_send_string(sprintf("PONG %s\r\n", tail)); irc_log(sprintf("sent /PONG %s", tail)); return; } close_server(); } #ifdef ENEMIES define lame_check() { variable s = Rpms[3]; variable i,j; i = index(s,3); if (i) { j = rindex(s,3); if (j>i) return 1; j = rindex(s,7); if (j>i) return 1; } i = index(s,7); if (i) { j = rindex(s,3); if (j>i) return 1; j = rindex(s,7); if (j>i) return 1; } return 0; } #endif define SrvA_PRIVMSG() { % irc_log(sprintf("PRIVMSG from %s to %s found.", Rpms[0], Rpms[2])); variable p, nick, uhost; variable trgt = Rpms[2]; variable text = Rpms[3]; (nick,uhost) = v_split(Rpms[0],"!"); p = nick_chan_check(Rpms[0],Rpms[2],0); % p==0 might be interpreted as an ignore !if (p) return; #ifdef ENEMIES if (assoc_key_exists(enemies,uhost)) return; if (lame_check()) { add_enemy(uhost); return; } #endif variable is_ctcp = ctcp_check(0); !if(is_ctcp) { if(strspn(trgt,"#&")) { irc_nick_action(nick,sprintf("chan msg -> %s",trgt)); () = irc_user_save(Rpms[0],'m'); if(andelse {joinbots >= 0} {3 > (unix_time() - joinbots)} {is_prefix(text,sprintf("[%s]", irc_nickname))} ) { irc_send_string(sprintf("PRIVMSG %s :[%s] Hiya.\r\n", Rpms[2], nick)); irc_say(sprintf("[%s] Hiya.\r\n", nick), irc_nickname, Rpms[2]); } } else { %irc_Logf("PRIVMSG from %s to %s", Rpms[0], trgt); irc_nick_action(nick,sprintf("user msg -> %s",trgt)); () = irc_user_save(Rpms[0],'o'); if(andelse {joinbots >= 0} {3 > (unix_time() - joinbots)} {extract_nick(Rpms[2]) == irc_nickname} ) { irc_Inff("Potential joinbot %s?", Rpms[0]); joinbots = -1; } if (beep_on_msg) irc_beep(); } irc_say(text, nick, trgt); } if(int(text) == '!') { if(strspn(trgt,"#&")) { if(is_defined("bot_say")) {nick; trgt; text ;eval("bot_say");} } else { if(is_defined("bot_msg")) {trgt; text; eval("bot_msg");} } } } define SrvA_NOTICE() { variable p, nick, uhost; variable trgt = Rpms[2]; variable text = Rpms[3]; p = nick_chan_check(Rpms[0],trgt,1); % p==0 might be interpreted as an ignore !if (p) return; (nick,uhost) = v_split(Rpms[0],"!"); #ifdef ENEMIES if (assoc_key_exists(enemies,uhost)) return; if (lame_check()) { add_enemy(uhost); return; } #endif () = irc_user_save(Rpms[0],'m'); variable is_ctcp = ctcp_check(1); !if(is_ctcp) { if (strspn(trgt,"#&")) irc_nick_action(nick,sprintf("chan notice -> %s",trgt)); else irc_nick_action(nick,sprintf("user notice -> %s",trgt)); irc_say(text, nick, trgt); } if(joinbots >= 0) { joinbots++; if((unix_time() - joinbots) < 3) { if(is_prefix(text,sprintf("[%s]",irc_nickname))) { irc_send_string(sprintf("PRIVMSG %s :[%s] Hiya.\r\n", trgt, nick)); irc_say(sprintf("[%s] Hiya.\r\n", nick), irc_nickname, trgt); } if(irc_nickname == extract_nick(trgt)) { irc_Inff("Potential joinbot %s? (Notice)", Rpms[0]); joinbots = -1; } } } } define SrvA_QUIT() { variable nick,uhost,tgts; (nick,uhost) = v_split(Rpms[0],"!"); tgts = chans_of_nick(nick); if (tgts != NullString) % here, we use irc_info with target all the chans nick is on irc_info(sprintf("%s has QUIT: %s", nick, Rpms[R_trailing]),tgts); () = irc_user_save(Rpms[0], 'd'); nick_chan_del(nick,"ALL"); } define SrvA_ERROR() { variable nick,uhost; (nick,uhost) = v_split(Rpms[2],"!"); irc_Logf("[%s] ERROR | %s", Rpms[0], Rpms[2]); } define SrvA_PART() { variable nick,chan; chan = Rpms[2]; (nick,) = v_split(Rpms[0],"!"); if (streq_i(nick,irc_nickname)) irc_Logf("You have left %s",chan); else irc_info(sprintf("%s has left %s",nick,chan),chan); () = irc_user_save(Rpms[0],'d'); nick_chan_del(nick,chan); } define SrvA_JOIN() { variable nick,uhost,chan,chans; chan = Rpms[2]; (nick,uhost) = v_split(Rpms[0],"!"); if (nick == irc_nickname) { % it's me if (is_list_element(join_chans,chan,' ')) { join_chans = cut_list_element(join_chans,chan,' '); % cut from pending chans = addto_strl(on_chans,chan," "); if (chans != on_chans) on_chans = chans; irc_set_target(chan); } } #ifdef ENEMIES if (assoc_key_exists(enemies,uhost)) return; #endif irc_info(sprintf("%s (%s) has joined %s", nick, uhost, chan),chan); () = irc_user_save(Rpms[0], 'j'); irc_nick_action(nick,sprintf("JOIN %s",chan)); nick_chan_add(nick,uhost,chan); if(nick == irc_nickname) joinbots = unix_time(); } define SrvA_NICK() { variable nick,uhost,tgts; () = irc_user_nickmod(Rpms[0],Rpms[2]); (nick,uhost) = v_split(Rpms[0],"!"); tgts = chans_of_nick(nick); if (tgts != NullString) #ifdef ENEMIES !if (assoc_key_exists(enemies,uhost)) #endif irc_info(sprintf("%s is now known as %s", nick, Rpms[2]),tgts); nick_chan_mod(nick,uhost,Rpms[2]); } define SrvA_KICK() { variable kicker,victim; (kicker,) = v_split(Rpms[0],"!"); (victim,) = v_split(Rpms[3],"!"); irc_info(sprintf("%s kicked by %s - %s", victim, kicker, Rpms[4]),Rpms[2]); () = irc_user_save(Rpms[3], 'd'); nick_chan_del(victim,Rpms[2]); % now, strangely enough, sometimes kicks don't use same nick/domain variable fvictim = irc_user_find(victim, 'f'); if (int(fvictim)) () = irc_user_save(fvictim, 'd'); } define SrvA_MODE() { variable bywhom,wuhost,modez; (bywhom,wuhost) = v_split(Rpms[0],"!"); modez = strtrim(sprintf("%s %s",Rpms[3],Rpms[4])); irc_info(sprintf("mode/%s [%s] by %s",Rpms[2],modez,bywhom),Rpms[2]); } define SrvA_INVITE() { variable nick; (nick,) = v_split(Rpms[0],"!"); irc_Inff("%s invites you to %s",nick,Rpms[3]); } define SrvA_PING() { irc_send_string(sprintf("PONG %s\r\n", Rpms[2])); if (Rpms[0] != NullString) irc_Logf("Responded to server[%s] ping %s",Rpms[0],Rpms[2]); % normally, there is no prefix above return; } define SrvA_PONG() { variable td; if (s_pinged) { td = unix_time - s_pinged; irc_Inff("%s PONG %dsecs",Rpms[0],td); s_pinged = 0; } return; } define SrvA_TOPIC() { variable bywhom,wuhost,modez; (bywhom,) = v_split(Rpms[0],"!"); irc_info(sprintf("topic on %s set by %s: %s",Rpms[2],bywhom,Rpms[3]),Rpms[2]); } define cat_Rpms() { variable i; for(i = 1; i < Rpms_ct; i++) { " | "; strcat; Rpms[i]; strcat; } } % The return parser. Very weird stuff. % the old command_DEFAULT is now here, avoiding the % return_parse() calls (C) irc_disect_*() calls (S-Lang) command_DEFAULT() define return_parse(buf) { % Split buf into the Rpms[] array, returning count of parms !if (irc_parse_params(buf)) return; % irc_Logf("[%s] (%s) %s...", Rpms[0], Rpms[1], Rpms[2]); irc_update_display(); variable cmnd1 = Rpms[1]; variable par = -1, function; () = perform_Aactions("*"); if (is_uppers(cmnd1)) { par = perform_Aactions(cmnd1); if (par > 0) return; function = "SrvA_" + cmnd1; if(is_defined(function) > 0) { eval(function); par = 0; } }else{ if(andelse {irc_servername == "*"} {is_digits(cmnd1)}) { irc_Inff("SETSERVERNAME[%s] (%s) (%s) (%s) (%s)", Rpms[0], Rpms[1], Rpms[2], Rpms[3], Rpms[4]); irc_set_servername(Rpms[0]); } %irc_Logf("[%s] (%s) %s...", Rpms[0], Rpms[1], Rpms[2]); if(Rpms[0] == irc_servername) { % above restriction is inappropriate for some command responses eg: /who if (is_digits(cmnd1)) { par = perform_Nactions(cmnd1); if (par > 0) return; function = "SrvN_" + cmnd1; variable def = is_defined(function); if(def <= 0) { function = sprintf("SrvN_%sx", substr(Rpms[1], 1, 2)); def = is_defined(function); } if(def > 0) { eval(function); if (Rpms[2] != irc_nickname) irc_Inff("[%s] (%s) (%s) (%s) (%s)", Rpms[0], Rpms[1], Rpms[2], Rpms[3], Rpms[4]); par = 0; } } } } if(par >= 0) return; % if(Rpms[0] == irc_servername) { % if (cmnd1[0] == '4') "ERROR:"; else "Server:"; % } else { sprintf("[%s]", Rpms[0]); % } cat_Rpms(); irc_info(irc_target); return; } % moved this out of slirc.c entirely, and amalgamated with command_DEFAULT define irc_exec_buffer() { !if (strlen(irc_buffer)) return; variable command, params, function, par; history_save_buffer(); if (irc_command_mode) { (command,params) = v_split(chop_1st(irc_buffer)," "); % all but cmd_char } else { if (irc_target == NullString) { irc_log("There is no target set"); return; } command = "PRIVMSG"; params = sprintf("%s %s", irc_target, irc_buffer); } command = strup(command); action_param = params; () = perform_cmd_actions("*"); par = perform_cmd_actions(command); if (par <= 0) { function = "command_" + command; if(is_defined(function)) { params; eval(function); } else if (par < 0) { irc_Inff("[STD-Pack] Unknown command \"%s\", sending anyway.", command); irc_send_string(sprintf("%s %s\r\n", command, params)); } } irc_set_buffer(""); % zeros BufferInsert BufferOffset command_mode; } % BTW, we could be in a pop-up menu here define handle_stdin(trash_fd, trash_which) { variable r, keysym = 0x00; variable status = "Exec"; keysym = irc_get_input(); r = irc_exec_key(keysym); if (r < 0) return; !if (r) { status = " "; std_key(keysym); } irc_set_status(sprintf("%s (%d/%d)", status, irc_edit_insert_pos, strlen(irc_buffer))); } define handle_server(sock,trash_which) { variable buf, n; n = vf_read(sock,&buf); if(n > 0) { server_recv_time = unix_time; % so we can recognize dead connection return_parse(buf); return; } if(n == 0) irc_Info("IRC Server closed connection."); else irc_Info("Error reading from IRC Server."); if(i_quit) close_server(); % no return () = set_action(sock,0,NULL); () = vf_close(sock); } % it is a do_actions() loop in slirc.c, % which actually causes all execution % it also calls the following check_timed() abt each 5 secs... % This will later be replaced by a set_actions()/do_actions() type % scheduler integrated with vfile's scheduler, which will allow % better precision in time-triggered-events define check_timed() { variable td = unix_time - server_recv_time; irc_set_srvtime(td); if (dcc_list.ct + dcc_pending.ct) eval("dcc_expire"); if (chat_list.ct + chat_pending.ct) eval("chat_expire"); if (ftp_list.ct) eval("ftp_expire"); if(td > 180) close_server(); % dead connection if (i_quit) if (unix_time - i_quit > 0) close_server(); if(andelse {td > 120} {s_pinged == 0}) { s_pinged = unix_time; irc_send_string(sprintf("PING %s\r\n", irc_servername)); } } define ConnectToServer(s) { variable d_server,d_port,d_passwd,d_nick; (d_server,d_port,d_passwd,d_nick) = v_split(s,":::"); d_port = integer(d_port); !if (d_port) d_port = 6667; irc_set_nickname(d_nick); irc_Inff("Connecting to %s:%d as %s...", d_server, d_port, d_nick); irc_set_servername("*"); % this only filled in when server responds %irc_set_clientname("*"); s_pinged = 0; server_recv_time = unix_time; irc_server = tcp_open(d_server,d_port); if(irc_server == NULL) { % Oh, dear, we failed. irc_log("Failed to connect to server:"); % irc_log(sprintf("[STD-Pack] Error code %d.", connect_res)); return 0; } server_recv_time = unix_time; variable r = set_rmode(irc_server,'\n',512); if(r) irc_Logf("set_rmode() returned %d",r); irc_set_servername("*"); % this only filled in when server responds () = set_action(irc_server, 0, "handle_server"); irc_set_status("Connected."); if (int(d_passwd)) irc_send_string(sprintf("PASS %s\r\n", d_passwd)); irc_send_string(sprintf("USER %s %s %s :%s\r\n", irc_username, irc_clientname, irc_servername, irc_fullname)); irc_send_string(sprintf("NICK %s\r\n", irc_nickname)); return 1; } define PUhandler_S(key,n,s) { variable p; if (key == 0x0d) { p = s_nth(servers,n); if (irc_servername != "*") command_DISCON("Changing servers"); () = ConnectToServer(p.v); } irc_destroy_popup(); } add_cmnd("server"); define command_SERVER(s) { variable sv,p0,p,items; p0 = servers.f; if (p0 == NULL) return; p = p0; "\n"; do { extract_element(p.v,0,':'); p = p.n; }while (p != p0); items = create_delimited_string(servers.ct); irc_create_popup("SELECT A SERVER", items, "PUhandler_S"); } () = irc_set_keysym('\n', "irc_exec_buffer", 0); () = irc_set_keysym('\r', "irc_exec_buffer", 0); () = set_action(StdIn, 0, "handle_stdin"); () = evalfile("slftp.sl"); () = ConnectToServer(servers.f.v); irc_log("[STD-Pack] Script complete."); irc_update_display();