#!/bin/bash #comchat.sh - very lazy terminal client for Chat@Heyuri #this program has become substantial enough that I added license terms #but said terms are basically just "leave my fucking name on it lmao" #Copyright (c) 2026 miredo # #Permission is hereby granted, free of charge, to any person obtaining a #copy of this software and associated documentation files (the "Software"), #to deal in the Software without restriction, including without limitation #the rights to use, copy, modify, merge, publish, distribute, sublicense, #and/or sell copies of the Software, and to permit persons to whom the #Software is furnished to do so, subject to the following conditions: # #The above copyright notice and this permission notice shall be included in #all copies or substantial portions of the Software. # #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL #THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #DEALINGS IN THE SOFTWARE. #TODO list: # * sound effect for new posts # * kaomoji selector # * eventually, rewrite in Python but I dunno if I care enough to bother #to allow for extreme laziness, I just load settings from individual files #too lazy to bother doing the user color version="4.6a" settingspath="$HOME"/.config/mrd_comchat refresh_time=30 user_color=15 #set your color here, 1-15 my_trip="" user_agent="$(curl --version | awk '{print $1"/"$2;exit}') comchat.sh/$version" #very dumb hack because curl doesn't give you a nice way to just get the version number msg_raw="" msg_old="" new_msg=false #grabs data for settings #technically, this just echoes the contents and strips newlines #usage: grabfile filename #it returns 1 on error grabdata() { if [ ! -f "$1" ] then return 1 fi tr -d '\n' < "$1" return 0 } #strip out excess keypresses cleanbuffer() { while read -t 0 do read -N 1 -s done } #reset all colors reset_col() { echo -e -n "\033[0m" } #show the full scrollback check_scrollback() { echo "$msg_raw" | fold -w `tput cols` -s | less } #write settings to a file #this doesn't check for errors, too lazy #if you can't write a handful of bytes to a text file in $HOME you have #bigger issues lol save_settings() { reset_col clear mkdir -p "$settingspath"/ #back up files cp "$settingspath"/username username.old cp "$settingspath"/tripcode tripcode.old #write echo "$username" > "$settingspath"/username echo "$my_trip" > "$settingspath"/tripcode echo "Wrote settings." sleep 1 } #set the display color #usage: set_col color bold #color 30-37: blk, red, grn, ylw, blu, mag, cyn, wht #40-47 set the background color #bold is 1 or 0 set_col() { echo -e -n "\033[$2;$1m" } #read in the tripcode set_tripcode() { reset_col IFS= read -p "tripcode (optional): " -e -r my_trip } #read in the username set_username() { reset_col IFS= read -p "username: " -e -r username } #read in the update interval set_interval() { reset_col IFS= read -p "update interval (min 15, default 30): " -e -r refresh_time refresh_time=$(($refresh_time)) if (( refresh_time < 15 )) then refresh_time=15 fi } #sends a message via cURL send_msg() { reset_col IFS= read -p "message: " -e -r mymsg curl -s \ --user-agent "$user_agent" \ --data-urlencode "mode=regist" \ --data-urlencode "name=$username" \ --data-urlencode "email=" \ --data-urlencode "password=$my_trip" \ --data-urlencode "comment=$mymsg" \ --data-urlencode "face=" \ --data-urlencode "color=$user_color" \ --data-urlencode "retime=0" \ --data-urlencode "lines=1" \ --data-urlencode "autoclear=on" \ https://cgi.heyuri.net/chat/comchat.cgi > /dev/null } #shows the help show_help() { reset_col clear set_col 36 1 echo "command keys:" reset_col echo "q, Q - quit" echo "? - show this help message" echo "/ - send a message (leave blank to cancel) [refreshes]" echo "r, space - refresh the chat [refeshes]" echo "p, ; - view the chat scrollback (q exits scrollback)" echo "#, T - set your tripcode" echo "N - set your name" echo "S - write your name and tripcode to disk (auto-loads on start)" echo "i - set the update interval (min 15s) [refreshes]" echo set_col 36 1 echo "other notes:" reset_col echo "* refresh the chat if you change your terminal size" echo "* only the commands marked by [refreshes] will refresh, all" echo " other commands will not" echo "* all screens expect a minimum 80x24 terminal; you can get away" echo " with less, but things may not look right" echo set_col 32 1 echo "Press any key to continue." reset_col read -N 1 -s } #main program starts here reset_col clear #show intro text set_col 36 0 echo "miredo's very very lazy comchat client for Chat@Heyuri" echo "version $version" echo "user-agent: '$user_agent'" #get user info set_col 36 1 #grab username from file,ask otherwise temp="$(grabdata "$settingspath/username")" if [ $? -ne 0 ] then set_username else username="$temp" echo "Using username '$username'." fi #grab tripcode from file, ask otherwise temp="$(grabdata "$settingspath/tripcode")" if [ $? -ne 0 ] then set_tripcode else my_trip="$temp" echo "Loaded tripcode from file." fi echo #chat refresh info refresh=true refresh_date=never #main loop here while true do #get terminal size scr_w=`tput cols` scr_h=`tput lines` #load and format the message list reset_col #TODO: handle HTML entities somehow lol (or at least find and replace " and &) #TODO: strip all control characters - probably not ever going to be an issue, but there isn't a real reason to not do it for sanity's sake if [[ "$refresh" == "true" ]] then set_col 31 1 echo -n "[loading...]" cleanbuffer msg_old="$msg_raw" msg_raw="$( curl -s https://cgi.heyuri.net/chat/simplelog.txt) " if [[ "$msg_raw" != "$msg_old" ]] then new_msg=true fi msg="$( echo "$msg_raw" | fold -s -w $scr_w | head -n $(expr $scr_h - 4) )" refresh_date="$(date)" refresh=false fi #draw the main screen clear set_col 44 0 set_col 37 1 echo "[refeshed on $refresh_date | ($scr_w"x"$scr_h) | reload: $refresh_time"s"]" #display the messages reset_col #highlight new message/most recent #white if old, yellow if new #TODO: this is where I'd play a sound too if [[ "$new_msg" == "true" && "$show_update" == "true" ]] then set_col 33 1 else set_col 37 1 fi new_msg=false show_update=false echo "$msg" | head -n 1 #dumb hack, highlights the first line reset_col echo "$msg" | tail -n +2 set_col 44 0 set_col 37 1 echo "keys: q-quit, /-send, r-refresh, ?-help" reset_col #handle user commands read -t $refresh_time -N 1 -s inp case "$inp" in r | "" | " ") #refresh refresh=true show_update=true ;; q | Q) #quit clear exit 1 ;; "/") #post send_msg refresh=true show_update=false ;; p | s | ";") #view whole scrollback of posts check_scrollback ;; h | "?") #show help show_help ;; T | "#") #set tripcode set_tripcode ;; N) #set username set_username ;; i) #set update interval set_interval refresh=true show_update=true ;; S) #write username and trip to files save_settings ;; esac cleanbuffer if [[ "$refresh" == "true" ]] then set_col 33 1 echo -n "[refreshing...] " #minimum time so we don't hammer the site with a bunch of requests #lowered it from before to improve responsiveness sleep 0.5 fi reset_col done