From 0d2564cf6c13fb22ba732c6d7b702de4fbae5590 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lihl?= <lukas.lihl@unicorn.com>
Date: Wed, 24 Apr 2024 13:47:14 +0200
Subject: [PATCH 1/2] added discord webhook

---
 discord-variables.sh                |   8 +
 discord-webhook-data-limit-check.sh | 218 ++++++++++++++++++++++++++++
 discord-webhook.sh                  | 191 ++++++++++++++++++++++++
 3 files changed, 417 insertions(+)
 create mode 100755 discord-variables.sh
 create mode 100755 discord-webhook-data-limit-check.sh
 create mode 100755 discord-webhook.sh

diff --git a/discord-variables.sh b/discord-variables.sh
new file mode 100755
index 0000000..1ffb704
--- /dev/null
+++ b/discord-variables.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/bash
+
+DISCORD_TOKEN=
+DISCORD_ID=
+DISCORD_USER=BASH
+DISCORD_AVATAR_URL=
+DISCORD_ROLE_ID=
+
diff --git a/discord-webhook-data-limit-check.sh b/discord-webhook-data-limit-check.sh
new file mode 100755
index 0000000..91ec1cc
--- /dev/null
+++ b/discord-webhook-data-limit-check.sh
@@ -0,0 +1,218 @@
+#!/bin/bash
+
+#### SCRIP USAGE FUNCTION ####
+
+# Usage function.
+usage() {
+    echo ""
+    echo "Usage: $0 [OPTIONS]"
+    echo ""
+    echo "Options:"
+    echo "  -m, --message <json-content>  The Discord webhook message JSON to be checked."
+    echo "  -d, --debug                   Turns on console output"
+    echo "  -h, --help                    Show this help message and exit."
+    echo ""
+    echo "This script will check a Discord webhook message JSON string against content"
+    echo "limits set by Discord. The message data must be within the limits in order"
+    echo "to be successfully sent. The script will return an exit number based on the"
+    echo "results of the check."
+    echo ""
+    echo " 0) The message data is within the limimts."
+    echo " 1) The message data is outside limits, but can be sent in multiple messages."
+    echo " 2) The message data is outside limits and cannot be sent."
+    echo ""
+    echo "Refer to Discord Webook documentation for more details on the webhook limits:"
+    echo ""
+    echo "  https://birdie0.github.io/discord-webhooks-guide/other/field_limits.html"
+    echo ""
+}
+
+#### PARSE ARGUMENTS ####
+
+# Parsed from command line arguments.
+while [[ $# -gt 0 ]]; do
+    case "$1" in
+        -m|--message)
+            jsonMessage="$2"
+            shift 2
+            ;;
+        -d|--debug)
+            debug=true
+            shift
+            ;;
+        -h|--help)
+            usage
+            exit 0
+            ;;
+        *)
+            echo "Invalid option: $1" >&2
+            usage
+            exit 2
+            ;;
+    esac
+done
+
+# Check if JSON is provided and not empty
+if [ -z "${jsonMessage}" ]; then
+    echo "Error: The --message option is mandatory." >&2
+    usage
+    exit 2
+fi
+
+#### INITIALIZATION & PARAMETERS ####
+
+# Character lenght limits & object count limits (the order is important!)
+limits=(
+    'Username       .username                   80      char    1'
+    'Content        .content                    2000    char    1'
+    'Embeds         .embeds                     10      obj     0'
+    'Author         .embeds[].author.name       256     char    1'
+    'Title          .embeds[].title             256     char    1'
+    'Description    .embeds[].description       1024    char    1'
+    'Fields         .embeds[].fields            25      obj     1'
+    'Name           .embeds[].fields[].name     256     char    1'
+    'Value          .embeds[].fields[].value    1024    char    1'
+    'Footer         .embeds[].footer.text       2048    char    1'
+    'Totals         na                          6000    char    1'
+    'Total          na                          6000    char    0'
+)
+
+# Set limit parameter names
+limitParameters="name section value type critical count"
+
+# Initialize result variables
+criticalResult=false
+outsideLimits=false
+results=""
+totalCharactersAllEmbeds=0
+
+#### LIMIT CHECK & RESULTS FUNCTION ####
+
+# Get count, check against limit and update results
+function updateResults() {
+
+    local indexedSection="$1"
+
+    # Get the object/character count if section is an object
+    [ "${indexedSection}" != "na" ] && count=$(jq "$indexedSection | length" <<< "${jsonMessage}")
+
+    # Output info if debug enabled
+    [ ${debug} ] && echo "${name}: ${count} / ${value}" >&2
+
+    # Compare count with limit value
+    if [[ ${count} -gt ${value} ]]; then
+
+        # Set 'outside limit' flag
+        outsideLimits=true
+
+        # Check if limit is a critical one
+        if [ "${critical}" == "1" ]; then
+
+            # Set 'critical limit' flag
+            criticalResult=true
+
+        fi
+
+        # Append to result if outside limit
+        results+="${name} ${indexedSection} ${value} ${type} ${critical} ${count}\n"
+
+    fi
+
+}
+
+#### CHECK CONTENT ####
+
+# Check content agains each limit
+for limit in "${limits[@]}"; do
+
+    # Read parameters from limit
+    IFS=' ' read -r $limitParameters <<< "$limit"
+
+    # Check if limit relates to the embeds section
+    if [[ "${section}" == *"embeds[]"* ]]; then
+
+        # Check each embed section individually for applicable limits
+        for (( i=0; i<$(jq ".embeds | length" <<< "${jsonMessage}"); i++ )); do
+
+            # Inject array index in embeds element for correct parsing
+            embedSection="${section/embeds[]/embeds[${i}]}"
+
+            # Check if section is a field section as this is an array
+            if [[ "${section}" == *"fields[]"* ]]; then
+
+                # Check each field section individually for applicable limits
+                for (( j=0; j<$(jq ".embeds[$i].fields | length" <<< "${jsonMessage}"); j++ )); do
+
+                    # Inject array index in fields element for correct parsing
+                    fieldSection="${embedSection/fields[]/fields[${j}]}"
+
+                    # Check limits and update results
+                    updateResults "${fieldSection}"
+
+                    # Add to total characters if character type
+                    [ "${type}" == "char" ] && ((embedTotals[$i]+=count))
+
+                done
+
+            else
+
+                # Check limits and update results
+                updateResults "${embedSection}"
+
+                # Add to total characters if character type
+                [ "${type}" == "char" ] && ((embedTotals[$i]+=count))
+
+            fi
+
+        done
+
+    elif [[ "${name}" == "Totals" ]]; then
+
+        # Read the total character count for each embed section
+        for count in "${embedTotals[@]}"; do
+
+            # Check agains limit and update result
+            updateResults "${section}" ${count}
+
+            # Add to the overall total character count
+            ((totalCharactersAllEmbeds+=count))
+
+        done
+
+    elif [[ "${name}" == "Total" ]]; then
+
+        # Get the total character count for all embeds
+        count=${totalCharactersAllEmbeds}
+
+        # Check agains limit and update result
+        updateResults "${section}" ${count}
+
+    else
+
+        # Check agains limit and update result
+        updateResults "${section}"
+
+    fi
+
+
+done
+
+#### RETURN RESULTS ####
+
+# Output results
+[ ${debug} ] && [ -n "${results}" ] && echo -e "${results%??}" >&2
+
+# Exit with appropriate status
+if ${criticalResult}; then
+
+    exit 2
+
+elif ${outsideLimits}; then
+
+    exit 1
+
+else
+
+    exit 0
+
+fi
\ No newline at end of file
diff --git a/discord-webhook.sh b/discord-webhook.sh
new file mode 100755
index 0000000..98e4653
--- /dev/null
+++ b/discord-webhook.sh
@@ -0,0 +1,191 @@
+#!/usr/bin/bash
+
+#### SET PATHS ####
+
+# Get path to where script is located.
+scriptPath=$(echo "${0%/*}")
+
+# Set other paths.
+limitCheckScrip=${scriptPath}/discord-webhook-data-limit-check.sh
+lastMessageFile=${scriptPath}/discord-webhook-last-message.json
+
+#### SCRIP USAGE FUNCTION ####
+
+# Usage function.
+usage() {
+    echo ""
+    echo "Usage: $0 [OPTIONS]"
+    echo ""
+    echo "Options:"
+    echo "  -c, --content <content>   Set the content of the Discord message."
+    echo "  -e, --embeds <embeds>     Set the embeds of the Discord message."
+    echo "  -f, --file <file-path>    Set the file attachment path (optional)."
+    echo "  -d, --debug               Turns on console output"
+    echo "  -h, --help                Show this help message and exit."
+    echo ""
+    echo "Refer to the Discord documentation for more information on Webhooks"
+    echo ""
+    echo "  https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks"
+    echo ""
+}
+
+### SEND WEBHOOK FUNCTION ###
+
+# Send Discord notification with or without payloaad.
+sendWebhook() {
+
+    local discordJsonData="$1"
+    local includeAttachment="$2"
+
+    # Write last message that was attmepted to be sent to file
+    echo "${discordJsonData}" > ${lastMessageFile}
+
+    # Check if attachment pathe exits and if is should be included in the message
+    if [ -z "${discordAttachmentPath}" ] || [ "${includeAttachment}" = "false" ]; then
+
+        # Send message without attachment
+        echo ${discordWebhookBase}"/"${discordID}"/"${discordToken}
+        echo "$discordJsonData"
+        response=$(curl -H "Content-Type: application/json" -d "$discordJsonData" ${discordWebhookBase}"/"${discordID}"/"${discordToken})
+
+    else
+
+        # Send message with attachment
+        response=$(curl -s -F payload_json="${discordJsonData}" -F "file1=@${discordAttachmentPath}" ${discordWebhookBase}"/"${discordID}"/"${discordToken})
+
+    fi
+
+    # Check if curl was successful
+    if [ $? -ne 0 ]; then
+        echo "Error: Failed to send webhook message." >&2
+        exit 1
+    fi
+
+    # Output curl reposnse if debug enabled
+    [ ${debug} ] && echo "${response}" >&2
+
+}
+
+#### PARSE ARGUMENTS ####
+
+# Parsed from command line arguments.
+while [[ $# -gt 0 ]]; do
+    case "$1" in
+        -c|--content)
+            discordMessageContent="$2"
+            shift 2
+            ;;
+        -e|--embeds)
+            discordMessageEmbeds="$2"
+            shift 2
+            ;;
+        -f|--file)
+            discordAttachmentPath="$2"
+            shift 2
+            ;;
+        -d|--debug)
+            debug=true
+            shift
+            ;;
+        -h|--help)
+            usage
+            exit 0
+            ;;
+        *)
+            echo "Invalid option: $1" >&2
+            usage
+            exit 1
+            ;;
+    esac
+done
+
+# Check if JSON is provided and not empty
+if [ -z "${discordMessageContent}" ] && [ -z "${discordMessageEmbeds}" ]; then
+    echo "Error: Either a message 'content' or message 'embed' is required." >&2
+    usage
+    exit 1
+fi
+
+#### DISCORD VARIABLES ####
+
+# Discord webhook address base.
+discordWebhookBase="https://discord.com/api/webhooks"
+
+# Import secret variables.
+source ${scriptPath}/discord-variables.sh
+
+# Discord secret variables.
+discordToken=${DISCORD_TOKEN}
+discordID=${DISCORD_ID}
+discordUsername=${DISCORD_USER}
+discordAvatarURL=${DISCORD_AVATAR_URL}
+discordRoleID=${DISCORD_ROLE_ID}
+
+#### REPLACE ROLES ####
+
+# Replace @admin mention with correct ID.
+discordMessageEmbeds=$(echo "${discordMessageEmbeds}" | sed 's/\@admin/\<\@\&'${discordRoleID}'/g')
+
+#### BUILD DISCORD MESSAGE ####
+
+# Complete the Discord JSON string.
+discordJson='{
+  "username":"'"${discordUsername}"'",
+  "content":"'"${discordMessageContent}"'",
+  "avatar_url":"'"${discordAvatarURL}"'",
+  "embeds": [ '${discordMessageEmbeds%?}' ]
+}'
+
+#### MESSAGE LIMIT CHECK & SEND ####
+
+# Call script to perform limit checks (pass on debug argument if debug enabled)
+${limitCheckScrip} -m "${discordJson}" ${debug:+-d}
+
+# Send full, split or drop message based in limit check
+case ${?} in
+
+    # Send full message
+    0)
+        # Output info if debug enabled
+        [ ${debug} ] && echo "Content within limits. Sending full webhook message." >&2
+
+        # Send full Json
+        sendWebhook "${discordJson}" true
+        ;;
+
+    # Split message in multiple webhooks
+    1)
+        # Output info if debug enabled
+        [ ${debug} ] && echo "Content to large, but within manageable limits. Splitting webhook message" >&2
+
+        # Remove embeds section
+        discordJsonMinusEmbeds=$(jq "del(.embeds)" <<< "${discordJson}")
+
+        # Send message without embeds
+        sendWebhook "${discordJsonMinusEmbeds}" true
+
+        # Get number of embeds in original message
+        embedsCount=$(jq ".embeds | length" <<< "${discordJson}")
+
+        # Send each embed as a separate message
+        for (( index=0; index<$embedsCount; index++ )); do
+
+            # Get current embed in embeds section
+            embed=$(jq ".embeds[$index]" <<< "${discordJson}")
+
+            # Replace embeds in orignal message with current single embed and remove content section
+            discordJsonSingleEmbed=$(jq ".embeds=[$embed] | del(.content)" <<< "${discordJson}")
+
+            # Send message with single embed and without the rest of the data
+            sendWebhook "${discordJsonSingleEmbed}" false
+
+        done
+        ;;
+
+    # Drop message and exit with error
+    *)
+        echo "Error: Limit check failed or content outside manageable limits. Unable to send webhook." >&2
+        exit 1
+        ;;
+
+esac
\ No newline at end of file

