dot

packages and services management
Log | Files | Refs | README

commit 1917c93fb033b611071e865daf57678065bd3c58
parent d91423f98a9bcb922504695a8d442be9d2edcd00
Author: sshbio <jd@ssh.bio>
Date:   Sat, 13 Aug 2016 23:00:17 +0200

Re-wrote the whole thing in 200 lines!

Diffstat:
Mbin/irc | 253+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 104 insertions(+), 149 deletions(-)

diff --git a/bin/irc b/bin/irc @@ -3,144 +3,93 @@ # \/ _____ ____ # /\ / ____\/ ___\ # / // / / /__ -# \/ \/ \____\ - Irc client based on nc and a script from http://xero.nu +# \/ \/ \____\ - http://tools.suckless.org/ii, forked from http://xero.nu #=============================================================================== -help=' -/c, /connect, /s, /server SERVER - Start connection with SERVER - -/msg, /privmsg CHANNEL/NICK MESSAGE - Send MESSAGE to a particular CHANNEL or NICK - -/j, /join CHANNEL/NICK - Join a CHANNEL or a private conversation with NICK and set the current - channel to this - -/nick NICK - Update the user'"'"'s nickname to NICK. - -/quit - Close all connection and quit the client. - -/* ARGUMENTS - All other commands are sent directly to the server with ARGUMENTS.' - NICK="${NICK-$USER}" FULLNAME='With netcat and a script as a client' -IRC_DIR="$HOME/.cache/irc" +DIR="$HOME/.cache/irc" NICK_LEN=14 NL=' -' +' CR=' ' -# Server interaction +# Functions #------------------------------------------------------------------------------- # -# Write a message to $in in this for format: '\n${message}\r'. +# Write a message to a server # write() { - local message="$1" server="$2" + local srv="$1" msg="$2" - printf '\r%s\n' "$message" >> "$IRC_DIR/$server/in" + printf '\r%s\n' "$msg" >> "$DIR/$srv/IN" } # -# Start netcat identify the client and user, and start monitoring the response. +# Start netcat, identify the client and user, and monitor the response. # -open_connection() +connect() { - local server="$1" in="$IRC_DIR/$1/in" + local srv="$1" user="$(tail "$DIR/NICK")" - mkdir -p "$IRC_DIR/$server" - [ -p "$in" ] || mkfifo "$in" + mkdir -p "$DIR/$srv" + [ -p "$DIR/$srv/IN" ] || mkfifo "$DIR/$srv/IN" - tail -f "$in" | nc "$server" 6667 | output "$server" & + tail -f "$DIR/$srv/IN" | nc "$srv" 6667 | output "$srv" & - write "NICK $NICK" "$server" - write "USER pipe +i * :$FULLNAME" "$server" + write "$srv" "NICK $user" + write "$srv" "USER $(whoami) +i * :$FULLNAME" } # -# Parse command from user input and execute corresponding actions. +# Parse command from user input and print IRC messages. # input() { - local SERVER CHANNEL msg + local srv chan arg user while read cmd do - if [ -z "${cmd##/*}" ] - then arg="${cmd#* }" cmd="${cmd#/}" cmd="${cmd%% *}" - else arg="$cmd" cmd='' - fi - + user="$(tail "$DIR/NICK")" + arg="${cmd#* }" cmd="${cmd#/}" cmd="${cmd%% *}" cmd="$(printf %s "$cmd" | tr [a-z] [A-Z])" case "$cmd" in + C | CONNECT | S | SERVER ) + srv="$arg" + connect "$srv" & + ;; M | MSG | PRIVMSG ) - write "PRIVMSG ${arg%% *} :${arg#* }" "$SERVER" + arg="${arg%% *} :${arg#* }" + write "$srv" "PRIVMSG $arg" + printf '%s' ":$user!localhost PRIVMSG $arg" \ + | output "$srv" ;; J | JOIN ) - CHANNEL="$arg" - write "JOIN $arg" "$SERVER" - ;; - S | SERVER | C | CONNECT ) - SERVER="$arg" - if [ "$(ps ax | grep -F "$SERVER")" ] - then open_connection "$SERVER" - fi - ;; - HELP ) - printf '%s\n' "$help" - ;; - QUIT ) - write "QUIT $arg" "$SERVER" - printf 'Closing background process\n' - kill -9 0 + chan="$arg" + write "$srv" "JOIN $arg" ;; ME | ACTION ) - C_A="$(printf '\001')" - msg="PRIVMSG $CHANNEL :${C_A}ACTION $arg$C_A" - write "$msg" "$SERVER" - print_message "$SERVER" ":$NICK!localhost $msg$NL" + CA="$(printf '\001')" + write "$srv" "PRIVMSG $chan :${CA}ACTION ${arg}${CA}" + ;; + TOPIC | LIST ) + write "$srv" "TOPIC ${arg-chan}" ;; '' ) - msg="PRIVMSG $CHANNEL :$arg" - write "$msg" "$SERVER" - print_message "$SERVER" ":$NICK!localhost :$msg$NL" + write "$srv" "PRIVMSG $chan $arg" ;; * ) - write "$cmd $arg" "$SERVER" + write "$srv" "$cmd $arg" ;; esac done } - -# -# Maintain the connection open and manage the messages. -# -output() -{ - local server="$1" - - while read message - do - message="${message% }" - - case "$message" in - PING* ) write "PONG${message#PING}" "$server" ;; - *'VERSION'* ) write "SYSTEM sshbio CTCP: VERSION netcat" ;; - * ) print_message "$server" "$message" ;; - esac - done -} - # -# Parse server's message and print formatted message +# Maintain the connection open and print formatted message # # message = [ ":" prefix SPACE ] command [ params ] crlf # prefix = servername / ( nickname [ [ "!" user ] "@" host ] ) @@ -156,38 +105,53 @@ output() # SPACE = %x20 ; space character # crlf = %x0D %x0A ; "carriage return" "linefeed" # -print_message() +# +output() { - # Parse server's message - - local server="$1" msg="$2" prefix='' nick='' cmd='' \ - local params='' middle='' trail='' channel='' - - if [ -z "${msg##:*}" ] - then - prefix="${msg%% *}" - prefix="${prefix#:}" - [ -z "${prefix%%*!*}" ] && nick="${prefix%%!*}" - msg="${msg#* }" - fi - - cmd="${msg%% *}" - msg="${msg#* }" - params="${msg# *}" - middle="${msg% }" - middle="${msg%%:*}" - [ -z "${params%%*:*}" ] && trail="$( - printf '%s' "${params#*:}" | sed -r ' - s/([^]*)/\1/g - s/([^]*)/\1/g - s/ACTION(.*)/**\1 **/g - ')" - channel="${middle%% *}" - case "$channel" in - "$NICK" | '*' | '' ) channel=SERVER ;; - esac + local srv="$1" user="$(tail "$DIR/NICK")" - # Print formatted message + while read msg + do + # Parse server message + + local prefix='' nick='' trail='' cmd params middle chan + + msg="${msg#$CR}" msg="${msg%$CR}" + if [ -z "${msg##:*}" ] + then + prefix="${msg%% *}" prefix="${prefix#:}" + [ -z "${prefix%%*!*}" ] && nick="${prefix%%!*}" + msg="${msg#* }" + fi + + cmd="${msg%% *}" + msg="${msg#* }" params="$msg" + middle="${msg% }" middle="${msg%%:*}" + [ -z "${params%%*:*}" ] && trail="${params#*:}" + chan="${middle%% *}" + case "$chan" in + "$user" | '*' | '' ) chan='SERVER' ;; + esac + + # Execute action + + case "$cmd" in + PING ) + write "$srv" "PONG $params" + ;; + * ) + print_msg "$nick" "$trail" "$cmd" >> "$DIR/$srv/$chan" + ;; + esac + done +} + +# +# Print formatted message +# +print_msg() +{ + local nick="$1" trail="$2" cmd="$3" user="$(tail "$DIR/NICK")" case "$cmd" in QUIT ) cmd='<' ;; @@ -197,49 +161,40 @@ print_message() PART ) cmd='~' ;; ERROR ) cmd='X' ;; MODE ) cmd='+' ;; - NICK ) cmd='=' [ "$nick" = "$NICK" ] && NICK="$trail" ;; + NICK ) cmd='=' + [ "$nick" = "$user" ] && printf '%s\n' "$trail" > "$DIR/NICK" + ;; esac # One line separator - if [ "$last" != "$nick" -o "$nick" = "$NICK" ] - then printf "%${NICK_LEN}s |\n" >> "$IRC_DIR/$SERVER/$channel" - fi - last="$nick" + printf "%${NICK_LEN}s |\n" # Print the message - printf '%s\n' "$trail" | fold -s -w $((80 - $NICK_LEN - ${#cmd})) \ + printf '%s\n' "$trail" | fold -s -w $((78 - $NICK_LEN - ${#cmd})) \ | while read line do - printf "%${NICK_LEN}s %1s %s\n" "$nick" "$cmd" "$line" \ - >> "$IRC_DIR/$SERVER/$channel" + printf "%${NICK_LEN}s %1s %s\n" "$nick" "$cmd" "$line" nick='' done } + # Algorythm #------------------------------------------------------------------------------- +# Kill background jobs and delete named pipes while quitting +trap 'find "$DIR" -type p -exec rm {} ";"; kill -9 0' INT EXIT + # Prepare the irc log directory -[ -d "$IRC_DIR" ] || mkdir -p "$IRC_DIR" - -# Start listenning the user input -[ -p "$IRC_DIR/in" ] || mkfifo "$IRC_DIR/in" - -if [ "$(ps ax | grep -F "$IRC_DIR" | wc -l)" -gt 1 ] -then - cd "$IRC_DIR" - IFS="$NL" - for file in $(find . -type f); do files="$files$NL${file#./}"; done - exec less -R $files - unset IFS -else - tail -f "$IRC_DIR/in" | input & - printf 'This is an interactive interpreter. You can send irc commands. -You can also send commands by writing them to '"$IRC_DIR/IN"'. -For a list of available commands, send "/help". -If you run the `irc` again, you will get all channels displayed in `less -R` -\n' - while read command - do printf '%s\n' "$command" > "$IRC_DIR/in" - done -fi +[ -d "$DIR" ] || mkdir -p "$DIR" +printf '%s\n' "$NICK" > "$DIR/NICK" + +# Start interactive session +printf '> ' "$DIR" 1>&2 +[ -p "$DIR/IN" ] || mkfifo "$DIR/IN" +tail -f "$DIR/IN" | input & +while read cmd +do + printf '\033[A\r\033[K> ' 1>&2 + printf '%s\n' "$cmd" >> "$DIR/IN" +done