This commit is contained in:
Jaidyn Lev 2019-01-19 23:42:07 -06:00
commit 952a896057
8 changed files with 804 additions and 0 deletions

72
README.txt Normal file
View File

@ -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 <jadedctrl@teknik.io>
Sauce is at https://git.eunichx.us/unichat

155
gendl Executable file
View File

@ -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

27
ucgen.sh Normal file
View File

@ -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

65
uclib/255color.sh Normal file
View File

@ -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
}

150
uclib/8color.sh Executable file
View File

@ -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"
}

132
uclib/ansi.sh Executable file
View File

@ -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
}

43
uclib/usernames.sh Executable file
View File

@ -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"

160
unichat.sh Executable file
View File

@ -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="<html><head><title>Unichat</title></head><body>"
footer="</body></html>"
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