A little Small Lua Telegram Library

Moderator: leecollings

User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

A little Small Lua Telegram Library

Post by emme »

Ciao,

I use to send notifications via Telegram in 3 different scenarios:
- myself
- in a group where the BOT is included
- to my wife

all these 3 scenarios does not fit the actual notification system in Domoticz that just handle one ID
so I use to run a brunch of os.execute and curl to send locally (within the script) all the notification I want.... but I dont like to put the bot Token everywhere...

SO... I finally wrote a small library to include in all scripts (dzVents included) that is able to send both messages and tvcc snapshot and would like to share with you.

It only runs under Linux....

save the following code to a file named Telegram.lua and put it in /home/pi/domoticz/scripts/lua

Code: Select all

local teleTok   = 'Enter your Bot Token here'
local snapFile  = '/home/pi/domoticzSnap'
local domoReq   = 'http://localhost:8080/camsnapshot.jpg?idx='
local tgAb = {}
tgAb['myName1']     = 222222222
tgAb['myName2']     = 111111111
tgAb['myGroup'] = -00000000

local telegram ={};

    function telegram.getId(nome)
        return tgAb[nome]
    end
    
    function telegram.sendText(chatId, message)
        return os.execute('curl --data chat_id='..chatId..' --data parse_mode=Markdown --data-urlencode "text='..message..'"  "https://api.telegram.org/bot'..teleTok..'/sendMessage" ')
    end

    function telegram.sendImage(chatId, camChannel)
        os.execute('wget -O "'..snapFile..camChannel..'.jpg" "'..domoReq..camChannel..'"')
        return os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendPhoto?chat_id='..chatId..'" -F photo="@'..snapFile..camChannel..'.jpg"')
    end

    function telegram.sendDoc(chatId, filePath)
        return os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendDocument?chat_id='..chatId..'" -F document="@'..filePath..'"')
    end
return telegram
then in your code add the reference library.
Please note that the library returns a boolean value for the success or not of the operation, so store it somewhere (in the example I put the result in the log)

Code: Select all

package.path = package.path .. ';' .. '/home/pi/domoticz/scripts/lua/?.lua'
local telegram = require('Telegram')
Actually I only included few option:
Send a text Message (Markdown formatting supported)
usage:
telegram.sendText(chatId, Message)
example

Code: Select all

result = telegram.sendText(123456789, 'This is a *TEST* Message')
Send a Camera SnapShot
usage:
telegram.sendImage(chatId, Camera Channel IDX)
example

Code: Select all

result = telegram.sendImage(123456789, 1)
Send a document (useful to send animated GIF also!!)
usage:
telegram.sendDoc(chatId, full_file_path_and_name)
example

Code: Select all

result = telegram.sendImage(123456789, '/home/pi/domoticz/domoticz.db')
AddressBook
le local array tgAb can be filled with the chatId and referred to a person/group
compile (and add raw if needed) using the syntax: tgAb['name you want to use to identify the chat'] = chatid
then, in your script use it like:

Code: Select all

local chatid = telegram.getId('name you want to use to identify the chat')

or, use it straight in the sendText function:

Code: Select all

telegram.sendText(telegram.getId('name you want to use to identify the chat'), 'This is a Message')
I hope you like it :P
ciao
M
Last edited by emme on Monday 08 January 2018 21:45, edited 6 times in total.
The most dangerous phrase in any language is:
"We always done this way"
bigpea
Posts: 91
Joined: Thursday 11 August 2016 12:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: IT
Contact:

Re: A little Small Lua Telegram Library

Post by bigpea »

Great idea and great script. :mrgreen:
It works very well, thanks!
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

added function to send docs and a chatid addressbook to fast references in your code
The most dangerous phrase in any language is:
"We always done this way"
wlevels
Posts: 16
Joined: Friday 16 September 2016 13:54
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.9700
Location: The Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by wlevels »

Thanks @emme just what I was looking for!
User avatar
EdddieN
Posts: 510
Joined: Wednesday 16 November 2016 11:31
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.9700
Location: Scotland
Contact:

Re: A little Small Lua Telegram Library

Post by EdddieN »

emme wrote: Monday 08 January 2018 21:46 added function to send docs and a chatid addressbook to fast references in your code
How do you use tgAb['myName1'] on the triggers script inside Domoticz?
11101101 - www.machinon.com
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

