#!/bin/sh # shi - an imageboard in POSIX shell, using the gnu coreutils # Copyright (C) 2018 oneseveneight # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # TODO: Banners # TODO: Return post number on posting # TODO: Post info only links top posts on boards page # TODO: Shellcheck # TODO: Handling of tar files that are too large or malformed # TODO: Pages # TODO: Implement http server within shi IFS='' LOG=log.txt TEMPLATEDIR="templates" alias echo='echo [shi.sh]:' newPost() { POSTTYPE=$2 POSTNUM=$(basename "$1") DATE=$(date -Ru) USER=$(cat "$1"/user) POSTTEXT=$(sed -e 's/&/&/g' \ -e 's//\>/g' \ -e 's/\([@\#$%^&*()~-=_+:;{}\[,.?\/]\)/\\\1/g' "$1"/content) POSTTEXT=$(echo $POSTTEXT | sed -e ':a;N;$!ba;s/\n/
/g') POSTTITLE=$(cat "$1"/title) echo "Creating post" > $LOG for f in "$1"/*.jpg "$1"/*.jpeg "$1"/*.png "$1"/*.gif do test -f $f && IMAGEPATH=$f done if test -f "$IMAGEPATH" then echo "Found image at $IMAGEPATH" >> $LOG IMAGENAME=$(basename "$IMAGEPATH") IMAGESIZE=$(du -sh "$IMAGEPATH"| cut -f 1 -d ' ') DIR=$(pwd | sed 's/\//\\\//g') THUMBPATH=$(echo "$IMAGEPATH" | sed -e 's/\..*$/_thumb\.jpeg/') if echo "$IMAGEPATH" | grep '.gif' then echo "Image is a gif" >> $LOG convert "$IMAGEPATH"'[0]' "$THUMBPATH" # If image is a gif, take the first frame else echo "Image is static" >> $LOG convert "$IMAGEPATH" "$THUMBPATH" # Convert the image to a jpeg fi convert "$THUMBPATH" -define jpeg:extent=100kb "$THUMBPATH" #Resizes the copy to < 100kb IMAGEPATH=$(echo "$IMAGEPATH" | sed -e "s/$DIR//" -e 's/\//\\\//g') THUMBPATH=$(echo "$THUMBPATH" | sed -e "s/$DIR//" -e 's/\//\\\//g') else echo "No image found" >> $LOG IMAGENAME="" IMAGESIZE="" IMAGEPATH="" fi if test -n "$IMAGENAME" then echo "Generating an image post" >> $LOG TEMPLATE=$TEMPLATEDIR/$POSTTYPE.template while read -r line do echo "$line" | sed -e "s/{{{ POSTNUM }}}/$POSTNUM/g" \ -e "s/{{{ DATE }}}/$DATE/g" \ -e "s/{{{ USER }}}/$USER/g" \ -e "s/{{{ POSTTITLE }}}/$POSTTITLE/g" \ -e "s/{{{ POSTTEXT }}}/$POSTTEXT/g" \ -e "s/{{{ IMAGEPATH }}}/$IMAGEPATH/g" \ -e "s/{{{ THUMBPATH }}}/$THUMBPATH/g" \ -e "s/{{{ IMAGENAME }}}/$IMAGENAME/g" \ -e "s/{{{ IMAGESIZE }}}/$IMAGESIZE/g" done < "$TEMPLATE" else echo "Generating a text post" >> $LOG TEMPLATE=$TEMPLATEDIR/$POSTTYPE-noimage.template while read -r line do echo "$line" | sed -e "s/{{{ POSTNUM }}}/$POSTNUM/g" \ -e "s/{{{ USER }}}/$USER/g" \ -e "s/{{{ DATE }}}/$DATE/g" \ -e "s/{{{ POSTTITLE }}}/$POSTTITLE/g" \ -e "s/{{{ POSTTEXT }}}/$POSTTEXT/g" done < "$TEMPLATE" fi } addPostToBoard() { POSTDIR="$1" POSTNUM="$(basename $POSTDIR)" BOARDDIR="$(dirname $POSTDIR)" REPLYNUM=$(grep -E "" "$POSTDIR"/index.html | wc -l) echo "Adding post to board" >> $LOG echo "Found $REPLYNUM replies" >> $LOG if [ $REPLYNUM -gt '4' ] then echo "More than 4 replies found, trimming" >> $LOG FIRSTREPLY=$(tac "$POSTDIR"/index.html \ | grep -Em5 "" \ | tail -n 1 \ | sed 's/^.* \([0-9]\+\).*$/\1/g') echo "First reply: $FIRSTREPLY" >> $LOG POSTHTML=$(sed -e ':a' -e 'N' -e '$!ba' \ -e "s/.*\(.*\).*/\1/g" \ -e "s/.*//g" \ "$POSTDIR"/index.html) else POSTHTML=$(sed -e ':a' -e 'N' -e '$!ba' \ -e "s/.*\(.*\).*/\1/g" \ "$POSTDIR"/index.html) fi sed -i \ -e ':a' \ -e 'N' \ -e '$!ba' \ -e "s/.*//g" "$BOARDDIR"/index.html TEMPFILE=$(mktemp) while read -r line do if echo "$line" | grep -q "" then printf "\t\t\n%s\n" "$POSTHTML" #test -z $(find $POSTDIR/* -type d) || \ #printf "\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n" "$POSTNUM" else echo "$line" fi done < "$BOARDDIR"/index.html > "$TEMPFILE" cat "$TEMPFILE" > "$BOARDDIR"/index.html } addNewPost() { post="$1" if basename "$post" | grep -qE "[0-9]$" && [ "$(basename "$post")" -gt "$2" ] then TEMPFILE=$(mktemp) if dirname "$post" | grep -qE "[0-9]*+/[0-9]*$" # If reply generate a reply then echo "Post type: reply" > $LOG PARENT=$(dirname "$post" | sed 's/^.*\/\([0-9]\+\)/\1/') while read -r line do if echo "$line" | grep -q "" then newPost "$post" "reply" printf "\t\t\t\t\t\t\n" "$PARENT" else echo "$line" fi done < "$post/../index.html" > "$TEMPFILE" cat "$TEMPFILE" > "$post/../index.html" addPostToBoard "$(dirname "$post")" else # Else generate an op post echo "Post type: OP post" >> $LOG while read -r line do echo "$line" if echo "$line" | grep -q "" then newPost "$post" "oppost" fi done < "$(dirname "$post")/index.html.template" > "$TEMPFILE" cat "$TEMPFILE" > "$post"/index.html rm "$TEMPFILE" addPostToBoard "$post" fi fi } update() { echo "Posting started at $(date -u)" >> $LOG find "$1" | while read -r post do addNewPost "$post" done echo $(( $2 + 1 )) > ./latest echo "Posting finished at $(date -u)" >> $LOG } INBOX="inbox/" while nc -lp 7070 | tar -x -C $INBOX || rm -rf $INBOX/* do for dir in $INBOX* do echo "Received post" >> $LOG REPLY=$(basename "$dir" | sed 's/-.*//g') LATEST=$(cat "./latest") if echo "$REPLY" | grep -qE "[0-9]$" then PARENT=$(find ./ -maxdepth 3 -name "$REPLY" -not -path '*/\.*') PARENT=$(dirname "$PARENT") BOARD=$(realpath "$PARENT") else PARENT="./boards" BOARD=$(realpath "$PARENT"/"$REPLY") fi if [ -d "$PARENT/$REPLY" ] then IMAGE=$(echo "$dir"/* | tr ' ' '\n' |grep -E '(png|jpg|gif)' | head -n 1) mkdir "$PARENT/$REPLY"/$(( LATEST + 1 )) NEW_POST_DIR="$PARENT/$REPLY"/$(( LATEST + 1 )) cp "$IMAGE" "$NEW_POST_DIR" >/dev/null 2>&1 cut -c -80 "$dir/title" > "$NEW_POST_DIR"/title cut -c -2000 "$dir/content" > "$NEW_POST_DIR"/content cut -c -20 "$dir/user" > "$NEW_POST_DIR"/user cp "$NEW_POST_DIR"/../main.css $NEW_POST_DIR rm -rf "$dir" update "$BOARD" "$LATEST" else rm -rf "$dir" fi done done