Mikrotik and Telegram

Hi, here are scripts to work with Telegram (see attach).
To use scripts:

  1. Unpack .rsc file and import it to router, you should see next scripts in System->Scripts:
    func_fetch – wrapper for /tool fetch
    tg_config – config
    tg_getUpdates – check Telegram for updates and run command scripts
    tg_sendMessage – send message to Telegram
    tg_cmd_hi – example of /hi command
    tg_cmd_health – example of /health command

  2. Fill tg_config script with your data. If you don’t know how create bot in Telegram or how get id of bot, your own Telegram id or HTTP API token - I will prepare short instruction in English.

  3. Send test commands to your bot (/hi or /health) and check if script works running in terminal few times command:

/system script run tg_getUpdates

If you got replies in Telegram - just enable correspondent Telegram task in System->Scheduler.

To send messages to Telegram just call tg_sendMessage function, for example:

:local send [:parse [/system script get tg_sendMessage source]]
...
$send text=(“Hi!”)
$send text=(“How are you?”)

In the case if none destination chat set messages will be sent into the default chat (set in the tg_config).
To add your own commands to bot just add new command to bot (/setcommands in @BotFather ) and create script named tg_cmd_command.
As example see /hi and /health bot commands (scripts tg_cmd_hi and tg_cmd_health).

In Russian all needed information given in my blog - https://www.mikrotik-club.in.ua/2017/12/05/telegram-bot-mikrotik/

