site-josuah

/usr/josuah
Log | Files | Refs

commit a69be6e87d625e18ff3fa54884fd8dc884432ed0
parent 84cec3a7667396a9aa2db968d2f131dfbb8604cc
Author: Josuah Demangeon <me@josuah.net>
Date:   Sat, 18 Apr 2020 04:36:09 +0200

stagit not ready yet...

Diffstat:
Mhead.html | 2+-
Mwiki/jj/index.md | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Awiki/jj/jj-in | 20++++++++++++++++++++
Awiki/jj/jj-log | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awiki/jj/jj-tail | 20++++++++++++++++++++
Awiki/jj/retail | 38++++++++++++++++++++++++++++++++++++++
6 files changed, 288 insertions(+), 2 deletions(-)

diff --git a/head.html b/head.html @@ -10,7 +10,7 @@ pre { margin-left:4ch; } <a href="/">[ josuah.net ]</a> <nav style="float:right;"> -<a href="git.z0.is">git</a> - +<a href="#">git</a> - <a href="/pub/josuah.ssh">ssh</a> - <a href="/pub/josuah.gpg">gpg</a> - <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#101;&#64;&#106;&#111;&#115;&#117;&#97;&#104;&#46;&#110;&#101;&#116;">mail</a> - diff --git a/wiki/jj/index.md b/wiki/jj/index.md @@ -21,7 +21,7 @@ It reads its entire configuration from environment variables, described on the the project's README.md, such as $IRC_DIR, in which it create a direcTory with the channel as a name. -I set IRC_DIR to /var/irc, which give us (full list on the README.md): +I set IRC_DIR to /var/irc, which gives us (full list on the README.md): * /var/irc/irc.freenode.net/channels/*.log - messages from users and channels. * /var/irc/irc.freenode.net/in - the FIFO pipe to which write messages. @@ -150,3 +150,66 @@ This is the same script while run as #!/bin/sh. Yes, this is a single command! s6-tcpclient 127.0.0.1 9050 \ sockc "5ogdsfyoqk47ompu.onion" "6667" \ jjd + + +Making jj useable interactively +------------------------------- +Being log-based, wrappers tools are necessary for making jj useable as a main +IRC client. + +### [[jj-in]] + +*similar to jji from the jj package* + +Take lines from the user stdin with a prompt set to the name of the channel. +A better line-editing tool could be used, such as rlwrap around this. + +[jj-in]: /wiki/jj/jj-in + +### [[jj-log]] + +*similar to jjp in the jj package* + +Get a human-readable feed out of the jj log: +Filter the log to add colors. One way to use it is: tail -f chan.log | jj-log + +[jj-log]: /wiki/jj/jj-log + +### [[retail]] + +*not in original jj package* + +Print the multiple files sorted as if tail -f was printing them since the +beginning, with the same "==> filename <==" header. + +[retail]: /wiki/jj/retail + +### [[jj-tail]] + +*not in original jj package* + +Instead of going with tmux for handling all the log files to follow, I went +with the approach of reading all channels of all networks in a same stream, +showing a headers for each channel (at least in my fork of jjp): + + irc.freenode.net/##networking + 00:12:30 TikityTik: it's like having a bad fever dream with this ISP + + irc.freenode.net/#cat-v + 00:12:34 cinap_lenrek: when usb is enabled sounds like a vm? + 00:12:36 cinap_lenrek: whats the context? + + irc.freenode.net/#openbsd + 00:12:36 thrig: Logan Runners? + 00:12:37 epsilonKNOT: with blackjack and hookers + +To avoid being bothered with too many channels at once, it takes a list of +find(1) -path $filters as argument that will match the name of the +server/channels. + +This way, you can reduce the scope of the conversation to one server, similar +channels on multiple servers, just the selected channels... + +This tool makes use of jj-log and retail. + +[jj-tail]: /wiki/jj/jj-tail diff --git a/wiki/jj/jj-in b/wiki/jj/jj-in @@ -0,0 +1,20 @@ +#!/bin/sh -e +# input wrapper for jj + +path=${1:?} +chan=${path#*/} +host=${path%%/*} + +cd "/var/irc/$host" +[ -p "in" -a -w "in" ] + +prompt() { [ -t 0 ] && printf '\033[37m%s\033[0m> ' "$1" >&2 || :; } + +while prompt "$chan" && IFS= read -r line || [ -n "$line" ]; do + case "$line" in + /[!/]*) line=${line#?} ;; + '') continue ;; + *) line="msg $chan $line" ;; + esac + printf '%s\n' "$line" +done >"in" diff --git a/wiki/jj/jj-log b/wiki/jj/jj-log @@ -0,0 +1,145 @@ +#!/usr/bin/awk -f + +function isleap(year) +{ + return (year % 4 == 0) \ + && (year % 100 != 0) \ + || (year % 400 == 0) +} + +function mdays(mon, year) +{ + return (mon == 2) \ + ? (28 + isleap(year)) \ + : (30 + (mon + (mon > 7)) % 2) +} + +# Split the time in seconds since epoch into a table, with fields named +# as with gmtime(3): tm["year"], tm["mon"], tm["mday"], tm["hour"], +# tm["min"], tm["sec"]. +function gmtime(sec, tm) +{ + tm["year"]=1970 + while (sec >= (s = 86400 * (365 + isleap(tm["year"])))) { + tm["year"]++ + sec-=s + } + + tm["mon"]=1 + while (sec >= (s = 86400 * mdays(tm["mon"], tm["year"]))) { + tm["mon"]++ + sec-=s + } + + tm["mday"]=1 + while (sec >= (s = 86400)) { + tm["mday"]++ + sec-=s + } + + tm["hour"]=0 + while (sec >= 3600) { + tm["hour"]++ + sec-=3600 + } + + tm["min"]=0 + while (sec >= 60) { + tm["min"]++ + sec-=60 + } + + tm["sec"]=sec +} + +# Handle tail's "==> filename <==" headers +$1 == "==>" { + sub("/channels/", " ") + sub(".log <==", "") + sub(".*/", "") + sub(" ", "/") + printf "\n%s", $0 + next +} + +function tz( cmd, date, h, m) +{ + cmd="date +%z 2>/dev/null" + cmd | getline date + close(cmd) + + h=substr(date, 2, 2) + m=substr(date, 4, 2) + tzoffset=substr(date, 1, 1) (h * 3600 + m * 60) +} + +BEGIN { + FS=" " + tz() +} { + if (NF < 2) { + printf "\n%s", $0 + next + } + + gmtime($1 + tzoffset, tm) + date=sprintf("%04d/%02d/%02d", tm["year"], tm["mon"], tm["mday"]) + time=sprintf("%02d:%02d", tm["hour"], tm["min"]) + + # Display date only when it actually changed. + if (lastdate != date) { + lastdate=date + printf "%s\033[37m-- %s --\033[0m", + (NR != 1 ? "\n\n" : ""), date + } + + nickend=index($2, ">") + type=substr($2, nickend+1) + msg=substr($0, index($0, ">") + 2 + length(type)) + nick=substr($2, 2, nickend-2) + + # Set the date color for highlights. + if (index(type, "!")) { + printf "\a" + dcolor="33" + } else { + dcolor="38;5;8" + } + + # When JJ_SERVERLOG is set, print messages in the default color. + if (ENVIRON["JJ_SERVERLOG"] != "") { + printf "\n\033[%sm%s\033[0m %s", dcolor, time, msg + next + } + + # Status message. + if (nick == "-") { + printf "\n\033[%sm%s \033[%sm%s\033[0m", + dcolor, time, "38;5;8", msg + next + } + + isme=index(type, "*") + + # Alternating nick colors for better readability. + if (!isme && lastnick != nick) { + alt=!alt + lastnick=nick + } + + if (isme) + ncolor="37" + else if (alt) + ncolor="31" + else + ncolor="0" + + # Handle ACTION. + if (index(type, "a")) { + msg=nick " " msg + nick="*" + } + + printf "\n\033[%sm%s\033[0m \033[%sm%10s\033[0m: %s", + dcolor, time, ncolor, nick, msg +} END { print "" } diff --git a/wiki/jj/jj-tail b/wiki/jj/jj-tail @@ -0,0 +1,20 @@ +#!/bin/sh -e +# tail all jj channels in /var/irc + +# build a list of (-path "") to give to find(1) +[ "$#" = 0 ] && set -- "" +for x in "$@"; do + shift + set -- "$@" -o -path "*$x*.log" +done + +# remove the leading -o +shift + +# First print the history +find "/var/irc" "$@" -exec retail {} + \ + | jj-log + +# Then print the live log +exec find "/var/irc" "$@" -exec tail -f -n 0 {} + \ + | exec jj-log diff --git a/wiki/jj/retail b/wiki/jj/retail @@ -0,0 +1,38 @@ +#!/usr/bin/awk -f +# print files as if tail -f was running since the beginning +# +# Non-POSIX tail(1) supports multiple files and printing a "==> filename <==" +# header. This gives a different result if you are running tail since 2 minutes +# with lines comming from the various files repeating the headers frequently, +# or if you re-run tail again on the files. +# +# This script sorts all lines from the different files, and print the header +# whenever the file being printed changes, which give the same output of a +# tail -f ... running since the beginning. +# +# Note that this requires the files'line to already be sorted, such as +# containing a timestamp. +# +# If you use a log with Apr Aug Dec Feb Jan Jun Jul Mar May Nov Sep instead of +# a real timestamp, you may convert the dates and pipe it to that script. + +BEGIN { + for (i = 1; i < ARGC; i++) + files[ARGV[i]] = "" + + for (f in files) + if ((getline files[f] <f) <= 0) + delete files[f] + + while (length(files) > 0) { + for (f in files) + if (!(min in files) || files[f] < files[min]) + min = f + if (last != min) + printf("\n==> %s <==\n", min) + last = min + print(files[min]) + if ((getline files[min] <min) <= 0) + delete files[min] + } +}