Add talk.js drop-in replacement for slack.js

Change-Id: Ida234ebe9caa1b8c5a739f3a21856cdfabb1e33e
diff --git a/bin/talk.sh b/bin/talk.sh
new file mode 100755
index 0000000..b00109e
--- /dev/null
+++ b/bin/talk.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+# Default values
+NC_URL="${NC_TALK_URL:-https://cloud.ids-mannheim.de}"
+CONVERSATION="${NC_TALK_CONVERSATION:-o6toyqx7}"
+SECRET="${NC_TALK_SECRET}"
+MESSAGE=""
+DEBUG=false
+SILENT=false
+
+# Function to display help
+show_help() {
+    cat << EOF
+Usage: $(basename "$0") [OPTIONS] [message]
+
+Sends <message> to a Nextcloud Talk room. Use - for reading message from stdin
+
+Options:
+    -h, --help                    Show this help message
+    -d, --debug                   Output extra debugging
+    -c, --conversation <token>    Send message to conversation (default: o6toyqx7)
+    -s, --secret <secret>         Bot secret
+    -u, --url <url>               Nextcloud URL (default: https://cloud.ids-mannheim.de)
+    --silent                      Send message silently (no notification)
+
+Environment variables:
+    NC_TALK_URL             Nextcloud URL
+    NC_TALK_CONVERSATION    Conversation token
+    NC_TALK_SECRET          Bot secret
+
+EOF
+    exit 0
+}
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        -h|--help)
+            show_help
+            ;;
+        -d|--debug)
+            DEBUG=true
+            shift
+            ;;
+        -c|--conversation)
+            CONVERSATION="$2"
+            shift 2
+            ;;
+        -s|--secret)
+            SECRET="$2"
+            shift 2
+            ;;
+        -u|--url)
+            NC_URL="$2"
+            shift 2
+            ;;
+        --silent)
+            SILENT=true
+            shift
+            ;;
+        -*)
+            echo "Unknown option: $1" >&2
+            show_help
+            ;;
+        *)
+            MESSAGE="$1"
+            shift
+            ;;
+    esac
+done
+
+# Check if we should read from stdin (before consuming stdin)
+if [[ -z "$MESSAGE" ]] || [[ "$MESSAGE" == "-" ]]; then
+    if [[ "$DEBUG" == true ]]; then
+        echo "Reading from stdin" >&2
+    fi
+    # Read from stdin and wrap in code blocks like slack.js
+    MESSAGE=$'```\n'"$(cat)"$'\n```'
+fi
+
+# Check required parameters
+if [[ -z "$CONVERSATION" ]]; then
+    echo "Error: Conversation token is required. Use -c/--conversation option or set NC_TALK_CONVERSATION environment variable." >&2
+    exit 1
+fi
+
+if [[ -z "$SECRET" ]]; then
+    echo "Error: Bot secret is required. Use -s/--secret option or set NC_TALK_SECRET environment variable." >&2
+    exit 1
+fi
+
+if [[ -z "$MESSAGE" ]]; then
+    echo "Error: Message is required." >&2
+    exit 1
+fi
+
+if [[ "$DEBUG" == true ]]; then
+    echo "URL: $NC_URL" >&2
+    echo "Conversation: $CONVERSATION" >&2
+    echo "Message: $MESSAGE" >&2
+    echo "Silent: $SILENT" >&2
+fi
+
+# Generate a random header and signature
+RANDOM_HEADER=$(openssl rand -hex 32)
+MESSAGE_TO_SIGN="${RANDOM_HEADER}${MESSAGE}"
+SIGNATURE=$(echo -n "${MESSAGE_TO_SIGN}" | openssl dgst -sha256 -hmac "${SECRET}" | cut -d' ' -f2)
+
+# Escape the message for JSON (replace backslashes, quotes, and newlines)
+MESSAGE_ESCAPED=$(echo -n "$MESSAGE" | jq -Rs .)
+
+# Send the message
+curl -X POST \
+"${NC_URL}/ocs/v2.php/apps/spreed/api/v1/bot/${CONVERSATION}/message" \
+  -H "Content-Type: application/json" \
+  -H "Accept: application/json" \
+  -H "OCS-APIRequest: true" \
+  -H "X-Nextcloud-Talk-Bot-Random: ${RANDOM_HEADER}" \
+  -H "X-Nextcloud-Talk-Bot-Signature: ${SIGNATURE}" \
+  -d '{"message":'"${MESSAGE_ESCAPED}"',"silent":'"$SILENT"'}'
+