PS: but one thing should be kept in mind - annoying logging of /tool fetch command to Log which can’t be switched off ^(
It is not problem if you call fetch few times in the day but problem if every minute (checking updates from Telegram) - log is filled by dummy and useless information ^(
It is the reason why Telegram task in Scheduler disabled by default.
But even in this case tg_sendMessage command can be very useful - to send notification to Telegram when something happens on router (new pptp session established, new Wi-Fi user connected or somebody logged to router).
telegram_v1.zip (2.88 KB)

Good work man

Can you describe the configuration options of your script exactly. I mean the telegram configuration $config. Where to download all the required variables.

tg: Load config
  status: failed

failure: closing connection: <400 Bad Request> 149.154.167.199:443 (5)

after running this

/system script run tg_getUpdates
  1. First you need install Telegram and create your account.
  2. Next - get your Telegram id (it is not username. ID - it is a number). To get it add to your contacts @MyTelegramID_bot and start conversation with it. It will say you your id. Remember it and put to “trusted” and “defaultChatID”. “Trusted” - it is a string of comma separated ids of trusted sources for sending messages to bot. Bot replies only to trusted and ignore the rest. In the simplest case - it is just your own Telegram id. I also use group chats for this. “defaultChatID” - where to send messages in the case if your not set destination chat in the tg_sendMessage. Again - simplest case is your Telegram ID.
  3. Create bot. To do this add to your contacts @BotFather ( https://core.telegram.org/bots#6-botfather ). Send to it command /newbot. It will ask you for description and username of bot.
    If all Ok it will say you long alpha-numeric token like 38…74:AAEW4Zdd…mi51FZ8Q1Bp8 . Copy it to botID in config.
  4. Add commands to your bot - send @BotFather command /setcommands , it will ask you for commands - just send this text to it:
hi - echo
health - get router's health

To split lines use “Shift-Enter”.
4. “storage” in config - is place for temp files. Better to not use internal flash for this. I use USB flash drive that why “disk1/”. For internal flash just make it empty - “”.

More information on bots - https://core.telegram.org/bots
If you stuck on bots creating (it is simple but may be hard for first time %) - I can help - via private messages in forum (or any people can use your bot %).

It seems to be wrong values in tg_config.
Before error it should show your line like
/tool fetch dst-path=“disk1/tg_get_updates.txt” url=“https://api.telegram.org/bot3835…”
Please copy it here to check.
Or send me full output of tg_getUpdates

/health works perfect but /hi does not

When you add commands to bot (/setcommands) - you pushed Shift-Enter after first line or just Enter?
If just Enter - it remembered only one command.
It is little bit crazy but I do /setcommands dozen times until I realized that lines should be separated by Shift-Enter.
To check if is it this issue - just put / in the mikrotik bot chat window and check will it show both /hi and /health commands or only /health

Or run /bybots in BotFather, choose your bot, Edit Bot and check how many commands it has.
Also tg_getUpdates processed only one command per one time.
And check output in the console - it should show command from chat and script which tried to call.

there was something wrong with tg_cmd_hi
i just change it

##########################
# /hi text
# Just echo to check bot is alive
# Input:
#  params - parameters
#  chatid - id of chat
#  from - name of who sent command
:local send [:parse [/system script get tg_sendMessage source]]

:put $params
:put $chatid
:put $from

$send chat=$chatid text="test"  mode="Markdown"
:return true

now its works

What was value of $from ?
mode=Markdown just means that you can do simple formatting ( https://core.telegram.org/bots/api#markdown-style )
Has your account has filled first_name, last_name or username? Or all them are empty?
But in any case I should add detection of “inkognito” accounts, thanks for reply.

tg_getUpdates fix - added correct processing of case when username, first_name, last_name of sender all are not filled or not exist.

:global TGLASTMSGID
:global TGLASTUPDID

:local fconfig [:parse [/system script get tg_config source]]
:local http [:parse [/system script get func_fetch source]]
:local gkey [:parse [/system script get tg_getkey source]]
:local send [:parse [/system script get tg_sendMessage source]]

:local cfg [$fconfig]
:local trusted [:toarray ($cfg->"trusted")]
:local botID ($cfg->"botAPI")
:local storage ($cfg->"storage")
:local timeout ($cfg->"timeout")

:put "cfg=$cfg"
:put "trusted=$trusted"
:put "botID=$botID"
:put "storage=$storage"
:put "timeout=$timeout"

:local file ($storage."tg_get_updates.txt")
:local logfile ($storage."tg_fetch_log.txt")
#get 1 message per time
:local url ("https://api.telegram.org/bot".$botID."/getUpdates?timeout=$timeout&limit=1")
:if ([:len $TGLASTUPDID]>0) do={
  :set url "$url&offset=$($TGLASTUPDID+1)"
}

:put "Reading updates..."
:local res [$http dst-path=$file url=$url resfile=$logfile]
:if ($res!="success") do={
  :put "Error getting updates"
  return "Failed get updates"
}
:put "Finished to read updates."

:local content [/file get [/file find name=$file] contents]

:local msgid [$gkey key="message_id" text=$content]
:if ($msgid="") do={ 
 :put "No new updates"
 :return 0 
}
:set TGLASTMSGID $msgid

:local updid [$gkey key="update_id" text=$content]
:set TGLASTUPDID $updid

:local fromid [$gkey block="from" key="id" text=$content]
:local username [$gkey block="from" key="username" text=$content]
:local firstname [$gkey block="from" key="first_name" text=$content]
:local lastname [$gkey block="from" key="last_name" text=$content]
:local chatid [$gkey block="chat" key="id" text=$content]
:local chattext [$gkey block="chat" key="text" text=$content]

:put "message id=$msgid"
:put "update id=$updid"
:put "from id=$fromid"
:put "first name=$firstname"
:put "last name=$lastname"
:put "username=$username"
:local name "$firstname $lastname"
:if ([:len $name]<2) do {
  :if  ([:len $username]>0) do={
   :set name $username
  } else={
   :set name "Stranger"
  }
}
:put "name=$name"

:put "in chat=$chatid"
:put "command=$chattext"

:local allowed ( [:type [:find $trusted $fromid]]!="nil" or [:type [:find $trusted $chatid]]!="nil")
:if (!$allowed) do={
 :put "Unknown sender, keep silence"
 :return -1
}

:local cmd ""
:local params ""
:local ltext [:len $chattext]

:local pos [:find $chattext " "]
:if ([:type $pos]="nil") do={
 :set cmd [:pick $chattext 1 $ltext]
} else={
 :set cmd [:pick $chattext 1 $pos]
 :set params [:pick $chattext ($pos+1) $ltext]
}

:local pos [:find $cmd "@"]
:if ([:type $pos]!="nil") do={
 :set cmd [:pick $cmd 0 $pos]
}

:put "cmd=<$cmd>"
:put "params=<$params>"

:global TGLASTCMD $cmd

:put "Try to invoke external script tg_cmd_$cmd"
:local script [:parse [/system script get "tg_cmd_$cmd" source]]
$script params=$params chatid=$chatid from=$name

Nice job .. i Already did it for my MT

:local sub1 ([/system identity get name])
:local sub2 ([/system clock get time])

:if ([/ping 8.8.8.8 count=5] = 0) do=
{
/ tool fetch "https://api.telegram.org/botXXXXXXXX/sendMessage?chat_id=-XXXXXXXX&text=($sub1) Can Not Ping Google at $sub2  "

:log warning "<<< Server Can Not Ping Google <<<"
}

Regards.

hi
tanks
What does this line mean?
\n"trusted"="AAAAAAAAA,BBBBBBBBB,CCCCCCCCC";\r


what is trusted

It is string of comma separated list of ids of trusted sources. I.e. it is who can send commands to Telegram bot.
If its is only you - when it is your Telegram id (not username!) in double quotes
In the config it is just list of some three hypothetical ids AAAAA, BBBBB, CCCCC

Yes, it is about the same that tg_sendMessage does %) With one difference - botID and chatID stored in the one place.
I.e. if you use Telegram in few places it is easy to update ids. But if in many - better to place them in one place (config) %)

is anyway to sending Log warning ? how can I do it ?
thanks



:log warning "Type ur text here :)"

I want to send below log message to telegram
Snap1.jpg

You can try parse log like here - http://forum.mikrotik.com/t/read-info-from-log/111775/1

can you help me ? I’m noob in scripting :frowning: