'Either curl (and/) or Discord is not handling escapes properly (using BASH)

I'm trying to automate listing players in a game server to Discord using webhooks and curl.

Some variables are:

$PREPLAY defined as PREPLAY=__Currently Connected:__ this adds the text underlined

$MESSAGE defined as MESSAGE="Current Online Count: \"$NOWCOUNT\" (this works, but had to edit for stackoverflow markup)

$NOWCOUNT defined by other script (This also works)

$PLAYERS (the list of players) - I'll get more into this in a second

The line I'm using is:

curl -H "Content-Type: application/json" -X POST -d "{\"embeds\": [{ \"color\": \"45044\", \"description\": \"$PREPLAY$PLAYERS\", \"title\": \"$MESSAGE\" }]}" $URL

when I use:

PLAYERS=$(cat /tmp/players.list | sed '/Players connected/q' | egrep -v '^$' | egrep -v "^LOG" | sed -e 's/^-/\\\\\\n/')

The output in Discord comes out as

Notice the extra ""

Notice the extra "\"

Or if, I remove ONE "\" from the variable assignment above to be:

PLAYERS=$(cat /tmp/players.list | sed '/Players connected/q' | egrep -v '^$' | egrep -v "^LOG" | sed -e 's/^-/\\\\\n/')

I get a JSON error:

enter image description here

OK, removing TWO "/"s and the new-lines just don't work:

enter image description here



Solution 1:[1]

I understand the problem with PLAYERS variable generation.

Suggesting to debug with set -x and and set +x to inspect the variable:

set -x # enable debug trace
PLAYERS=$(cat /tmp/players.list | sed '/Players connected/q' | egrep -v '^$' | egrep -v "^LOG" | sed -e 's/^-/\\\\\n/')
echo "PLAYERS=$PLAYERS" # debug trace
set +x # disable debug trace

Suggesting to try test the PLAYERS command step by step:

PLAYERS1=$(sed '/Players connected/q' /tmp/players.list)
echo "PLAYERS1=$PLAYERS1" # debug trace

This should print /tmp/players.list all lines until found RegExp pattern /Players connected/

PLAYERS2=$(sed '/Players connected/q' /tmp/players.list| egrep -v '^([[:space:]]*$|LOG)')
echo "PLAYERS2=$PLAYERS2" # debug trace

This should print /tmp/players.list all lines until found RegExp pattern /Players connected/.

Filtering out empty lines, and Lines starting with LOG

PLAYERS3=$(sed '/Players connected/q' /tmp/players.list| egrep -v '^([[:space:]]*$|LOG)'| sed -e 's|^-|\\\\\n|')
echo "PLAYERS3=$PLAYERS3" # debug trace

This should print /tmp/players.list all lines until found RegExp pattern /Players connected/.

Filtering out empty lines, and Lines starting with LOG

And replacing lines starting with - to \\ followed by new line.

For example:

  line 1
  -line 2

Will transform:

  line 1
  \\
  line 2

If you want to concat the lines with \\n the command is:

PLAYERS4=$(sed '/Players connected/q' /tmp/players.list|egrep -v '^([[:space:]]*$|LOG)'| sed -z 's|\n-|\\\\n|')
echo "PLAYERS4=$PLAYERS4" # debug trace

For example:

  line 1
  -line 2

Will transform:

  line 1\\nline 2

It is possible to simplify/fold the sed commands and egrep command into single awk command.

PLAYERS5=$(awk '!/^([[:space:]]*$|LOG)/{sub("-","\\\\n");print $0}' ORS="" /tmp/players.list)
echo "PLAYERS5=$PLAYERS5" # debug trace

Once you have the desired PLAYERS list. Make sure you feed them correctly in JSON format.

Finally.

Suggesting to use jq command to prepare a valid JSON single-line string or an object from $PLAYERS.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1