irc: IRC messages reimplemented

db4
Bruno Deferrari 2009-03-05 23:11:46 -02:00
parent b5352033cb
commit 1c70bf833f
12 changed files with 262 additions and 232 deletions

View File

@ -1,4 +1,4 @@
USING: help.markup help.syntax quotations kernel irc.messages ;
USING: help.markup help.syntax quotations kernel irc.messages irc.messages.base irc.messages.parser ;
IN: irc.client
HELP: irc-client "IRC Client object" ;
@ -56,15 +56,15 @@ ARTICLE: "irc.client" "IRC Client"
"Some of the RFC defined irc messages as objects:"
{ $table
{ { $link irc-message } "base of all irc messages" }
{ { $link logged-in } "logged in to server" }
{ { $link rpl-welcome } "logged in to server" }
{ { $link ping } "ping message" }
{ { $link join } "channel join" }
{ { $link part } "channel part" }
{ { $link quit } "quit from irc" }
{ { $link privmsg } "private message (to client or channel)" }
{ { $link kick } "kick from channel" }
{ { $link roomlist } "list of participants in channel" }
{ { $link nick-in-use } "chosen nick is in use by another client" }
{ { $link rpl-names } "list of participants in channel" }
{ { $link rpl-nickname-in-use } "chosen nick is in use by another client" }
{ { $link notice } "notice message" }
{ { $link mode } "mode change" }
{ { $link unhandled } "uninmplemented/unhandled message" }

View File

@ -1,7 +1,7 @@
USING: kernel tools.test accessors arrays sequences
io io.streams.duplex namespaces threads destructors
calendar irc.client.private irc.client irc.messages.private
concurrency.mailboxes classes assocs combinators ;
calendar irc.client.private irc.client irc.messages
concurrency.mailboxes classes assocs combinators irc.messages.parser ;
EXCLUDE: irc.messages => join ;
RENAME: join irc.messages => join_
IN: irc.client.tests
@ -49,13 +49,13 @@ M: mb-writer dispose drop ;
{ "factorbot" } [ irc> nick>> ] unit-test
{ "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
! { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
{ "#factortest" } [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
parse-irc-line forward-name ] unit-test
string>irc-message forward-name ] unit-test
{ "someuser" } [ ":someuser!n=user@some.where PRIVMSG factorbot :hi"
parse-irc-line forward-name ] unit-test
string>irc-message forward-name ] unit-test
] with-irc
! Test login and nickname set
@ -102,7 +102,7 @@ M: mb-writer dispose drop ;
"#factortest" <irc-channel-chat> [ %add-named-chat ] keep
":somebody!n=somebody@some.where PRIVMSG #factortest :hello" %push-line
[ privmsg? ] read-matching-message
[ class ] [ name>> ] [ trailing>> ] tri
[ class ] [ target>> ] [ trailing>> ] tri
] unit-test
] with-irc
@ -110,7 +110,7 @@ M: mb-writer dispose drop ;
"ircuser" <irc-nick-chat> [ %add-named-chat ] keep
":ircuser!n=user@isp.net PRIVMSG factorbot :hello" %push-line
[ privmsg? ] read-matching-message
[ class ] [ name>> ] [ trailing>> ] tri
[ class ] [ target>> ] [ trailing>> ] tri
] unit-test
] with-irc

View File