From d5962e1d35f93a7e5f865d32c6446ceb5e5d0ec3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lihl?= <lukas.lihl@unicorn.com>
Date: Wed, 24 Apr 2024 14:06:46 +0200
Subject: [PATCH 2/2] added discord webhook

---
 .idea/.gitignore     |  8 ++++++++
 discord-variables.sh | 10 +++++-----
 2 files changed, 13 insertions(+), 5 deletions(-)
 create mode 100644 .idea/.gitignore

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/discord-variables.sh b/discord-variables.sh
index 1ffb704..c424531 100755
--- a/discord-variables.sh
+++ b/discord-variables.sh
@@ -1,8 +1,8 @@
 #!/usr/bin/bash
-
-DISCORD_TOKEN=
-DISCORD_ID=
-DISCORD_USER=BASH
-DISCORD_AVATAR_URL=
+#https://discord.com/api/webhooks/1232659205496897587/DsnlhTJhtLGqNhLISYdBzaKFKSekH9MBwWN_ZYCgS9Su-0H9MD6-Psyl9wn88THs6Tz6
+DISCORD_TOKEN="DsnlhTJhtLGqNhLISYdBzaKFKSekH9MBwWN_ZYCgS9Su-0H9MD6-Psyl9wn88THs6Tz6"
+DISCORD_ID=1232659205496897587
+DISCORD_USER="Obědovník"
+DISCORD_AVATAR_URL="https://zspraskacka.cz/wp-content/uploads/2022/07/jidlo.png"
 DISCORD_ROLE_ID=