diff --git a/lib/modules/Protocols.pmod/IRC.pmod/Client.pike b/lib/modules/Protocols.pmod/IRC.pmod/Client.pike index 933667744e75c8fcdfb5883ca22709ab7516f07b..635e26efd6489bde5947c5842ce23331874cfef9 100644 --- a/lib/modules/Protocols.pmod/IRC.pmod/Client.pike +++ b/lib/modules/Protocols.pmod/IRC.pmod/Client.pike @@ -2,7 +2,7 @@ import "."; -object raw; +Raw raw; string pass=MIME.encode_base64(Crypto.randomness.reasonably_random()->read(6)); mapping options; @@ -52,12 +52,19 @@ void create(string _server,void|mapping _options) call_out(da_ping,options->ping_interval || 60); } +void close() +{ + if (raw->con) raw->con->close(); + destruct(raw); + raw=0; +} + string expecting_pong; void da_ping() { - call_out(da_ping,options->ping_interval || 60); - call_out(no_ping_reply,options->ping_timeout || 60); // timeout + call_out(da_ping,options->ping_interval || 120); + call_out(no_ping_reply,options->ping_timeout || 120); // timeout cmd->ping(expecting_pong= options->host+" "+Array.shuffle("pike""IRC""client"/"")*""); } @@ -97,12 +104,12 @@ void got_command(string what,string ... args) options->error_notify(@args); return; } - werror("got command: %O, %O\n",what,args); +// werror("got command: %O, %O\n",what,args); } void got_notify(string from,string type, void|string to,void|string message, - void|string extra,void|string extra2) + string ...extra) { object c; if (options->system_notify && glob("2??",type)) @@ -138,19 +145,61 @@ void got_notify(string from,string type, break; case "353": // names list - if (extra && (c=channels[lower_case(extra||"")])) + if (sizeof(extra) && (c=channels[lower_case(extra[0]||"")]) && + c->not_names) { - c->not_names(map(extra2/" "-({""}), + c->not_names(map(extra[1]/" "-({""}), lambda(string name) { string a,b,c; - sscanf(name,"%[@]%s%[+]", + sscanf(name,"%[+@%]%s%[+@%]", a,b,c); - return ({person(b),a+c}); + Person p=person(b); + p->channels[lower_case(extra[0])]=1; + return ({p,a+c}); })); return; } break; + case "366": // "end of names list" + break; + + case "352": // who list + if (sizeof(extra)>2 && + message && (c=channels[lower_case(message||"")])) + { + Person p=person(extra[3],extra[0]+"@"+extra[1]); + p->server=extra[2]; + p->realname=extra[6..]*" "; + p->channels[lower_case(message)]=1; + if (c->not_who) c->not_who(p,extra[4]); + return; + } + break; + case "315": // "end of who list" + break; + + case "482": // "you're not channel operator" + if ((c=channels[lower_case(message||"")])) + { + if (c->not_not_oper) c->not_not_oper(); + return; + } + break; + + + case "401": // no such nick + werror("%O\n",({from,type,to,message,extra})); + break; + + case "367": // mode b line + if ((c=channels[lower_case(message||"")])) + { + if (c->not_mode_b) c->not_mode_b(to,extra*" "); + return; + } + break; + /* --- */ @@ -166,12 +215,13 @@ void got_notify(string from,string type, if ((c=channels[lower_case(to||"")])) { // who, mode, by - c->not_mode(extra?person(extra):originator,message,originator); + c->not_mode(extra[0]?person(extra[0]):originator,message+( ({""})+extra)*" ",originator); return; } break; case "JOIN": +// werror("me=%O\n",me); if ((c=channels[lower_case(to||"")])) { c->not_join(originator); @@ -180,6 +230,7 @@ void got_notify(string from,string type, break; case "PART": + originator->channels[lower_case(to)]=0; if ((c=channels[lower_case(to||"")])) { // who, why, by @@ -189,10 +240,11 @@ void got_notify(string from,string type, break; case "KICK": + person(message)->channels[lower_case(extra[0])]=0; if ((c=channels[lower_case(to||"")])) { // who, why, by - c->not_part(person(message),extra,originator); + c->not_part(person(message),extra[0],originator); return; } break; @@ -219,16 +271,27 @@ void got_notify(string from,string type, options->privmsg_notify(originator,message,to); return; + case "NOTICE": + if ((c=channels[lower_case(to||"")])) + { + c->not_message(originator,message); + return; + } + if (!options->notice_notify) break; + options->notice_notify(originator,message,to); + return; + case "NICK": -// werror("%s is known as %s (aka %s)\n", -// originator->nick, -// to, -// ((array)originator->aka)*","); + werror("%s is known as %s (aka %s)\n", + originator->nick, + to, + ((array)originator->aka)*","); mixed err=0; originator->aka[originator->nick]=1; originator->aka[to]=1; if (options->nick_notify) err=catch { options->nick_notify(originator,to); }; + m_delete(nick2person,originator->nick); originator->nick=to; nick2person[to]=originator; if (err) throw(err); @@ -236,7 +299,7 @@ void got_notify(string from,string type, } // werror("got notify: %O, %O, %O, %O\n",from,type,to,message); if (options->generic_notify) - options->generic_notify(from,type,to,message,extra); + options->generic_notify(from,type,to,message,extra[0]); } object cmd=class @@ -334,58 +397,63 @@ void send_message(string|array to,string msg) cmd->privmsg( (arrayp(to)?to*",":to), msg); } -// ----- channel - -class Channel -{ - string name; - - void not_message(string who,string message); - void not_join(string who); - void not_part(string who,string message,string executor); - void not_mode(string who,string mode); - void not_failed_to_join(); -} - // ----- persons class Person { - string nick; // Mirar - string user; // mirar - string ip; // mistel.idonex.se - int last_action; // time_t - multiset aka=(<>); + inherit .Person; void say(string message) { cmd->privmsg(nick,message); } - void me(string what) + void notice(string message) + { + cmd->notice(nick,message); + } + + void action(string what) { say("\1ACTION "+what+"\1"); } + + string _sprintf(int t) + { + switch (t) + { + case 'O': + return sprintf("Person(%s!%s@%s%s)", + nick,user||"?",ip||"?", + (realname!="?")?"("+realname+")":""); + default: + return 0; + } + } } mapping nick2person=([]); -object me; +Person me; Person person(string who,void|string ip) { Person p; - if ( ! (p=nick2person[who]) ) + if ( ! (p=nick2person[lower_case(who)]) ) { p=Person(); p->nick=who; - nick2person[who]=p; + nick2person[lower_case(who)]=p; +// werror("new person: %O\n",p); + } + else if (lower_case(p->nick)!=lower_case(who)) + { + werror("nick mismatch: %O was %O\n",who,p->nick); + p->nick=who; } if (ip && !p->ip) sscanf(ip,"%*[~]%s@%s",p->user,p->ip); -// werror("%O is %O %O %O\n",who,p->nick,p->user,p->ip); - return p; } diff --git a/lib/modules/Protocols.pmod/IRC.pmod/Raw.pike b/lib/modules/Protocols.pmod/IRC.pmod/Raw.pike index 53e2245df96b4dabc411d3bccf9e9e43cd2d3e1e..e8df9820ebd39fffb5d67777b241bad2c4a90e45 100644 --- a/lib/modules/Protocols.pmod/IRC.pmod/Raw.pike +++ b/lib/modules/Protocols.pmod/IRC.pmod/Raw.pike @@ -4,7 +4,7 @@ import "."; object con; -// #define IRC_DEBUG +// #define IRC_DEBUG function(string,string ...:void) command_callback; function(string,string ...:void) notify_callback; @@ -101,6 +101,13 @@ void con_write(string s) write_buf+=({s}); return; } + if (!con) + { +#ifdef IRC_DEBUG + werror("<- (write error; con lost)\n"); +#endif + return; + } int j=con->write(s); if (j!=sizeof(s)) { diff --git a/lib/modules/Protocols.pmod/IRC.pmod/Requests.pmod b/lib/modules/Protocols.pmod/IRC.pmod/Requests.pmod index d4b08b5945abf04d286dfee06fce38a5135b1808..7ffddd7c8d9586fa5c88d94d05179f96b9f6e927 100644 --- a/lib/modules/Protocols.pmod/IRC.pmod/Requests.pmod +++ b/lib/modules/Protocols.pmod/IRC.pmod/Requests.pmod @@ -6,7 +6,7 @@ NICK Mirar^ USER mirar mistel.idonex.se irc.starchat.net :Mirar is testing */ -string __cvs_id="$Id: Requests.pmod,v 1.3 2000/09/28 03:39:01 hubbe Exp $"; +string __cvs_id="$Id: Requests.pmod,v 1.4 2000/11/12 23:41:50 mirar Exp $"; import "."; @@ -17,12 +17,14 @@ class Request void async(object con,mixed ...args) { - con->transmit_async(cmd,encode(args),got_answer); + con->transmit_noreply(cmd,encode(args)); + if (callback) call_out(callback,0,1); } - mixed sync(object con,mixed ...args) - { - return decode_answer(con->transmit(cmd,encode(args))); + int(1..1) sync(object con,mixed ...args) + { + con->transmit_noreply(cmd,encode(args)); + return 1; } void got_answer(mixed s) @@ -47,18 +49,6 @@ inherit Protocols.IRC.Requests.Request; string cmd=\"%cmd%\"; -void async(object con,mixed ...args) -{ - con->transmit_noreply(cmd,encode(args)); - if (callback) call_out(callback,0,1); -} - -int(1..1) sync(object con,mixed ...args) -{ - con->transmit_noreply(cmd,encode(args)); - return 1; -} - string encode(array args) { %encode% @@ -110,6 +100,34 @@ object user=NoReply("USER","string","string","string","text"); object pong=NoReply("PONG","text"); object ping=NoReply("PING","text"); object privmsg=NoReply("PRIVMSG","string","text"); +object notice=NoReply("NOTICE","string","text"); object join=NoReply("JOIN","string"); object names=NoReply("NAMES","string"); +object who=NoReply("WHO","string"); +object kick=NoReply("KICK","string","string","text"); + +class mode +{ + inherit Request; + + string cmd="MODE"; + + string encode(array args) + { + switch (sizeof(args)) + { + case 2: + return sprintf("%s %s",@args); + case 3: + return sprintf("%s %s :%s",@args); + default: + error("illegal number of args to MODE"); + } + } + + mixed decode_answer(string s) + { + return 1; + } +};