commit 952a896057e655a843cb4c2f92f371633f776f02 Author: Jaidyn Lev Date: Sat Jan 19 23:42:07 2019 -0600 Init diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..4b35150 --- /dev/null +++ b/README.txt @@ -0,0 +1,72 @@ +=============================================================================== +UNICHAT.SH Read Unichat in your terminal! +=============================================================================== + +With unichat.sh, you can read Unichat the way gods intended: in your terminal, +in pretty ANSI-formatted text! <3 + +unichat.sh supports regular monochrome text, 8-bit ANSI colors, and (if you're +one of those lucky lads who gets them) 255-range ANSI colors! + +https://unichat-comic.com + + + +---------------------------------------- +PRE-REQUISITES +---------------------------------------- +You'll need: + * `lynx` installed + * a POSIX-compatible shell (tested with `pdksh` and `bash`) + * "gendl" in your $PATH + * "uclib/" in your CWD or in the dir that "unichat.sh" resides in + + + +---------------------------------------- +USAGE +---------------------------------------- + +UNICHAT.SH +-------------------- +Run unichat.sh in your terminal, like so: + + unichat.sh id [width] [color] + +id is the only required option. + +id, of course, means the comic ID that you want to read. +width is the width of each line-- default is 80 characters. +color is the color-type you want-- 0, 8, and 255 are the only valid options. + + +UCGEN.SH +-------------------- +ucgen.sh will download all unichat comics in the format you provide. +It's for stripping the site, basically. :) + + ucgen.sh [width] [color] + +The comics will be output into a subdir of your cwd, with a name based on +the width and color values you provided, I.E., "80-255" or something like that. + + +GENDL +-------------------- +gendl is just for downloading things, as a frontend for "curl" "wget" etc. +It's here for portability reasons-- you probably don't want to use it yourself. + +But here's usage, if you decide you do: + + gendl [-o path] url + +gendl downloads the URL to stdout, unless you specify an output file with "-o". + + + +---------------------------------------- +BORING STUFF +---------------------------------------- +License is CC-0 +Author is Jenga Phoenix +Sauce is at https://git.eunichx.us/unichat diff --git a/gendl b/gendl new file mode 100755 index 0000000..6f4ea9e --- /dev/null +++ b/gendl @@ -0,0 +1,155 @@ +#!/bin/sh +############################## +# name: gendl +# lisc: gnu gplv3 +# desc: download to stdout or +# file, independent of +# a specific downloader. +# ftp/wget/curl support. +# main: jadedctrl +############################## + +# usage: gendl [-o output] url + + + +#--------------------------------------- +# backend bits + +# NIL --> STRING +# return the download program you're using +function download_program +{ + programs="ftp curl wget" + current="" + + for program in $programs + do + if whereis $program > /dev/null + then + current=$program + fi + done + + if uname -s | grep -e "LibertyBSD" -e "OpenBSD" > /dev/null + then + current="ftp" + fi + + echo "$current" +} + +# STRING PATH --> NIL +# download URL $1 to stdout +function download_stdout +{ + program=$(download_program) + url=$1 + + case "$program" in + "ftp") + output="$(ftp -VMo- $url)" + ;; + "curl") + output="$(curl $url)" + ;; + "wget") + output="$(wget --quiet -O $url)" + ;; + esac + + return_code=$? + + echo "$output" + return $return_code +} + +# STRING PATH --> NIL +# download URL $1 to path $2 +function download_file +{ + program=$(download_program) + url=$1 + path=$2 + + case "$program" in + "ftp") + ftp -VMU "." -o $path $url + ;; + "curl") + curl -o $path $url + ;; + "wget") + wget --quiet -O $path $url + ;; + esac + + return_code=$? + + if test $return_code -ne 0 2>/dev/null + then + rm $path 2> /dev/null + # for consistency in behavior; wget saves 404s anyway, whereas + # ftp doesn't save anything from 404s, etc. + fi + + return $return_code +} + + + +# -------------------------------------- +# front-end string-manip + +# STRING --> STRING +# return the last word in a string +function last_word +{ + string="$1" + + echo "$string" \ + | rev \ + | sed 's% .*%%' \ + | rev +} + +function usage +{ + echo "usage: gendl [-o output] URL" +} + + + +# -------------------------------------- +# invocation + +args="$(getopt o: $*)" +if test -z "$@" 2>/dev/null +then + usage + exit 2 +fi + + +set -- $args +while test $# -ne 0 +do + case "$1" + in + -o) + download_path="$2"; shift; shift;; + --) + shift; break;; + esac +done + + +url="$(last_word "$@")" + + +if test -n "$download_path" 2> /dev/null +then + download_file $url $download_path +else + download_stdout "$url" +fi diff --git a/ucgen.sh b/ucgen.sh new file mode 100644 index 0000000..409640f --- /dev/null +++ b/ucgen.sh @@ -0,0 +1,27 @@ +#!/bin/sh +######################################## +# name: gen.sh +# desc: generate txt-versions of all +# unichat comics, in the given +# width/color format +######################################## + +WIDTH="$1" +COLOR="$2" + +if test -z "$1" -o -z "$2" +then + echo "usage: ucgen.sh width color" + exit 2 +fi + +dir="$COLOR-$WIDTH" +mkdir "$dir" + +i=1 +while test $i -lt 194 +do + echo "Page $i..." + sh unichat.sh $i $WIDTH $COLOR > "$dir/$i.txt" + i=$(echo "$i + 1" | bc) +done diff --git a/uclib/255color.sh b/uclib/255color.sh new file mode 100644 index 0000000..2939bb3 --- /dev/null +++ b/uclib/255color.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# -------------------------------------- +# main + +# STRING --> STRING +# return the 255 color of a username +function name_color255 { + username="$1" + result_stack="" + + hex=$(name_color_hex "$username"); result_stack="$result_stack $?" + hex255=$(hex_to_255 $hex); result_stack="$result_stack $?" + color="$(color_255 $hex255)"; result_stack="$result_stack $?" + + + if echo "$result_stack" | grep 1 > /dev/null + then + color="$(name_color8 "$username")" + fi + + echo "$color" +} + + + +# -------------------------------------- +# helper functions + +# STRING --> STRING +# return the hexcode of a username (from CSS) +function name_color_hex { + username="$1" + + if test ! -e /tmp/255.html; then + gendl -o /tmp/255.html "http://unichat-comic.com/comics/1" + fi + + cat /tmp/255.html \ + | grep ".${username} { color:" \ + | sed 's/.*color: #//' \ + | sed 's/ \!important.*//' +} + +# STRING --> NUMBER +# return the 255 number of a color hexcode +# from https://unix.stackexchange.com/a/269085 +function hex_to_255 { + hex=${1#"#"} + r=$(printf '0x%0.2s' "$hex" 2>/dev/null) + g=$(printf '0x%0.2s' ${hex#??} 2>/dev/null) + b=$(printf '0x%0.2s' ${hex#????} 2>/dev/null) + printf '%03d' "$(( (r<75?0:(r-35)/40)*6*6 + + (g<75?0:(g-35)/40)*6 + + (b<75?0:(b-35)/40) + 16 ))" 2>/dev/null +} + +# NUMBER --> STRING +# return 255 ANSI escape-code of a color +# frlom https://unix.stackexchange.com/a/269085 +function color_255 { + for c; do + printf '\e[38;5;%dm' $c 2>/dev/null + done +} diff --git a/uclib/8color.sh b/uclib/8color.sh new file mode 100755 index 0000000..41c2f92 --- /dev/null +++ b/uclib/8color.sh @@ -0,0 +1,150 @@ +#!/bin/sh + + +function name_color8 { + username="$1" + + case "$username" in + "SonjaOfTheMoon") echo "$MAGENTA";; + "EntropicPhantom") echo "$YELLOW";; + "Sidhe_Trickster") echo "$GREEN";; + "SecundaSonja") echo "$MAGENTA";; + "CmdrCordovaOfficial") echo "$CYAN";; + "LieutenantCordova") echo "$YELLOW";; + "pwnz0rz") echo "$CYAN";; + "pwnz1ing") echo "$YELLOW";; + "pwnz2much") echo "$YELLOW";; + "pwnz3r") echo "$CYAN";; + "metampsychotic") echo "$YELLOW";; + "FelisKitty") echo "$GREEN";; + "CGoddess") echo "$CYAN";; + "MatttheRA") echo "$MAGENTA";; + "ReverseTheStreams") echo "$RED";; + "Reverse_The_Streams") echo "$RED";; + "dukerex") echo "$ORANGE";; + "ItsDuckKingKarl") echo "$YELLOW";; + "bloodshoes") echo "$ORANGE";; + "AdmiralPancake") echo "$RED";; + "Admiral_Pancake") echo "$RED";; + "Admiral.Pancake") echo "$RED";; + "Pancake_High_Admiral") echo "$RED";; + "romanceconspirator") echo "$CYAN";; + "apocalypseconspirator") echo "$CYAN";; + "aardvarkconspirator") echo "$CYAN";; + "silentconspirator") echo "$CYAN";; + "Empress_Of_Silence") echo "$CYAN";; + "banannaconspirator") echo "$CYAN";; + "billygoatconspirator") echo "$CYAN";; + "bobtheconspirator") echo "$CYAN";; + "quixoticconspirator") echo "$CYAN";; + "yellowconspirator") echo "$CYAN";; + "lemmingconspirator") echo "$CYAN";; + "largeconspirator") echo "$CYAN";; + "sillyconspirator") echo "$CYAN";; + "lackadaisicalconspirator") echo "$CYAN";; + "bouncyconspirator") echo "$CYAN";; + "wildfireconspirator") echo "$CYAN";; + "zygoteconspirator") echo "$CYAN";; + "Pancomputer") echo "$GREEN";; + "Anarchon") echo "$YELLOW";; + "DrHorrible") echo "$YELLOW";; + "venemous") echo "$BLUE";; + "m1ndh1ve1") echo "$GREEN";; + "Bulwark") echo "$GREEN";; + "BULWARK") echo "$GREEN";; + "GodsOfOlympus") echo "$BLUE";; + "OITHEOI") echo "$BLUE";; + "TA_DAIMONIA") echo "$BLUE";; + "Theodore_Oien") echo "$BLUE";; + "__RSPTN__") echo "$BLUE";; + "ThatOneVampChick") echo "$MAGENTA";; + "MrE") echo "$ORANGE";; + "CaptainKoreaboo") echo "$CYAN";; + "Unus_Relicuum") echo "$BLUE";; + "Unum_Relicuum") echo "$BLUE";; + "HadesRealmOfficial") echo "$ORANGE";; + "VladmirOrlovOfficial") echo "$YELLOW";; + "BBC_Official") echo "$ORANGE";; + "BuzzfeedOfficial") echo "$BLUE";; + "algranon") echo "$GREEN";; + "DOGFOODLID") echo "$YELLOW";; + "xX_RabbitFan_Xx") echo "$YELLOW";; + "giant_death_ferret") echo "$BROWN";; + "WhoRemembers") echo "$BROWN";; + "RED") echo "$RED";; + "YELLOW") echo "$YELLOW";; + "GREEN") echo "$GREEN";; + "BLUE") echo "$BLUE";; + "PURPLE") echo "$MAGENTA";; + "WHITE") echo "$WHITE";; + "JUPITER") echo "$RED";; + "HERA") echo "$RED";; + "NEPTUNE") echo "$RED";; + "MINERVA") echo "$RED";; + "ARES") echo "$RED";; + "APHRODITE") echo "$RED";; + "TheRealHannah") echo "$GREEN";; + "not_metampsychotic") echo "$YELLOW";; + "Do_I_know_this_guy") echo "$CYAN";; + "EntropicKitten") echo "$YELLOW";; + "SonjaOfTheMeow") echo "$VIOLET";; + "purrz0rz") echo "$CYAN";; + "meowtampsychotic") echo "$YELLOW";; + "AdogmiralPanbark") echo "$RED";; + "Adogmiral_Panbark") echo "$RED";; + "Dellis") echo "$GREEN";; + "DefinitelyNotAnUmbrella") echo "$MAGENTA";; + "Seabiscuit") echo "$BLUE";; + "Arbiter") echo "$BLUE";; + "TempShoulderAngel") echo "$MAGENTA";; + "_TempShoulderAngel") echo "$MAGENTA";; + "HotFuzzFacts") echo "$BLUE";; + "HotFuzzFacts2") echo "$BLUE";; + "HotFuzzFacts3") echo "$BLUE";; + "HotFuzzFacts4") echo "$BLUE";; + "HotFuzzFacts5") echo "$BLUE";; + "HotFuzzFacts6") echo "$BLUE";; + "HotFuzzFacts7") echo "$BLUE";; + "HotFuzzFacts8") echo "$BLUE";; + "HotFuzzFacts9") echo "$BLUE";; + "HotFuzzFacts413") echo "$BLUE";; + "HotFuzzFacts414") echo "$BLUE";; + "HotFuzzFacts415") echo "$BLUE";; + "HotFuzzFacts416") echo "$BLUE";; + "KittenLicks") echo "$CYAN";; + "Xenocartographer") echo "$BROWN";; + "GAIA") echo "$BROWN";; + "etamnanki") echo "$BROWN";; + "SansFinalGuardian") echo "$BLUE";; + "SansOfTheUnderground") echo "$YELLOW";; + "SansTheComic") echo "$GREEN";; + "endsoftime") echo "$MAGENTA";; + "DeepDark") echo "$YELLOW";; + "BookOfQuantumFlux") echo "$BROWN";; + "reddragonfall") echo "$GRAY";; + "Turquoise") echo "$GREEN";; + "judge_of_character") echo "$BROWN";; + "Wildcat") echo "$RED";; + "Wildcat2") echo "$MAGENTA";; + "__Delta__") echo "$RED";; + "ppDeltapp") echo "$RED";; + "Padlock") echo "$GRAY";; + "Mini_coopa2") echo "$GRAY";; + "The44th") echo "$MAGENTA";; + "Ravencorp") echo "$BLUE";; + "CONNECT_1200") echo "$GRAY";; + "FallenLeaves") echo "$YELLOW";; + "Pixelknight") echo "$BLUE";; + "SteveTheMewHunter") echo "$CYAN";; + "Stargazer") echo "$BLUE";; + "TheDerangedOne") echo "$BLUE";; + "russiansoldier1") echo "$RED";; + "russiansoldier2") echo "$ORANGE";; + esac +} + +function colorize_name8 { + username="$1" + + echo "$(name_color8 "$username")${username}$RESET" +} diff --git a/uclib/ansi.sh b/uclib/ansi.sh new file mode 100755 index 0000000..b113798 --- /dev/null +++ b/uclib/ansi.sh @@ -0,0 +1,132 @@ +#!/bin/sh + +# -------------------------------------- +# colors + +BLACK="$(tput setaf 0 2> /dev/null)" +RED="$(tput setaf 1 2> /dev/null)" +GREEN="$(tput setaf 2 2> /dev/null)" +YELLOW="$(tput setaf 3 2> /dev/null)" +BLUE="$(tput setaf 4 2> /dev/null)" +MAGENTA="$(tput setaf 5 2> /dev/null)" +CYAN="$(tput setaf 6 2> /dev/null)" +WHITE="$(tput setaf 7 2> /dev/null)" +ORANGE="$RED" +GRAY="$CYAN" +BROWN="$GREEN" + +BOLD="$(tput bold 2> /dev/null)" + +RESET="$(tput sgr0)" + + + +# -------------------------------------- +# generic color functions + +# STRING --> STRING +# return the color-string of a certain username +function name_color { + username="$1" + + if test $COLOR -eq 8; then + name_color8 "$username" + elif test $COLOR -eq 255; then + name_color255 "$username" + fi +} + +# STRING --> STRING +# return a colored username +function colorize_name { + username="$1" + + if test $COLOR -eq 8; then + echo "$(name_color8 "$username")${username}${RESET}" + elif test $COLOR -eq 255; then + echo "$(name_color255 "$username")${username}${RESET}" + fi +} + +# -------------------------------------- + +# STRING STRING --> STRING +# colorize all non-message references to a given username (generic) +function colorize_name_instances { + string="$1" + username="$2" + + echo "$string" \ + | sed 's/ '"$username"':/ '"$(colorize_name "$username")"':/g' \ + | sed 's/message '"$username"' /message '"$(colorize_name "$username")"' /g' \ + | sed 's/user '"$username"'/user '"$(colorize_name "$username")"'/g' \ + | sed 's/User '"$username"'/User '"$(colorize_name "$username")"'/g' +} + +# STRING STRING --> STRING +# colorize all lines that are a message of the given username (generic) +function colorize_name_lines { + string="$1" + username="$2" + + echo "$string" \ + | sed 's/'"$username"':/'"$(name_color "$username")$username"':/g' +} + + + +# -------------------------------------- + +# STRING --> STRING +# embolden all action-lines +function action_bold { + txt="$1" + + echo "$txt" \ + | sed 's/^\*/'"$BOLD"'\*/' +} + +# -------------------------------------- + +# STRING --> STRING +# add an ANSI reset escape-code at the end of every line +function reset_ends { + string="$1" + + echo "$string" \ + | sed 's/$/'"$RESET"'/g' +} + +# STRING --> STRING +# apply basic formatting/cleanup actions to an ANSI string +function ansi_process { + txt="$1" + + txt="$(reset_ends "$txt")" + txt="$(action_bold "$txt")" + + echo "$txt" +} + + + +# -------------------------------------- + +# STRING NUMBER --> STRING +# convert regular text to ANSI-formatted text +function txt_to_ansi { + txt="$1" + width="$2" + + + for username in $usernames + do + if echo "$txt" | grep "$username" > /dev/null + then + txt="$(colorize_name_instances "$txt" "$username")" + txt="$(colorize_name_lines "$txt" "$username")" + fi + done + + ansi_process "$(txt_process "$txt")" | fold -sw $width +} diff --git a/uclib/usernames.sh b/uclib/usernames.sh new file mode 100755 index 0000000..8c420d0 --- /dev/null +++ b/uclib/usernames.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# -------------------------------------- +# usernames + +usernames="SonjaOfTheMoon EntropicPhantom Sidhe_Trickster SecundaSonja" +usernames="$usernames CmdrCordovaOfficial LieutenantCordova pwnz0rz pwnz1ing" +usernames="$usernames pwnz2much pwnz3r metampsychotic FelisKitty CGoddess" +usernames="$usernames MatttheRA ReverseTheStreams Reverse_The_Streams dukerex" +usernames="$usernames ItsDuckKingKarl bloodshoes AdmiralPancake" +usernames="$usernames Admiral_Pancake Admiral.Pancake Pancake_High_Admiral" +usernames="$usernames romanceconspirator apocalypseconspirator" +usernames="$usernames aardvarkconspirator silentconspirator Empress_Of_Silence" +usernames="$usernames banannaconspirator billygoatconspirator" +usernames="$usernames bobtheconspirator quixoticconspirator yellowconspirator" +usernames="$usernames yellowconspirator lemmingconspirator largeconspirator" +usernames="$usernames sillyconspirator lackadaisicialconspirator" +usernames="$usernames bouncyconspirator wildfireconspirator zygoteconspirator" +usernames="$usernames Pancomputer Anarchon DrHorrible venemous m1ndh1ve1" +usernames="$usernames Bulwark BULWARK GodsOfOlympus OITHEOI TA_DAIMONIA" +usernames="$usernames Theodore_Oien __RSPTN__ ThatOneVampChick MrE" +usernames="$usernames CaptainKoreaboo Unus_Relicuum Unum_Relicuum" +usernames="$usernames HadesRealmOfficial VladmirOrlovOfficial BBC_Official" +usernames="$usernames BuzzfeedOfficial algranon DOGFOODLID xX_RabbitFan_Xx" +usernames="$usernames giant_death_ferret WhoRemembers" +usernames="$usernames RED YELLOW GREEN BLUE PURPLE WHITE" +usernames="$usernames JUPITER HERA NEPTUNE MINERVA ARES APHRODITE" +usernames="$usernames TheRealHannah not_metampsychotic Do_I_know_this_guy" +usernames="$usernames EntropicKitten SonjaOfTheMeow purrz0rz meowtampsychotic" +usernames="$usernames AdogmiralPanbark Adogmiral_Panbark Dellis" +usernames="$usernames DefinitelyNotAnUmbrella Seabiscuit Arbiter" +usernames="$usernames TempShoulderAngel _TempShoulderAngel" +usernames="$usernames HotFuzzFacts HotFuzzFacts2 HotFuzzFacts3 HotFuzzFacts4" +usernames="$usernames HotFuzzFacts5 HotFuzzFacts6 HotFuzzFacts7 HotFuzzFacts8" +usernames="$usernames HotFuzzFacts9 HotFuzzFacts413 HotFuzzFacts414" +usernames="$usernames HotFuzzFacts415 HotFuzzFacts416" +usernames="$usernames KittenLicks Xenocartographer GAIA etamnanki" +usernames="$usernames SansFinalGuardian SansOfTheUnderground SansTheComic" +usernames="$usernames endsoftime DeepDark BookOfQuantumFlux reddragonfall" +usernames="$usernames Turquoise judge_of_character Wildcat Wildcat2 __Delta__" +usernames="$usernames ppDeltapp Padlock Mini_coopa2 The44th Ravencorp" +usernames="$usernames CONNECT_1200 FallenLeaves Pixelknight SteveTheMewHunter" +usernames="$usernames Stargazer TheDerangedOne russiansoldier1 russiansoldier2" diff --git a/unichat.sh b/unichat.sh new file mode 100755 index 0000000..f119986 --- /dev/null +++ b/unichat.sh @@ -0,0 +1,160 @@ +#!/bin/sh +######################################## +# name: unichat.sh +# desc: download a unichat page to ansi +# -formatted, colored text. +# perfect for reading on terminal! +######################################## + +if test -e uclib; then + prefix="./" +else + prefix="$(dirname "$(echo "$0")")/" +fi + +. "${prefix}uclib/usernames.sh" +. "${prefix}uclib/ansi.sh" +. "${prefix}uclib/255color.sh" +. "${prefix}/uclib/8color.sh" + + +# -------------------------------------- +# generic + +# NIL --> STRING +# read from stdin until eof hit; return all input +# good for writing functions that take piped info +function reade { + local stack="" + + while read input + do + stack="$(printf '%s\n%s' "$stack" "$input")" + done + + echo "$stack" +} + + + +# -------------------------------------- +# fetch + +# NUMBER --> STRING +# actual download/return HTML of unichat comic of given id +function unichat_fetch { + id="$1" + + gendl -o "$TEMP" "http://unichat-comic.com/comics/${id}/" + cat "$TEMP" +} + + + +# -------------------------------------- +# html manipulations + +# |STRING --> STRING +# remove everything from piped unichat html except for +# the actual comic part +function isolate_log { + html="$(reade)" + + echo "$html" \ + | sed '1,/Unichat log/d' \ + | sed '/article-foot/,$d' +} + +# |STRING --> STRING +# add tags to the isolated log to make it valid HTML +function isolate_to_html { + log="$(reade)" + + header="Unichat" + footer="" + + printf "%s\n%s\n%s" "$header" "$log" "$footer" +} + +# |STRING --> STRING +# convert piped HTML into plain-text-- via w3m +function html_to_txt { + html="$(reade)" + + echo "$html" \ + | echo "$(lynx -stdin -width 1000 -nolist -dump)" +} + + + +function whitespace_trim { + string="$1" + + echo "$string" \ + | sed 's/^ //g' \ + | sed 's/^ //g' +} + +function unichat_to_txt { + id="$1" + + gendl "http://unichat-comic.com/comics/${id}/" \ + | isolate_log \ + | isolate_to_html \ + | html_to_txt +} + +function txt_process { + txt="$1" + + txt="$(whitespace_trim "$txt")" + + echo "$txt" +} + +function txt_to_txt { + txt="$1" + width="$2" + + txt_process "$txt" | fold -sw $width +} + + + +# -------------------------------------- +# invocation + +ID="1" +WIDTH="80" +COLOR=8 +TEMP="$(mktemp)" + +if test -n "$1"; then + ID="$1" +fi +if test -n "$2"; then + WIDTH="$2" +fi +if test -n "$3"; then + COLOR=$3 +fi + +# -------------------------------------- + +function invoke { + if test $COLOR -eq 0; then + txt_to_txt "$(unichat_to_txt "$ID")" $WIDTH + else + txt_to_ansi "$(unichat_to_txt "$ID")" $WIDTH + fi + + rm $TEMP +} + + +if test -z "$1"; then + echo "usage: unichat.sh id [width] [color]" + exit 2 +fi + +invoke