@ -3,7 +3,7 @@
USING: concurrency.mailboxes kernel io.sockets io.encodings.8-bit calendar
accessors destructors namespaces io assocs arrays fry
continuations threads strings classes combinators splitting hashtables
ascii irc.messages ;
ascii irc.messages irc.messages.base irc.messages.parser call ;
RENAME: join sequences => sjoin
EXCLUDE: sequences => join ;
IN: irc.client
@ -74,12 +74,12 @@ SINGLETON: irc-disconnected ! sent when connection is lost
SINGLETON: irc-connected ! sent when connection is established
: terminate-irc ( irc-client -- )
[ is-running>> ] keep and [
dup is-running>> [
f >>is-running
[ stream>> dispose ] keep
[ in-messages>> ] [ out-messages>> ] bi 2array
[ irc-end swap mailbox-put ] each
] when* ;
] [ drop ] if ;
<PRIVATE
@ -120,7 +120,7 @@ M: irc-chat to-chat in-messages>> mailbox-put ;
: chats-with-participant ( nick -- seq )
irc> chats>> values
[ [ irc-channel-chat? ] keep and [ participants>> key? ] [ drop f ] if* ]
[ dup irc-channel-chat? [ participants>> key? ] [ 2drop f ] if ]
with filter ;
: to-chats-with-participant ( message nickname -- )
@ -165,11 +165,10 @@ M: irc-chat to-chat in-messages>> mailbox-put ;
" hostname servername :irc.factor" irc-print ;
: /CONNECT ( server port -- stream )
irc> connect>> call drop ; inline
irc> connect>> call( host port -- stream local ) drop ;
: /JOIN ( channel password -- )
"JOIN " irc-write
[ [ " :" ] dip 3append ] when* irc-print ;
"JOIN " irc-write [ " :" swap 3append ] when* irc-print ;
: /PONG ( text -- )
"PONG " irc-write irc-print ;
@ -187,7 +186,7 @@ M: join forward-name trailing>> ;
M: part forward-name channel>> ;
M: kick forward-name channel>> ;
M: mode forward-name name>> ;
M: privmsg forward-name dup name>> me? [ irc-message-sender ] [ name>> ] if ;
M: privmsg forward-name dup target>> me? [ sender>> ] [ target>> ] if ;
UNION: single-forward join part kick mode privmsg ;
UNION: multiple-forward nick quit ;
@ -200,48 +199,48 @@ M: irc-message forward-message
M: single-forward forward-message dup forward-name to-chat ;
M: multiple-forward forward-message
dup irc-message-sender to-chats-with-participant ;
dup sender>> to-chats-with-participant ;
M: broadcast-forward forward-message
irc> chats>> values [ to-chat ] with each ;
GENERIC: process-message ( irc-message -- )
M: object process-message drop ;
M: logged-in process-message
name>> t irc> [ (>>is-ready) ] [ (>>nick) ] [ chats>> ] tri
M: rpl-welcome process-message
nickname>> t irc> [ (>>is-ready) ] [ (>>nick) ] [ chats>> ] tri
values [ initialize-chat ] each ;
M: ping process-message trailing>> /PONG ;
M: nick-in-use process-message name>> "_" append /NICK ;
M: rpl-nickname-in-use process-message name>> "_" append /NICK ;
M: join process-message
[ drop +normal+ ] [ irc-message-sender ] [ trailing>> ] tri
[ drop +normal+ ] [ sender>> ] [ trailing>> ] tri
dup chat> [ add-participant ] [ 3drop ] if ;
M: part process-message
[ irc-message-sender ] [ channel>> ] bi remove-participant ;
[ sender>> ] [ channel>> ] bi remove-participant ;
M: kick process-message
[ [ who>> ] [ channel>> ] bi remove-participant ]
[ dup who>> me? [ unregister-chat ] [ drop ] if ]
[ [ user>> ] [ channel>> ] bi remove-participant ]
[ dup user>> me? [ unregister-chat ] [ drop ] if ]
bi ;
M: quit process-message
irc-message-sender remove-participant-from-all ;
sender>> remove-participant-from-all ;
M: nick process-message
[ irc-message-sender ] [ trailing>> ] bi rename-participant-in-all ;
[ sender>> ] [ trailing>> ] bi rename-participant-in-all ;
M: mode process-message ( mode -- )
[ channel-mode? ] keep and [
dup channel-mode? [
[ name>> ] [ mode>> ] [ parameter>> ] tri
[ change-participant-mode ] [ 2drop ] if*
] when* ;
] [ drop ] if ;
: >nick/mode ( string -- nick mode )
dup first "+@" member? [ unclip ] [ 0 ] if participant-mode ;
: names-reply>participants ( names-reply -- participants )
trailing>> [ blank? ] trim " " split
nicks>> [ blank? ] trim " " split
[ >nick/mode 2array ] map >hashtable ;
: maybe-clean-participants ( channel-chat -- )
@ -249,14 +248,14 @@ M: mode process-message ( mode -- )
H{ } clone >>participants f >>clean-participants
] when drop ;
M: names-reply process-message
M: rpl-names process-message
[ names-reply>participants ] [ channel>> chat> ] bi [
[ maybe-clean-participants ]
[ participants>> 2array assoc-combine ]
[ (>>participants) ] tri
] [ drop ] if* ;
M: end-of-names process-message
M: rpl-names-end process-message
channel>> chat> [
t >>clean-participants
[ f f f <participant-changed> ] dip name>> to-chat
@ -268,7 +267,7 @@ M: end-of-names process-message
GENERIC: handle-outgoing-irc ( irc-message -- ? )
M: irc-end handle-outgoing-irc drop f ;
M: irc-message handle-outgoing-irc irc-message>client-line irc-print t ;
M: irc-message handle-outgoing-irc irc-message>string irc-print t ;
! ======================================
! Reader/Writer
@ -293,9 +292,9 @@ DEFER: (connect-irc)
: (reader-loop) ( -- ? )
irc> stream>> [
|dispose stream-readln [
parse-irc-line handle-reader-message t
string>irc-message handle-reader-message t
] [
handle-disconnect
f handle-disconnect
] if*
] with-destructors ;
@ -314,7 +313,7 @@ DEFER: (connect-irc)
[ forward-message ] [ process-message ] [ irc-end? not ] tri ;
: strings>privmsg ( name string -- privmsg )
privmsg new [ (>>trailing) ] keep [ (>>name) ] keep ;
privmsg new [ (>>trailing) ] keep [ (>>target) ] keep ;
: maybe-annotate-with-name ( name obj -- obj )
{ { [ dup string? ] [ strings>privmsg ] }
@ -325,7 +324,7 @@ DEFER: (connect-irc)
GENERIC: annotate-message ( chat object -- object )
M: object annotate-message nip ;
M: part annotate-message swap name>> >>channel ;
M: privmsg annotate-message swap name>> >>name ;
M: privmsg annotate-message swap name>> >>target ;
M: string annotate-message [ name>> ] dip strings>privmsg ;
: spawn-irc ( -- )
@ -335,7 +334,7 @@ M: string annotate-message [ name>> ] dip strings>privmsg ;
3drop ;
GENERIC: (attach-chat) ( irc-chat -- )
USE: prettyprint
M: irc-chat (attach-chat)
[ [ irc> >>client ] [ name>> ] bi irc> chats>> set-at ]
[ [ irc> is-ready>> ] dip and [ initialize-chat ] when* ]

View File

@ -0,0 +1 @@
Bruno Deferrari

View File

@ -0,0 +1,115 @@
! Copyright (C) 2009 Bruno Deferrari
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs classes.parser classes.tuple
combinators fry generic.parser kernel lexer
mirrors namespaces parser sequences splitting strings words ;
IN: irc.messages.base
TUPLE: irc-message line prefix command parameters trailing timestamp sender ;
TUPLE: unhandled < irc-message ;
SYMBOL: string-irc-type-mapping
string-irc-type-mapping [ H{ } clone ] initialize
: register-irc-message-type ( type string -- )
string-irc-type-mapping get set-at ;
: irc>type ( string -- irc-message-class )
string-irc-type-mapping get at unhandled or ;
GENERIC: irc-trailing-slot ( irc-message -- string/f )
M: irc-message irc-trailing-slot
drop f ;
GENERIC: irc-parameter-slots ( irc-message -- seq )
M: irc-message irc-parameter-slots
drop f ;
GENERIC: process-irc-trailing ( irc-message -- )
M: irc-message process-irc-trailing
dup irc-trailing-slot [
swap [ trailing>> swap ] [ <mirror> ] bi set-at
] [ drop ] if* ;
GENERIC: process-irc-prefix ( irc-message -- )
M: irc-message process-irc-prefix
drop ;
<PRIVATE
: [slot-setter] ( mirror -- quot )
'[ [ _ set-at ] [ drop ] if* ] ; inline
PRIVATE>
GENERIC: process-irc-parameters ( irc-message -- )
M: irc-message process-irc-parameters
dup irc-parameter-slots [
swap [ parameters>> swap ] [ <mirror> [slot-setter] ] bi 2each
] [ drop ] if* ;
GENERIC: post-process-irc-message ( irc-message -- )
M: irc-message post-process-irc-message drop ;
GENERIC: fill-irc-message-slots ( irc-message -- )
M: irc-message fill-irc-message-slots
{
[ process-irc-trailing ]
[ process-irc-prefix ]
[ process-irc-parameters ]
[ post-process-irc-message ]
} cleave ;
GENERIC: irc-command-string ( irc-message -- string )
M: irc-message irc-command-string drop f ;
! FIXME: inverse of post-process is missing
GENERIC: set-irc-parameters ( irc-message -- )
M: irc-message set-irc-parameters
dup irc-parameter-slots
[ over <mirror> '[ _ at ] map >>parameters ] when* drop ;
GENERIC: set-irc-trailing ( irc-message -- )
M: irc-message set-irc-trailing
dup irc-trailing-slot [ over <mirror> at >>trailing ] when* drop ;
GENERIC: set-irc-command ( irc-message -- )
M: irc-message set-irc-command
[ irc-command-string ] [ (>>command) ] bi ;
: irc-message>string ( irc-message -- string )
{
[ prefix>> ]
[ command>> ]
[ parameters>> " " join ]
[ trailing>> dup [ CHAR: : prefix ] when ]
} cleave 4array sift " " join ;
<PRIVATE
: ?define-irc-parameters ( class slot-names -- )
dup empty? not [
[ \ irc-parameter-slots create-method-in ] dip
[ [ "_" = not ] keep and ] map '[ drop _ ] define
] [ 2drop ] if ;
: ?define-irc-trailing ( class slot-name -- )
[
[ \ irc-trailing-slot create-method-in ] dip
first '[ drop _ ] define
] [ drop ] if* ;
: define-irc-class ( class params -- )
[ { ":" "_" } member? not ] filter
[ irc-message ] dip define-tuple-class ;
: define-irc-parameter-slots ( class params -- )
{ ":" } split1 [ over ] dip
[ ?define-irc-parameters ] [ ?define-irc-trailing ] 2bi* ;
PRIVATE>
#! SYNTAX:
#! IRC: type "COMMAND" slot1 ...;
#! IRC: type "COMMAND" slot1 ... : trailing-slot;
: IRC: ( name string parameters -- )
CREATE-CLASS
[ scan-object register-irc-message-type ] keep
";" parse-tokens
[ define-irc-class ] [ define-irc-parameter-slots ] 2bi ; parsing

View File

@ -0,0 +1 @@
IRC messages base implementation

View File

@ -1,19 +1,10 @@
USING: kernel tools.test accessors arrays
irc.messages irc.messages.private ;
irc.messages.parser irc.messages ;
EXCLUDE: sequences => join ;
IN: irc.messages.tests
{ "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
{ T{ irc-message
{ line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
{ prefix "someuser!n=user@some.where" }
{ command "PRIVMSG" }
{ parameters { "#factortest" } }
{ trailing "hi" } } }
[ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
string>irc-message f >>timestamp ] unit-test
! { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
{ T{ privmsg
{ line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
@ -21,9 +12,10 @@ IN: irc.messages.tests
{ command "PRIVMSG" }
{ parameters { "#factortest" } }
{ trailing "hi" }
{ name "#factortest" } } }
{ target "#factortest" }
{ text "hi" } } }
[ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test
{ T{ join
{ line ":someuser!n=user@some.where JOIN :#factortest" }
@ -32,7 +24,7 @@ IN: irc.messages.tests
{ parameters { } }
{ trailing "#factortest" } } }
[ ":someuser!n=user@some.where JOIN :#factortest"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test
{ T{ mode
{ line ":ircserver.net MODE #factortest +ns" }
@ -42,7 +34,7 @@ IN: irc.messages.tests
{ name "#factortest" }
{ mode "+ns" } } }
[ ":ircserver.net MODE #factortest +ns"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test
{ T{ mode
{ line ":ircserver.net MODE #factortest +o someuser" }
@ -53,7 +45,7 @@ IN: irc.messages.tests
{ mode "+o" }
{ parameter "someuser" } } }
[ ":ircserver.net MODE #factortest +o someuser"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test
{ T{ nick
{ line ":someuser!n=user@some.where NICK :someuser2" }
@ -62,9 +54,9 @@ IN: irc.messages.tests
{ parameters { } }
{ trailing "someuser2" } } }
[ ":someuser!n=user@some.where NICK :someuser2"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test
{ T{ nick-in-use
{ T{ rpl-nickname-in-use
{ line ":ircserver.net 433 * nickname :Nickname is already in use" }
{ prefix "ircserver.net" }
{ command "433" }
@ -72,4 +64,4 @@ IN: irc.messages.tests
{ name "nickname" }
{ trailing "Nickname is already in use" } } }
[ ":ircserver.net 433 * nickname :Nickname is already in use"
parse-irc-line f >>timestamp ] unit-test
string>irc-message f >>timestamp ] unit-test

View File

@ -1,179 +1,63 @@
! Copyright (C) 2008 Bruno Deferrari
! See http://factorcode.org/license.txt for BSD license.
USING: kernel fry splitting ascii calendar accessors combinators
arrays classes.tuple math.order ;
RENAME: join sequences => sjoin
arrays classes.tuple math.order words assocs strings
irc.messages.base ;
EXCLUDE: sequences => join ;
IN: irc.messages
TUPLE: irc-message line prefix command parameters trailing timestamp ;
TUPLE: logged-in < irc-message name ;
TUPLE: ping < irc-message ;
TUPLE: join < irc-message ;
TUPLE: part < irc-message channel ;
TUPLE: quit < irc-message ;
TUPLE: nick < irc-message ;
TUPLE: privmsg < irc-message name ;
TUPLE: kick < irc-message channel who ;
TUPLE: roomlist < irc-message channel names ;
TUPLE: nick-in-use < irc-message name ;
TUPLE: notice < irc-message type ;
TUPLE: mode < irc-message name mode parameter ;
TUPLE: names-reply < irc-message who channel ;
TUPLE: end-of-names < irc-message who channel ;
TUPLE: unhandled < irc-message ;
: <irc-client-message> ( command parameters trailing -- irc-message )
irc-message new
now >>timestamp
swap >>trailing
swap >>parameters
swap >>command ;
<PRIVATE
GENERIC: command-string>> ( irc-message -- string )
M: irc-message command-string>> ( irc-message -- string ) command>> ;
M: ping command-string>> ( ping -- string ) drop "PING" ;
M: join command-string>> ( join -- string ) drop "JOIN" ;
M: part command-string>> ( part -- string ) drop "PART" ;
M: quit command-string>> ( quit -- string ) drop "QUIT" ;
M: nick command-string>> ( nick -- string ) drop "NICK" ;
M: privmsg command-string>> ( privmsg -- string ) drop "PRIVMSG" ;
M: notice command-string>> ( notice -- string ) drop "NOTICE" ;
M: mode command-string>> ( mode -- string ) drop "MODE" ;
M: kick command-string>> ( kick -- string ) drop "KICK" ;
GENERIC: command-parameters>> ( irc-message -- seq )
M: irc-message command-parameters>> ( irc-message -- seq ) parameters>> ;
M: ping command-parameters>> ( ping -- seq ) drop { } ;
M: join command-parameters>> ( join -- seq ) drop { } ;
M: part command-parameters>> ( part -- seq ) channel>> 1array ;
M: quit command-parameters>> ( quit -- seq ) drop { } ;
M: nick command-parameters>> ( nick -- seq ) drop { } ;
M: privmsg command-parameters>> ( privmsg -- seq ) name>> 1array ;
M: notice command-parameters>> ( norice -- seq ) type>> 1array ;
M: kick command-parameters>> ( kick -- seq )
[ channel>> ] [ who>> ] bi 2array ;
M: mode command-parameters>> ( mode -- seq )
[ name>> ] [ channel>> ] [ mode>> ] tri 3array ;
GENERIC# >>command-parameters 1 ( irc-message params -- irc-message )
M: irc-message >>command-parameters ( irc-message params -- irc-message )
drop ;
M: logged-in >>command-parameters ( part params -- part )
first >>name ;
M: privmsg >>command-parameters ( privmsg params -- privmsg )
first >>name ;
M: notice >>command-parameters ( notice params -- notice )
first >>type ;
M: part >>command-parameters ( part params -- part )
first >>channel ;
M: kick >>command-parameters ( kick params -- kick )
first2 [ >>channel ] [ >>who ] bi* ;
M: nick-in-use >>command-parameters ( nick-in-use params -- nick-in-use )
second >>name ;
M: names-reply >>command-parameters ( names-reply params -- names-reply )
first3 nip [ >>who ] [ >>channel ] bi* ;
M: end-of-names >>command-parameters ( names-reply params -- names-reply )
first2 [ >>who ] [ >>channel ] bi* ;
M: mode >>command-parameters ( mode params -- mode )
dup length {
{ 3 [ first3 [ >>name ] [ >>mode ] [ >>parameter ] tri* ] }
{ 2 [ first2 [ >>name ] [ >>mode ] bi* ] }
[ drop first >>name dup trailing>> >>mode ]
} case ;
PRIVATE>
GENERIC: irc-message>client-line ( irc-message -- string )
M: irc-message irc-message>client-line ( irc-message -- string )
[ command-string>> ]
[ command-parameters>> " " sjoin ]
[ trailing>> [ CHAR: : prefix ] [ "" ] if* ]
tri 3array " " sjoin ;
GENERIC: irc-message>server-line ( irc-message -- string )
M: irc-message irc-message>server-line ( irc-message -- string )
drop "not implemented yet" ;
<PRIVATE
! ======================================
! Message parsing
! ======================================
: split-at-first ( seq separators -- before after )
dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
: remove-heading-: ( seq -- seq )
":" ?head drop ;
: parse-name ( string -- string )
remove-heading-: "!" split-at-first drop ;
: split-prefix ( string -- string/f string )
dup ":" head?
[ remove-heading-: " " split1 ] [ f swap ] if ;
: split-trailing ( string -- string string/f )
":" split1 ;
: copy-message-in ( command irc-message -- command )
{
[ line>> >>line ]
[ prefix>> >>prefix ]
[ command>> >>command ]
[ trailing>> >>trailing ]
[ timestamp>> >>timestamp ]
[ parameters>> [ >>parameters ] [ >>command-parameters ] bi ]
} cleave ;
PRIVATE>
UNION: sender-in-prefix privmsg join part quit kick mode nick ;
GENERIC: irc-message-sender ( irc-message -- sender )
M: sender-in-prefix irc-message-sender ( sender-in-prefix -- sender )
prefix>> parse-name ;
: string>irc-message ( string -- object )
dup split-prefix split-trailing
[ [ blank? ] trim " " split unclip swap ] dip
now irc-message boa ;
: irc-message>command ( irc-message -- command )
[
command>> {
{ "PING" [ ping ] }
{ "NOTICE" [ notice ] }
{ "001" [ logged-in ] }
{ "433" [ nick-in-use ] }
{ "353" [ names-reply ] }
{ "366" [ end-of-names ] }
{ "JOIN" [ join ] }
{ "PART" [ part ] }
{ "NICK" [ nick ] }
{ "PRIVMSG" [ privmsg ] }
{ "QUIT" [ quit ] }
{ "MODE" [ mode ] }
{ "KICK" [ kick ] }
[ drop unhandled ]
} case new
] keep copy-message-in ;
: parse-irc-line ( string -- message )
string>irc-message irc-message>command ;
! connection
IRC: pass "PASS" password ;
IRC: nick "NICK" nickname ;
IRC: user "USER" user mode _ : realname ;
IRC: oper "OPER" name password ;
IRC: mode "MODE" name mode parameter ;
IRC: service "SERVICE" nickname _ distribution type _ : info ;
IRC: quit "QUIT" : comment ;
IRC: squit "SQUIT" server : comment ;
! channel operations
IRC: join "JOIN" channel ;
IRC: part "PART" channel : comment ;
IRC: topic "TOPIC" channel : topic ;
IRC: names "NAMES" channel ;
IRC: list "LIST" channel ;
IRC: invite "INVITE" nickname channel ;
IRC: kick "KICK" channel user : comment ;
! chating
IRC: privmsg "PRIVMSG" target : text ;
IRC: notice "NOTICE" target : text ;
! server queries
IRC: motd "MOTD" target ;
IRC: lusers "LUSERS" mask target ;
IRC: version "VERSION" target ;
IRC: stats "STATS" query target ;
IRC: links "LINKS" server mask ;
IRC: time "TIME" target ;
IRC: connect "CONNECT" server port remote-server ;
IRC: trace "TRACE" target ;
IRC: admin "ADMIN" target ;
IRC: info "INFO" target ;
! service queries
IRC: servlist "SERVLIST" mask type ;
IRC: squery "SQUERY" service-name : text ;
! user queries
IRC: who "WHO" mask operator ;
IRC: whois "WHOIS" target mask ;
IRC: whowas "WHOWAS" nickname count target ;
! misc
IRC: kill "KILL" nickname : comment ;
IRC: ping "PING" server1 server2 ;
IRC: pong "PONG" server1 server2 ;
IRC: error "ERROR" : message ;
! numeric replies
IRC: rpl-welcome "001" nickname : comment ;
IRC: rpl-whois-user "311" nicnamek user host _ : real-name ;
IRC: rpl-channel-modes "324" channel mode params ;
IRC: rpl-notopic "331" channel : topic ;
IRC: rpl-topic "332" channel : topic ;
IRC: rpl-inviting "341" channel nickname ;
IRC: rpl-names "353" nickname _ channel : nicks ;
IRC: rpl-names-end "366" nickname channel : comment ;
! error replies
IRC: rpl-nickname-in-use "433" _ name ;
IRC: rpl-nick-collision "436" nickname : comment ;

View File

@ -0,0 +1 @@
Bruno Deferrari

View File

@ -0,0 +1,35 @@
! Copyright (C) 2009 Bruno Deferrari
! See http://factorcode.org/license.txt for BSD license.
USING: kernel fry splitting ascii calendar accessors combinators
arrays classes.tuple math.order words assocs
irc.messages.base sequences ;
IN: irc.messages.parser
<PRIVATE
: split-at-first ( seq separators -- before after )
dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
: split-trailing ( string -- string string/f ) ":" split1 ;
: remove-heading-: ( seq -- seq ) ":" ?head drop ;
: split-prefix ( string -- string/f string )
dup ":" head? [
remove-heading-: " " split1
] [ f swap ] if ;
: split-message ( string -- prefix command parameters trailing )
split-prefix split-trailing
[ [ blank? ] trim " " split unclip swap ] dip ;
: sender ( irc-message -- sender )
prefix>> [ remove-heading-: "!" split-at-first drop ] [ f ] if* ;
PRIVATE>
: string>irc-message ( string -- irc-message )
dup split-message
[ [ irc>type new ] [ >>command ] bi ]
[ >>parameters ]
[ >>trailing ]
tri*
[ (>>prefix) ] [ fill-irc-message-slots ] [ swap >>line ] tri
now >>timestamp dup sender >>sender ;

View File

@ -0,0 +1 @@
Basic parser for irc messages

View File

@ -0,0 +1 @@
IRC message definitions