How to send emoji via bash script to Telegram bot using curl?
Asked Answered
Y

2

5

I'm trying to send an emoji/emoticon to my Telegram bot using a bash script. This bash script calls the Telegram API as follows:

curl -s -X POST 'https://api.telegram.org/'$API'/sendMessage' -F chat_id=$chat -F text=$text

Since the bash script isn't unicode, I cannot simply copy/paste the emojis from the web. Therefore I tried using the UTF-8 emoji variants, but the backslash character keeps getting escaped.

The expected json output should be as follows: "text":"\ud83d\udd14"

Instead, this is what I get:

Input: $text = \xF0\x9F\x98\x81 JSON Output = "text":"\\xF0\\x9F\\x98\\x81\\"

Input: $text = u'\U0001F604' JSON Output = "text": "u'\\U0001F604'\"

Input: $text = \U0001F514 JSON Output = "text":"\\U0001F514"

Input: $text = "(1f600)" JSON Output = "text":"\"(1f600)\""

Input: $text = \ud83d\ude08 JSON Output = "text":"\\ud83d\\ude08"

Input: $text = \\\ud83d\\\udd14 JSON Output = "text":"\\\\\\ud83d\\\\\\udd14"

What is the correct syntax to send an emoji using a bash script and curl to my Telegram bot?

Thank you very much!

Yonne answered 24/4, 2018 at 19:58 Comment(5)
If you're trying to generate JSON, let a tool written to handle JSON, like jq, figure out how to encode your string.Crowell
BTW, what do you mean, "the bash script isn't unicode"? If you need to fix your editor settings, that's a problem with your text editor's configuration, and can be fixed from there. UTF-8 is a perfectly valid encoding to use for your script itself.Crowell
Maybe I'm mixing things up, but I am using nano via SSH on a stripped down Unix environment (Synology NAS). If i copy/paste an emoticon from the Web into my SSH session, I get two question marks as a result. Hence i thought it was an encoding issue.Yonne
Hmm. What terminal are you using for the SSH session? Are you sure that's UTF-8 capable, and using an appropriate font?Crowell
I am using Rebex, but it appears that the encoding was set to some ISO-xxxx standard. After switching it to utf 8, I am able to copy/paste emoticons, yet I still have to declare them as variable first for them to be processed properly (i.e. not getting escaped) by the telegram api.Yonne
C
8

Generating JSON For The Telegram API

If your question is about JSON encoding, let jq figure it out for you:

s='🔔'  ## or s=$'\360\237\224\224'

json=$(jq -anc --arg id "$chat" --arg s "$s" '{"chat_id": $id, "text": $s}')
curl -X POST -H "Content-Type: application/json" -d "$json" \
  "https://api.telegram.org/$API/sendMessage"

From JSON To String Literal

In bash 4.0 or newer, the shell itself can be asked to give you an ASCII-printable literal string which will correspond to a multi-byte character.

LC_ALL=C printf "s=%q\n" "$(jq -r . <<<'"\ud83d\udd14"')"

...will output:

s=$'\360\237\224\224'

From String Literal To JSON

To go in the other direction:

s=$'\360\237\224\224'
jq -anM --arg s "$s" '$s'

...emits as output:

"\ud83d\udd14"
Crowell answered 24/4, 2018 at 20:6 Comment(9)
How the bell did you post that bell?Wrought
@hek2mgl, I got the bell from jq -r . <<<'"\ud83d\udd14"', consuming the literal JSON string the OP put in the question.Crowell
Many thanks for your super quick answer and example. I am going to try this out tomorrow. I am not sure if jq is installed on my environment, but if not I'll fall back to your second example. Thank you very much! I'll let you know how it goes.Yonne
Hmm. If you don't have JQ, I'd be tempted to use Python rather than bash (since any remotely-recentish Python interpreter will have a JSON parser/generator built-in). That's doubly true if your messages are going to be coming from tooling that you don't directly control -- you don't need a text string ending in, say ", "sendVideo": "http://example.com/spam.m4v to be able to create new JSON fields rather than being correctly escaped as data.Crowell
Many many thanks for your detailed answer! Both approaches worked (i.e. the jq approach and the 'convert to String Literal manually approach) for me. I spent almost 2 hours on getting something simple like this to work. Thanks again for the help!Yonne
Is there a way to have the emoji inside the string instead of a separate var? eg json=$(jq -anc --arg id "$chat" --arg s "$'\360\237\224\224'" '{"chat_id": $id, "text": $s}'Forgiving
@Stormenet, that example would work fine if you didn't have double quotes around the ANSI C-like string. Make it --arg s $'\360\237\224\224'Crowell
I wasn't clear with my intent, can we do this around existing text, something like --arg s "This is an emoji: $'\360\237\224\224' and this is some more text..." since the latter isn't working here.Forgiving
@Forgiving --arg s $'This is an emoji: \360\237\224\224 and this is some more text...' -- or you can switch quoting styles within your string by ending the double quotes and starting the ANSI C-like string, then if you want to switch back to double quotes ending the C-like string and starting double quotes again. This isn't really a jq question, it's just about how quoting works in bash in general.Crowell
I
6

You can use echo -e '\U0001F514' for get emoji

curl -F "text=`echo -e '\U0001F514'` - it's a bell" "https://api.telegram.org/$API/sendMessage?chat_id=$chat"

or $'\U0001F514'

curl -F "text="$'\U0001F514'" - it's a bell" "https://api.telegram.org/$API/sendMessage?chat_id=$chat"
Infect answered 26/4, 2019 at 8:11 Comment(2)
thx @Infect I was thinking the same as you by using "echo -e" and it worked for me.Ramage
Boo, hiss re: echo -e; even the POSIX standard for echo says to use printf instead (see the APPLICATION USAGE and RATIONALE sections). There's also an excellent answer on the Unix & Linux question Why is printf better than echo?Crowell

© 2022 - 2024 — McMap. All rights reserved.