that a part of the addressbook function...
tgAb['Marco'] = 222222222
function telegram.getId(nome)
return tgAb[nome]
end

the ab contains only the chatid... is a better way to remeber the right addresses :P :P

then in the script I would use telegram.getId('Marco') to get 222222222
The most dangerous phrase in any language is:
"We always done this way"
hoeby
Posts: 528
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by hoeby »

do you also know how to do the command sendMediaGroup?

This works in a bash file. But prefer it to have in dzvents. Then al scripts are in the same place, when wanting to view them

Code: Select all

curl -s \
-X POST "https://api.telegram.org/bot"$token"/sendMediaGroup" \
-F chat_id=$SendMsgTo \
-F media='[{"type":"photo","media":"attach://photo_1","caption":"Camera Voordeur en Oprit"},{"type":"photo","media":"attach://photo_2","caption":"Camera Voordeur en Oprit"}]' \
-F photo_1="@$SnapFile1" \
-F photo_2="@$SnapFile2"
The part i am stuck with, it the info behind media=
It looks like DZvents is not accepting that row
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by waaren »

hoeby wrote: Sunday 10 March 2019 12:59 do you also know how to do the command sendMediaGroup?

This works in a bash file. But prefer it to have in dzvents. Then al scripts are in the same place, when wanting to view them
The part i am stuck with, it the info behind media=
It looks like DZvents is not accepting that row
dzVents or Lua should not have a problem with the string behind Media, except for the trailing \

Code: Select all

local media='[{"type":"photo","media":"attach://photo_1","caption":"Camera Voordeur en Oprit"},{"type":"photo","media":"attach://photo_2","caption":"Camera Voordeur en Oprit"}]' 
logWrite(media)
gives

Code: Select all

2019-03-10 13:09:00.476  Status: dzVents: Debug: media Test: [{"type":"photo","media":"attach://photo_1","caption":"Camera Voor                      deur en Oprit"},{"type":"photo","media":"attach://photo_2","caption":"Camera Voordeur en Oprit"}]
in the log
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
hoeby
Posts: 528
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by hoeby »

When i try it, it gives a nil value on the logWrite(mediaurl)

Code: Select all

return {
    on = { 
       devices = {'Camera voordeur'},
    },

    execute = function(domoticz, device)
        if(device.state == 'On') then
            local teleTok    = 'xxxxxxxxxxxxxxxx'
            local chatId     = 'xxxxxxxxxxxxxxxx'
            local snapFile   = '/home/pi/domoticz/scripts/camera_'
            local domoReq1   = 'http://192.168.178.246/jpg/1/image.jpg'
            local domoReq2   = 'http://192.168.178.246/jpg/1/image.jpg'
            local camName1   = 'Voordeur'
            local camName2   = 'Oprit'
            local mediaurl   = '[{"type":"photo","media":"attach://photo_1","caption":"Camera Voordeur en Oprit"},{"type":"photo","media":"attach://photo_2","caption":"Camera Voordeur en Oprit"}]' 
            logWrite(mediaurl)
            os.execute('wget -O "'..snapFile..camName1..'.jpg" "'..domoReq1..'"')
            os.execute('wget -O "'..snapFile..camName2..'.jpg" "'..domoReq2..'"')
            os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..'" -F media="..mediaurl.." -F photo1="@'..snapFile..camName1..'.jpg" -F photo2="@'..snapFile..camName2..'.jpg"')
            os.execute("rm " ..snapFile..camName1..'.jpg')
            os.execute("rm " ..snapFile..camName2..'.jpg')
        end
    end
}
            
 
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by waaren »

hoeby wrote: Sunday 10 March 2019 13:58 When i try it, it gives a nil value on the logWrite(mediaurl)
That's because you have no function logWrite in your code. You can copy it from my example or use the standard dzVents domoticz.log function.

your os.execute for the curl command is not correct
You have

Code: Select all

os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..'" -F media="..mediaurl.." -F photo1="@'..snapFile..camName1..'.jpg" -F photo2="@'..snapFile..camName2..'.jpg"')
This should be changed to

Code: Select all

