shi/shi/shi.sh

239 lines
6.8 KiB
Bash
Executable File

#!/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 <https://www.gnu.org/licenses/>.
#
# 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/&/&amp;/g' \
-e 's/</\&lt;/g' \
-e 's/>/\&gt;/g' \
-e 's/\([@\#$%^&*()~-=_+:;{}\[,.?\/]\)/\\\1/g' "$1"/content)
POSTTEXT=$(echo $POSTTEXT | sed -e ':a;N;$!ba;s/\n/<br>/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 "<!--BEGIN REPLY [0-9]*-->" "$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 "<!--BEGIN REPLY [0-9]+-->" \
| tail -n 1 \
| sed 's/^.* \([0-9]\+\).*$/\1/g')
echo "First reply: $FIRSTREPLY" >> $LOG
POSTHTML=$(sed -e ':a' -e 'N' -e '$!ba' \
-e "s/.*\(<!--BEGIN OP POST $POSTNUM-->.*<!--END OP POST $POSTNUM-->\).*/\1/g" \
-e "s/<!--BEGIN REPLY [0-9]\+-->.*<!--END REPLY $FIRSTREPLY-->//g" \
"$POSTDIR"/index.html)
else
POSTHTML=$(sed -e ':a' -e 'N' -e '$!ba' \
-e "s/.*\(<!--BEGIN OP POST $POSTNUM-->.*<!--END OP POST $POSTNUM-->\).*/\1/g" \
"$POSTDIR"/index.html)
fi
sed -i \
-e ':a' \
-e 'N' \
-e '$!ba' \
-e "s/<!--BEGIN OP POST $POSTNUM-->.*<!--END OP POST $POSTNUM-->//g" "$BOARDDIR"/index.html
TEMPFILE=$(mktemp)
while read -r line
do
if echo "$line" | grep -q "<!--BEGIN POSTS-->"
then
printf "\t\t<!--BEGIN POSTS-->\n%s\n" "$POSTHTML"
#test -z $(find $POSTDIR/* -type d) || \
#printf "\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<!--END OP POST %s-->\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 "<!--END REPLIES $PARENT-->"
then
newPost "$post" "reply"
printf "\t\t\t\t\t\t<!--END REPLIES %s-->\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 "<!--BEGIN POSTS-->"
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