commit b5d1efbbc00afcc9294784d3d94f07c01e5ecd3c Author: Jaidyn Ann Date: Tue May 31 19:56:34 2022 -0500 Init diff --git a/README.md b/README.md new file mode 100644 index 0000000..6f79a66 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# librejam-omnom + +Librejam omnom is a simple script for accepting game jam submissions over IRC, +with git links or direct archive links. + +It requires `ii-ssl`, `git`, `curl`, and potentially others. bashisms are +avoided. + +To run, edit the `librejam-irc`, substituting in relative path and jam +information, then simply do… + +`$ sh librejam-irc` + +… everything should be good. diff --git a/librejam_certainty b/librejam_certainty new file mode 100755 index 0000000..4176bba --- /dev/null +++ b/librejam_certainty @@ -0,0 +1,9 @@ +#!/bin/sh + +if ps ax | grep ii | grep -v grep > /dev/null; then + exit 0 +else + >&2 echo "ii isn't running, let's restart things…" + pkill ii + pkill librejam_irc_ +fi diff --git a/librejam_gemini b/librejam_gemini new file mode 100755 index 0000000..c408885 --- /dev/null +++ b/librejam_gemini @@ -0,0 +1,95 @@ +#!/bin/sh +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Name: librejam_gemini +# Desc: Creates a gemini page for a game-jam entry. +# Reqs: librejam_gemini +# Date: 2022-03-30 +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +sanitize() { + sed 's% %-%g' \ + | tr 'A-Z' 'a-z' \ + | sed 's% $%%' +} + +get_release_git() { + pushd "$SUBMISSIONS_ROOT/$OUTNAME/" + git clone "$URL" "release" + if test "$?" -ne 0; then + popd + exit 1 + fi + + pushd "release/" + git checkout "$BRANCH" + if test "$?" -ne 0; then + popd + rm -rf release/ + popd + exit 2 + fi + + popd + tar -czvf release.tar.gz release/ + rm -rf release/ + popd +} + + +get_release_curl() { + local suffix="$(echo "$URL" | sed 's%.*\.%%')" + if echo "$suffix" | grep "/"; then + suffix="raw" + fi + + local out_path="$SUBMISSIONS_ROOT/$OUTNAME/release.$suffix" + + curl -o "$out_path" "$URL" + if test "$?" -ne 0; then + exit 3 + fi + + OUTLEAF="$(basename "$out_path")" +} + +average_rating() { + SUM="$(awk '{print $2}' "$RATINGS_FILE" | tr '\n' '+' | sed 's%+$%%')" + COUNT="$(wc -l "$RATINGS_FILE" | awk '{print $1}')" + echo "($SUM) / $COUNT" \ + | bc +} + + +SENDER="$1" +URL="$2" +BRANCH="$3" +NAME="$4" +SUBMISSIONS_ROOT="$5" +RATINGS_FILE="$6" + +OUTNAME="$(echo "$NAME" | sanitize)" +OUTLEAF="release.tar.gz" + +if test -z "$RATINGS_FILE" -a "$BRANCH" = ":curl"; then + get_release_curl > /dev/null +elif test -z "$RATINGS_FILE" -a -n "$BRANCH"; then + get_release_git > /dev/null +fi + +echo "# $NAME - By $SENDER" +echo "=> $OUTLEAF Submitted version" +echo "=> $URL Upstream source" + +if test -n "$RATINGS_FILE" -a -e "$RATINGS_FILE"; then + echo "" + echo "## Ratings" + echo "* Average score: $(average_rating)" + + awk '{ printf("* %s: [%s] ", $1, $2); + for(i = 1; i <= NF; i++) + if (i > 2) + printf($i" "); + print "" }' \ + "$RATINGS_FILE" \ + | sed 's% $%%' +fi diff --git a/librejam_irc b/librejam_irc new file mode 100755 index 0000000..5ac3ebb --- /dev/null +++ b/librejam_irc @@ -0,0 +1,51 @@ +#!/bin/sh +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Name: librejam_irc +# Desc: A game-jam chatbot, using ii to connect to IRC. You need to edit the +# hard-coded variables at the start of this script. +# Reqs: librejam_irc_process, ii-ssl +# Date: 2022-05-31 +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +IRC_DIR="irc" +SERVER="leagueh.xyz" +ROOM="#librejam" +NICK="omnom" +NAME="Mx. Omnom" +PASS="" +SUBMISSIONS_DIR="/GEMINI/DOMAIN/librejam/2022-06/" +SUBMITTING_ENDS="2022-06-15 01:00" +RATING_ENDS="2022-06-21 23:59" + +connect() { + mkdir -p "$IRC_DIR" + + pkill ii + ii -i "$IRC_DIR" -s "$SERVER" -e ssl -n "$NICK" -k "$PASS" -f "$NAME" & + sleep 5 + + if test ! -d "$IRC_DIR/$SERVER"; then + >&2 echo "Failed to connect to $SERVER! Might want to try 'ii' manually." + pkill ii + exit 2; + fi + + echo "/j $ROOM" \ + > "$IRC_DIR/$SERVER/in" + if test ! -e "$IRC_DIR/$SERVER/$ROOM/in"; then + >&2 echo "Failed to join $ROOM! Maybe check $IRC_DIR manually?" + exit 3; + fi +} + + +while true; do + connect + + tail --lines=0 --follow "$IRC_DIR/$SERVER/$ROOM/out" "$IRC_DIR/$SERVER/out" \ + | librejam_irc_process "$NICK" "$SUBMISSIONS_DIR" "$SUBMITTING_ENDS" "$RATING_ENDS" \ + > "$IRC_DIR/$SERVER/$ROOM/in" + + # If ii's disconnected, let's take a pause before restarting. + sleep 5; +done diff --git a/librejam_irc_process b/librejam_irc_process new file mode 100755 index 0000000..6a01c11 --- /dev/null +++ b/librejam_irc_process @@ -0,0 +1,345 @@ +#!/bin/sh +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Name: librejam_irc_process +# Desc: Part of a game-jam chatbot. Processes lines of `ii` output from stdin +# as chat commands. Outputs text to be sent to the chatroom. +# Should probably not be run manually, but instead by librejam_irc. +# Reqs: librejam_gemini +# Date: 2022-03-30 +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +line_date() { + sed 's% .*%%' +} + +line_sender() { + line_sanitize \ + | awk '{print $3}' \ + | tr -d '<>' +} + +line_message() { + line_sanitize \ + | after_column 3 +} + +line_command() { + line_message \ + | awk '{print $1}' \ + | grep '^!' +} + +line_args() { + line_message \ + | after_column 1 +} + +line_sanitize() { + tr -d '$`{}^%\\' +} + +after_column() { + local column_no="$1" + cut -sd ' ' -f "$((column_no+1))"- +} + +ensure_file() { + local path="$1" + touch "$path" + if test ! -e "$path"; then + >&2 echo "${path} cannot be created; do you have write permission for this directory?" + return 3 + elif test ! -w "$path" -o ! -r "$path"; then + >&2 echo "${path} is either not readable or not writible-- please check your permissions." + return 3 + fi +} + +ensure_directory() { + local path="$1" + mkdir -p "$path" + if test ! -d "$path"; then + >&2 echo "$path isn't an accessible directory." + return 2 + fi +} + +remove_line() { + local path="$1" + local line="$2" + local tmp="$(mktemp)" + + grep -v "$line" "$path" \ + > "$tmp" + + cat "$tmp" \ + > "$path" + + echo "$line" \ + >> "$path.old" +} + +sanitize() { + sed 's% %-%g' \ + | tr 'A-Z' 'a-z' \ + | sed 's% $%%' +} + +init_gemini() { + local sender="$1"; local url="$2"; local branch="$3"; local name="$4" + local outname="$(echo "$name" | sanitize)" + + librejam_gemini "$sender" "$url" "$branch" "$name" "$SUBMISSIONS_DIR" \ + "$ratings_path" \ + > "$SUBMISSIONS_DIR/${outname}/${outname}.gmi" +} + +update_gemini() { + local sender="$1"; local url="$2"; local branch="$3"; local name="$4" + local ratings_path="$5" + local outname="$(echo "$name" | sanitize)" + ensure_directory "$SUBMISSIONS_DIR/${outname}/" + ensure_directory "$(dirname "$ratings_path")" + + librejam_gemini "$sender" "$url" "$branch" "$name" "$SUBMISSIONS_DIR" \ + "$ratings_path" \ + > "$SUBMISSIONS_DIR/${outname}/${outname}.gmi" + case "$?" in + 0) return 0 ;; + 1) echo "$sender: I had trouble cloning your git repo― did you give me the right URL?" ;; + 2) echo "$sender: Couldn't switch to the $branch branch― does $branch even exist?" ;; + 3) echo "$sender: Couldn't download the archive― did you give the right URL?" ;; + esac + return 2 +} + + +HELP_SUBMIT="!submit [-b branch] +. Submit a Librejam entry, either with a Git repository or archive over FTP/HTTP/etc. +. If submitting a Git repository, you must specify the branch with the -b +. argument. You can update your submission until the jam ends by re-running +. this command." +submit_cmd() { + local args="$1"; local sender="$2" + local entries="$SUBMISSIONS_DIR/entries.txt" + local url="$(echo "$args" | awk '{print $1}')" + local branch="$(echo "$args" | awk '{print $3}')" + local name="$(echo "$args" | after_column 3)" + + if test ! "$(echo "$args" | awk '{print $2}')" = "-b"; then + branch=":curl" + name="$(echo "$args" | after_column 1)" + fi + + ensure_file "$entries" + ensure_file "$entries.old" + if test "$SUBMITTING_ENDS" -le "$(date +%s)"; then + echo "$sender: Sorry, but the time for submissions is over!" + return + fi + + # Just in case they've already submitted + local prev_entry="$(grep "^$sender" "$entries")" + + if test -z "$prev_entry" -a -z "$name" -o -z "$url"; then + echo "$sender: Please provide all arguments to submit!" + return + fi + + # If they've already submitted, replace empty args with implied values + if test -z "$name" -a -n "$prev_entry"; then + name="$(echo "$prev_entry" | after_column 3)" + fi + if test -z "$branch" -a -n "$prev_entry"; then + branch="$(echo "$prev_entry" | awk '{print $3}')" + fi + if test -z "$url" -a -n "$prev_entry"; then + url="$(echo "$prev_entry" | awk '{print $2}')" + fi + + submit_game "$sender" "$prev_entry" "$url" "$branch" "$name" +} + +submit_game() { + local sender="$1"; local prev_entry="$2" + local url="$3"; local branch="$4"; local name="$5" + local entries="$SUBMISSIONS_DIR/entries.txt" + local outname="$(echo "$name" | sanitize)" + + update_gemini "$sender" "$url" "$branch" "$name" + + if test "$?" -eq 0; then + # Remove previous entry, if necessary + if test -n "$prev_entry"; then + remove_line "$entries" "$prev_entry" + fi + + echo "$sender $url $branch $name" \ + >> "$entries" + if test "$branch" = ":curl"; then + echo "$sender: $name has been submitted from archive!" + else + echo "$sender: $name has been submitted from git!" + fi + fi +} + + +HELP_RATE="!rate <1-10> [comment] +. Submit your rating on a given game, with an optional comment. If you rate +. a single game multiple times, the latest rating will be used." +rate_cmd() { + local args="$1"; local sender="$2" + local id="$(echo "$args" | awk '{print $1}')" + local rating="$(echo "$args" | awk '{print $2}')" + local comment="$(echo "$args" | after_column 2)" + local entries="$SUBMISSIONS_DIR/entries.txt" + + local now="$(date +%s)" + if test "$now" -le "$SUBMITTING_ENDS" -o "$now" -gt "$RATING_ENDS"; then + echo "$sender: Sorry, it's not time to rate!" + return + fi + if test "$rating" -lt 1 -o "$rating" -gt 10; then + echo "$sender: That's an invalid rating, sorry!" + return + fi + local entry_count="$(wc -l "$entries" | awk '{print $1}')" + if test "$id" -lt 1 -o "$id" -gt "$entry_count"; then + echo "$sender: That's… that's not an ID. Try below $entry_count." + return + fi + + local entry="$(awk 'NR=='"$id" "$entries")" + local outname="$(echo "$entry" | after_column 3 | sanitize)" + local ratings="$SUBMISSIONS_DIR/${outname}/ratings.txt" + ensure_directory "$(dirname "$ratings")" + ensure_file "$ratings" + + if test "$sender" = "$(echo "$entry" | awk '{print $1}')"; then + echo "$sender: … You can't rate your own game! xD" + return + fi + + local prev_rating="$(grep "^$sender" "$ratings" | head -1)" + if test -n "$prev_rating"; then + remove_line "$ratings" "$prev_rating" + fi + echo "$sender $rating $comment" \ + >> "$ratings" + + echo "$sender: Rating accepted!" + + update_gemini "$(echo "$entry" | awk '{print $1}')" \ + "$(echo "$entry" | awk '{print $2}')" \ + "$(echo "$entry" | awk '{print $3}')" \ + "$(echo "$entry" | after_column 3)" \ + "$ratings" +} + +HELP_LIST="!list +. List all games submitted for the jam." +list_cmd() { + local entries="$SUBMISSIONS_DIR/entries.txt" + + local index="1" + while read entry; do + if test -n "$entry"; then + local name="$(echo "$entry" | after_column 3)" + echo "$entry" \ + | awk '{ printf("[%s] %s | By %s | %s\n", + '"$index"', "'"$name"'", $1, $2) }' + index="$((index + 1))" + fi + done < "$entries" +} + + +HELP_ABOUT="!about +. … you could just try the command. It won't bite." +about_cmd() { + local sender="$2" + + echo "$sender: I'm a bot made for Librejam (gemini://leagueh.xyz/en/librejam)." + echo "My sauce is at https://github.com/jadedctrl/librejam-omnom/" + echo "Current submissions are at gemini://xwx.moe/librejam/" + echo "Submissions end at: $(date -ud @"$SUBMITTING_ENDS")" + echo "Rating ends at: $(date -ud @"$RATING_ENDS")" +} + + +HELP_HELP="!help +. … do I really have to explain this one? &2 echo "Usage: $(basename "$0") nick entry_dir submit_deadline rate_deadline" + exit 1 +fi +ensure_directory "$SUBMISSIONS_DIR" + +while read line; do + if echo "$line" | grep "^....-..-.. ..:.. Closing link" >/dev/null; then + >&2 echo "ii has disconnected!" + exit 2; + fi + + echo "$line" | grep "<$NICK>" > /dev/null + if test "$?" -ne 0; then + process_line "$line" + fi +done