os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..'" -F media="'..mediaurl..'" -F photo1="@'..snapFile..camName1..'.jpg" -F photo2="@'..snapFile..camName2..'.jpg"')
(Single quotes needed around ..mediaurl.. )
Please be aware that using these os.execute command from dzVents can cause a block. The wget or curl command can take some seconds and as the domoticz event system is single threaded all other eventhandlers will be blocked until this script has finished.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

Sorry folks to be so missing on this.... :(
unfortunately I'm out of internet connection at home (hopefully this should be the week they would fix it) so I have poor time to implement it

but if you're able to do this, please share the code! :P
ciao
M
The most dangerous phrase in any language is:
"We always done this way"
hoeby
Posts: 528
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by hoeby »

I don't get it to work in domoticz dzvents.
Don't know what i am doing wrong

Copied the codes from Waaren, but still getting a nil value response.
Added the single quotes needed around ..mediaurl..
But it didn't matter. I stopped research on it, because it works in .sh
Maybe somebody could get it to work, but i don't know how to debug the rigth way, with those os.execute commands to telegram
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

having a look to the sendMediaGroup docs it looks files cannot be sent as -F <filepath> but it has to be a JSON array of Media from 2 to 10:

[{ type: 'photo', media: attach://home/pi/temp/snap1.jpg },{ type: 'photo', media: attach://home/pi/temp/snap2.jpg }]

so the curl line should be like

Code: Select all

local mediaurl = [{ type: 'photo', media: attach://home/pi/temp/snap1.jpg },{ type: 'photo', media: attach://home/pi/temp/snap2.jpg }]
os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..'"&media="..mediaurl)
can you try it?
The most dangerous phrase in any language is:
"We always done this way"
hoeby
Posts: 528
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by hoeby »

I tried your script part, but get an nil value error

Code: Select all

Status: dzVents: Error (2.4.6): An error occured when calling event handler Camera voordeur snapshot3
Status: dzVents: Error (2.4.6): .../dzVents/generated_scripts/Camera voordeur snapshot3.lua:22: attempt to call global 'photo' (a nil value)
Used this code, some little code parts where forgotten in your code
And changed the location of my .jpg files

Code: Select all

local mediaurl = '[{ type: 'photo', media: attach://home/pi/domoticz/scripts/camera_Voordeur.jpg },{ type: 'photo', media: attach://home/pi/domoticz/scripts/camera_Oprit.jpg }]'
os.execute('curl -s -X POST "https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..'"&media="..mediaurl')
I think the nil value is because of 'photo', this searches for a local function, but there is non
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

ok.. I'm able to sendMediaGroup for internet images....

I'm still trying to work on local uploadable files.... stay tuned :P :P

Ok... got the issue!
local file paths cannot be written directly in the JSON array media key... they have to be specified in a data variable, encoded, uploaded and then referenced in the array

still need some work on this as soon as I have time
The most dangerous phrase in any language is:
"We always done this way"
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

The solution is here
https://www.domoticz.com/forum/viewtopi ... 88#p185288

but I cannot having working under windows....
The most dangerous phrase in any language is:
"We always done this way"
hoeby
Posts: 528
Joined: Saturday 02 June 2018 11:05
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.1
Location: Echt, Netherlands
Contact:

Re: A little Small Lua Telegram Library

Post by hoeby »

I have it working with the .sh file, where to link points to.
But would liked to have it working in DZvents.

The .sh file is only possible to change when logging in with a pc.
But working from a tablet this doesn't work. Therefor the prefer for dzvents.
Thin-client --> Docker Domoticz main environment
Pi3A+ --> Google home (GAssistPi)
Pi3B+ --> Docker (P1monitor, Domoticz test environment, Ubiquity controller)
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

this evening I'll try to adapt it...

it would be difficult to implement the number of files to send (from 2 to 10...) but I'll figure out how...
most probably the JSON array must be provided instead of providing just the file names... this way you can choos to use optionals options (like caption) that otherwise you should provide as parameters....

it will be something like telegram.sendMediaGroup(chat_id, <mediaJson>)
ciao
M
The most dangerous phrase in any language is:
"We always done this way"
User avatar
emme
Posts: 909
Joined: Monday 27 June 2016 11:02
Target OS: Raspberry Pi / ODroid
Domoticz version: latest
Location: Milano, Italy
Contact:

Re: A little Small Lua Telegram Library

Post by emme »

Ok folks... got it!!! :P :P

first... edit the Telegram.lua library and add the following code befor the last line "return telegram":

Code: Select all

    function telegram.sendMG(chatId, arrPic)
        local strMedia = ''
        local strPics = ''
        if type(arrPic) == 'table' then
            for idx = 1, #arrPic do
                if arrPic[idx][2]:sub(1,9) == "attach://" then  -- Local file
                    strPics = strPics..' -F '..arrPic[idx][1]..'_'..idx..'=@'..arrPic[idx][2]:sub(10)
                    strMedia = strMedia..'{"type":"'..arrPic[idx][1]..'","media":"attach://'..arrPic[idx][1]..'_'..idx..'","caption":"'..arrPic[idx][3]..'","parse_mode":"'..arrPic[idx][4]..'"}'
                else
                    strMedia = strMedia..'{"type":"'..arrPic[idx][1]..'","media":"'..arrPic[idx][2]..'","caption":"'..arrPic[idx][3]..'","parse_mode":"'..arrPic[idx][4]..'"}'
                end
                if idx ~= #arrPic then
                    strMedia = strMedia..','
                end
            end
            return os.execute('curl -X POST https://api.telegram.org/bot'..teleTok..'/sendMediaGroup?chat_id='..chatId..' '..strPics..' -F media=\'['..strMedia..']\'')
        end
        dz.log(strPics..' / '..strMedia)
    end
save it

next..
to use it in your code you have to provide a neasted table to the function:

Code: Select all

local arrPic = {{'photo', 'attach:///home/pi/snap1.jpg', 'Test', 'Markdown'},{'photo', 'attach:///home/pi/temp/snap.jpg', 'Test', 'Markdown'}}
the keys are:
1. Type (photo or media)
2. File (prefix attach:// and then the full path from root) or url ( prefix http://)
3. Caption
4. Caption format (Markdown or HTML)

each record is closed betweeb { } records are separated by , ALL in closed between { }
remember you can do from 2 to 10 pics...
How to gain such table is up to your code... (it's time you start working with lua tables ;) )

now you can call them using: telegram.sendMG(chat_id, arrPic) where chat_id you already know what is, and arrPic is your table

the function will care about generating the right URL and execute it!

...btw... how many of you are using this library right now?.... did you enjoy it?
ciao
M
The most dangerous phrase in any language is:
"We always done this way"
zicht
Posts: 251
Joined: Sunday 11 May 2014 11:09
Target OS: Windows
Domoticz version: 2023.1+
Location: NL
Contact:

Re: A little Small Lua Telegram Library

Post by zicht »

Hi folks

Just see this nice script right now, good job ! Less complex then what i was using before. (I use telegram a lot to send foto's from security script.) Works great !

Some things to keep in mind with os.execute and possible sollutions :
There is some experience with this curl, and you can slow down domoticz a lot when doing it for LUA.
The first sign will be a error line in the log "Script running for more than 10 seconds"
Its happens not to often but in my case when it happens it will be a lot of times in a row. Probably due to some issues on telegram side ...
The slow down is realy noticable.

I solved it with adding " --connect-timeout 5 --max-time 6 " to the curl command. (still a slow down but under control)
Then i do not use os.execute but io.popen...

Code: Select all

function os.capture(cmd, raw)				-- os.command uitvoeren en resultaat daarvan lezen in string
  --
  local f=assert(io.popen(cmd, 'r'))
  local s=assert(f:read('*a'))
  f:close()
  if raw then return s end
  s=string.gsub(s, '^%s+', '')
  s=string.gsub(s, '%s+$', '')
  s=string.gsub(s, '[\n\r]+', ' ')
 return s
end
var s will contain the return from the curl. So you can check if telegram received the command by evalutation of variable s

If you want to use it from windows. Install a curl,exe (haxx.se) in you domoticz folder and call it via powershell like 'start /b /realtime curl.exe --connect-timeout 5 --max-time 9' ..cmd This also give the shell some priority within the windows system. again not os,execute but io.popen to catch return values.

I am not a coder at all, all was found on the forum during my "domoticz time". feel free to comment, use, optimize and share.
Rpi & Win x64. Using : cam's,RFXCom, LaCrosse, RFY, HuE, google, standard Lua, Tasker, Waze traveltime, NLAlert&grip2+,curtains, vacuum, audioreceiver, smart-heating&cooling + many more (= automate all repetitive simple tasks)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest