239 lines
6.8 KiB
Bash
Executable File
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/&/&/g' \
|
|
-e 's/</\</g' \
|
|
-e 's/>/\>/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
|