openHAB, Telegram Bot and quoting URLs

Posted by ads' corner on Wednesday, 2020-08-19
Posted in [Ansible][Openhab]

A while ago I integrated DWD warnings (Deutscher Wetterdienst) into our home automation system, and receive severe weather notifications ever since then. That works quite good, but it was missing a weblink with more details - or if you want to forward the warning to someone it would be useful to have a link to the warning as well. The DWD binding does not provide that piece of information, but it is easy enough to add - or so I thought.

In my setup I roll out the rules file with Ansible, which lets me loop over all the locations I’m interested in. I expanded the $dwds variable with an additional link:

1
2
3
4
5
{% set dwds = [('Ort 1', 'ort1', '111000001', 'https://www.dwd.de/DE/wetter/warnungen_gemeinden/warnWetter_node.html?ort=Halle%20(Saale)'),
               ('Ort 2', 'ort2', '111000002', '...'),
               ('Ort 3', 'ort3', '111000003', '...'),
               ('Ort 4', 'ort4', '111000004', '...')
              ] %}

So far this is easy, and I only need to attach the link to the Telegram message. First iteration:

1
2
3
    meldung = meldung + Warning{{ dwd[1] }}Instruction{{ chan }}.state.toString
    meldung = meldung + "\n\n" + "[Details]({{ dwd[3] }})"
    logInfo("DWD", meldung)

The format the Telegram bot uses is “Markdown V2”, and the [...](...) format adds a link (...) with a description in [...]. That however does not work, the Telegram API does not add the correct link (one closing parenthesis short), and the resulting link in the group is a 404.

A look into the documentation reveals:

Inside (...) part of inline link definition, all ')' and '\' must be escaped with a preceding '\' character.

Well, ok, let’s escape the closing parenthesis and see where this goes. I’m doing that directly in Ansible:

1
    meldung = meldung + "\n\n" + "[Details]({{ dwd[3] | replace(')', '\\)') }})"

However you can also do it in the rule DSL:

1
    meldung = meldung + "\n\n" + "[Details](url.replace(')','\\)'))"

The debug output shows that the parenthesis is indeed escaped:

https://www.dwd.de/DE/wetter/warnungen_gemeinden/warnWetter_node.html?ort=Halle%20(Saale\)

But for reasons I’m unable to figure out, Telegram still shows the closing parenthesis. The URL however is still cut short by one parenthesis, and an additional ? is added.

short DWD Message in Telegram
short DWD Message in Telegram

At this point, and after much debugging, I switched to URL escaping the characters. In Ansible:

1
meldung = meldung + "\n\n" + "[Details]({{ dwd[3] | replace('(', '%28') | replace(')', '%29') }})"

Or directly in the rule:

1
meldung = meldung + "\n\n" + "[Details](url.replace('(','%28').replace(')', '%29'))"

The debug output for the link is now:

https://www.dwd.de/DE/wetter/warnungen_gemeinden/warnWetter_node.html?ort=Halle%20%28Saale%29

And the correct link is added in Telegram:

correct  DWD Message in Telegram
correct DWD Message in Telegram

Notes:

All URLs should be URL quoted, if they come from an external source. In this case I don’t have to care about this, because I specify the URLs myself.

I could also add the quoted URLs directly to the $dwds variable - however I don’t know if I will have further use cases which need the original URL. So I rather quote and escape it when needed, and don’t add already quoted URLs to the initial data.


Categories: [Ansible] [Openhab]