Community discussions

 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Mikrotik and Telegram

Tue Dec 05, 2017 5:42 pm

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 ... -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).
You do not have the required permissions to view the files attached to this post.
 
User avatar
ADahi
Member Candidate
Member Candidate
Posts: 206
Joined: Thu Sep 21, 2017 7:16 pm
Location: Iraq, Ninavah
Contact:

Re: Mikrotik and Telegram

Tue Dec 05, 2017 7:34 pm

Good work man
 
arky
just joined
Posts: 12
Joined: Sat Apr 09, 2011 12:39 pm

Mikrotik and Telegram

Tue Dec 05, 2017 11:24 pm

Can you describe the configuration options of your script exactly. I mean the telegram configuration $config. Where to download all the required variables.
 
User avatar
irghost
Member Candidate
Member Candidate
Posts: 273
Joined: Sun Feb 21, 2016 1:49 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 12:29 am

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
MTCNA MTCRE MTCTCE MTCUME MTCWE MTCIPv6E MTCINE
میکروتیک فا برای فارسی زبان ها
Mikrotik Certified Consultant
https://mikrotikfa.com
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 7:10 am

Can you describe the configuration options of your script exactly. I mean the telegram configuration $config. Where to download all the required variables.
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 %).
Last edited by BlackVS on Wed Dec 06, 2017 7:20 am, edited 3 times in total.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 7:15 am

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
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
 
User avatar
irghost
Member Candidate
Member Candidate
Posts: 273
Joined: Sun Feb 21, 2016 1:49 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 8:54 am

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
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
MTCNA MTCRE MTCTCE MTCUME MTCWE MTCIPv6E MTCINE
میکروتیک فا برای فارسی زبان ها
Mikrotik Certified Consultant
https://mikrotikfa.com
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 9:40 am

/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.
 
User avatar
irghost
Member Candidate
Member Candidate
Posts: 273
Joined: Sun Feb 21, 2016 1:49 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 10:05 am

/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
MTCNA MTCRE MTCTCE MTCUME MTCWE MTCIPv6E MTCINE
میکروتیک فا برای فارسی زبان ها
Mikrotik Certified Consultant
https://mikrotikfa.com
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 10:44 am

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.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Dec 06, 2017 10:57 am

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
 
User avatar
katem07
just joined
Posts: 16
Joined: Mon Apr 10, 2017 11:35 am

Re: Mikrotik and Telegram

Fri Dec 08, 2017 6:54 pm

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.
Knowledge Sharing ... 8)
 
alireza1305
just joined
Posts: 1
Joined: Fri Dec 08, 2017 7:52 pm

Re: Mikrotik and Telegram

Fri Dec 08, 2017 9:01 pm

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


what is trusted
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Sat Dec 09, 2017 5:45 pm

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
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Sat Dec 09, 2017 5:48 pm

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.
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) %)
 
User avatar
ErfanDL
Member Candidate
Member Candidate
Posts: 223
Joined: Thu Sep 29, 2016 9:13 am
Location: IRAN
Contact:

Re: Mikrotik and Telegram

Sun Dec 10, 2017 5:53 pm

is anyway to sending Log warning ? how can I do it ?
thanks
 
User avatar
katem07
just joined
Posts: 16
Joined: Mon Apr 10, 2017 11:35 am

Re: Mikrotik and Telegram

Mon Dec 11, 2017 11:03 am

is anyway to sending Log warning ? how can I do it ?
thanks
:log warning "Type ur text here :)"
Knowledge Sharing ... 8)
 
User avatar
ErfanDL
Member Candidate
Member Candidate
Posts: 223
Joined: Thu Sep 29, 2016 9:13 am
Location: IRAN
Contact:

Re: Mikrotik and Telegram

Tue Dec 12, 2017 12:11 pm

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 do not have the required permissions to view the files attached to this post.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Tue Dec 12, 2017 3:59 pm

You can try parse log like here - viewtopic.php?t=125097
 
User avatar
ErfanDL
Member Candidate
Member Candidate
Posts: 223
Joined: Thu Sep 29, 2016 9:13 am
Location: IRAN
Contact:

Re: Mikrotik and Telegram

Wed Dec 13, 2017 9:05 am

You can try parse log like here - viewtopic.php?t=125097
can you help me ? I'm noob in scripting :(
 
ychuangtw
just joined
Posts: 1
Joined: Tue Dec 05, 2017 3:19 pm

Re: Mikrotik and Telegram

Wed Dec 27, 2017 9:30 pm

I'm a noob in Mikrotik and Scripting. But i got the same error as @irghost got.
However, if I try to run the tg_cmd_hi directly from terminal, then it would run without problems (lack of $from variable, of course)
So it seems that it's not a tg_config problem, or it won't run in that case...
Here's what I got from terminal running tg_getUpdates:
[edit]: I'm using ROS ver 6.40.5, if that helps
tg: Load config

trusted=2312312312;trusted=12345678
botID=42123367:OOOOOOOOOOOOOOOOOOOOOlAQ
storage=
timeout=1
Reading updates...
>> /tool fetch dst-path="tg_get_updates.txt" url="https://api.telegram.org/bot42123367:OOOOOOOOOOOOOOOOOOOOOlAQ/getUpdates?timeout=1&limit=1&offset=1151
68289"
Finished to read updates.
message id=23
update id=115168289
from id=2312312312
first name=Joshua
last name=Huang
username=jhuang
name=Joshua Huang
in chat=2312312312
command=/hi
cmd=<hi>
params=<>
Try to invoke external script tg_cmd_hi

2312312312
Joshua Huang
tg: Load config
  status: failed

failure: closing connection: <400 Bad Request> 149.154.167.200:443 (5)
Last edited by ychuangtw on Fri Dec 29, 2017 6:54 am, edited 1 time in total.
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Thu Dec 28, 2017 4:55 pm

Before last command in tg_SendMessage insert debug command:

:put $url

(or :log $url) and check URL composed by this script.
As variant - wrong botID or chatID.
 
sipiyuku
just joined
Posts: 1
Joined: Sat Jan 20, 2018 2:59 pm

Re: Mikrotik and Telegram

Sat Jan 20, 2018 4:09 pm

Before last command in tg_SendMessage insert debug command:

:put $url

(or :log $url) and check URL composed by this script.
As variant - wrong botID or chatID.
After send command /health to mybot, i have tracert my error log, :
/system script run tg_getUpdates
tg: Load config

trusted=263160993
botID=504794943:AAEyJkLCZljTmb-cKumVAKa1OtdvmbsnWaU
storage=
timeout=1
Reading updates...
>> /tool fetch dst-path="tg_get_updates.txt" url="https://api.telegram.org/bot504794943:A ... =790797188"
Finished to read updates.
message id=149
update id=790797188
from id=263160993
first name=Fendi
last name=Kurniawan
username=
in chat=263160993
command=/health
cmd=<health>
params=<>
Try to invoke external script tg_cmd_health

263160993
Fendi Kurniawan
ambiguous value of value-name, more than one possible value matches input
 
shaider
just joined
Posts: 11
Joined: Thu Mar 23, 2017 6:54 am
Location: Taytay, Philippines
Contact:

Re: Mikrotik and Telegram

Wed Feb 07, 2018 1:11 pm

is it possible to send command via telegram then execute in RouterBOARD?
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Feb 07, 2018 2:00 pm

Fendi Kurniawan
ambiguous value of value-name, more than one possible value matches input
Have you use the last version (see viewtopic.php?f=9&t=128394#p631125 )?
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Feb 07, 2018 2:02 pm

is it possible to send command via telegram then execute in RouterBOARD?
yes
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Tue Feb 13, 2018 2:03 am

I tried the script, Nice job. But I have got problem with updates, It's seems like tgGetkey not working well...

I'm allways getting:
command=
cmd=<>
params=<>

When I'm opening the file I see the incoming message ("Hi" in this example)...

{"ok":true,"result":[{"update_id":44584376,
"message":{"message_id":10,"from":{"id":542535389,"is_bot":false,"first_name":"Metal","last_name":"Jef","username":"mjef","language_code":"en-US"},"chat":{"id":542535389,"first_name":"Metal","last_name":"Jef","username":"mjef","type":"private"},"date":1518475137,"text":"Hi"}}]}

Any idea why tgGetkey not working well ?
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Tue Feb 13, 2018 8:35 am

Command must start from /,
i.e "/hi" but not "hi".
Also this command should be set for you bot via @BotFarther's /setcommands.
PS: sample commands done in lowercase, i.e "/hi", not "/Hi". Case makes difference too.
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Tue Feb 13, 2018 11:14 am

Command must start from /,
i.e "/hi" but not "hi".
Also this command should be set for you bot via @BotFarther's /setcommands.
PS: sample commands done in lowercase, i.e "/hi", not "/Hi". Case makes difference too.
Great, Thanks. I'm new with telegram :)...

More question how I'm sending $cmd and $params in message?
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Tue Feb 13, 2018 11:30 am

I'm trying to make telegram available by global (enviroment), This is the complete script:
:global tgBotAPI "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
:global tgDefaultChatID "AAAAAAAA,BBBBBBBB,CCCCCCC";
:global tgTrusted "AAAAAAAA,BBBBBBBB,CCCCCCC";
:global tgStorage "";
:global tgTimeout 1;

:global tgSendMessage do={
	:global tgBotAPI;
	:global tgStorage;
	:global tgDefaultChatID;
	:local tgID $tgDefaultChatID

	:if ([:len $chat]>0) do={ set tgID $chat }

	:foreach chatID in=[:toarray $tgID] do={
		:local fail false;
		:local url "https://api.telegram.org/bot$tgBotAPI/sendmessage\?chat_id=$chatID&text=$text"
		:if ([:len $mode]>0) do={:set url ($url."&parse_mode=$mode")}
		:do {
			/tool fetch url=$url keep-result=no
		} on-error={
			:log error "failed to send telegram message to '$chatID'."
			:set fail true;
		}
		:if (!$fail) do={
			:log info "telegram message has been sent to '$chatID'"
		}
	}
}

:global tgGetUpdates do={
	:global tgLastMsgID
	:global tgLastUPDID

	:local tgGetkey do={
		:local cur 0
		:local lkey [:len $key]
		:local res ""
		:local p

		:if ([:len $block]>0) do={
 			:set p [:find $text $block $cur]
 			:if ([:type $p]="nil") do={
	  			:return $res
 			}
 			:set cur ($p+[:len $block]+2)
		}

		:set p [:find $text $key $cur]
		:if ([:type $p]!="nil") do={
 			:set cur ($p+lkey+2)
 			:set p [:find $text "," $cur]
 			:if ([:type $p]!="nil") do={
   				:if ([:pick $text $cur]="\"") do={
    				:set res [:pick $text ($cur+1) ($p-1)]
   				} else={
    				:set res [:pick $text $cur $p]
   				}
			}
		}
		:return $res	
	}

	:local http do={
		:local res "fetchresult.txt"
		:if ([:len $resfile]>0) do={:set res $resfile}
		#:put $res

		:local cmd "/tool fetch"
		:if ([:len $mode]>0) do={:set cmd "$cmd mode=$mode"}
		:if ([:len $upload]>0) do={:set cmd "$cmd upload=$upload"}
		:if ([:len $user]>0) do={:set cmd "$cmd user=\"$user\""}
		:if ([:len $password]>0) do={:set cmd "$cmd password=\"$password\""}
		:if ([:len $address]>0) do={:set cmd "$cmd address=\"$address\""}
		:if ([:len $host]>0) do={:set cmd "$cmd host=\"$host\""}
		:if ([:len $"http-data"]>0) do={:set cmd "$cmd http-data=\"$"http-data"\""}
		:if ([:len $"http-method"]>0) do={:set cmd "$cmd http-method=\"$"http-method"\""}
		:if ([:len $"check-certificate"]>0) do={:set cmd "$cmd check-certificate=\"$"check-certificate"\""}
		:if ([:len $"src-path"]>0) do={:set cmd "$cmd src-path=\"$"src-path"\""}
		:if ([:len $"dst-path"]>0) do={:set cmd "$cmd dst-path=\"$"dst-path"\""}
		:if ([:len $ascii]>0) do={:set cmd "$cmd ascii=\"$ascii\""}
		:if ([:len $url]>0) do={:set cmd "$cmd url=\"$url\""}

		:put ">> $cmd"

		:global FETCHRESULT
		:set FETCHRESULT "none"

		:local script "\
	 	:global FETCHRESULT;\
	 	:do {\
	   		$cmd;\
	   		:set FETCHRESULT \"success\";\
	 	} on-error={\
	  		:set FETCHRESULT \"failed\";\
	 	}\
		"
		:execute script=$script file=$res
		:local cnt 0
		#:put "$cnt -> $FETCHRESULT"
		:while ($cnt<100 and $FETCHRESULT="none") do={ 
	 		:delay 1s
	 		:set $cnt ($cnt+1)
	 		#:put "$cnt -> $FETCHRESULT"
		}
		:local content [/file get [find name=$res] content]
		#:put $content
		if ($content~"finished") do={:return "success"}
		:return $FETCHRESULT
	}

	:global tgTrusted [:toarray $tgTrusted];
	:global tgBotAPI;
	:global tgStorage;
	:global tgTimeout;

	:put "cfg=$cfg"
	:put "trusted=$tgTrusted"
	:put "botID=$tgBotAPI"
	:put "storage=$tgStorage"
	:put "timeout=$tgTimeout"

	:local file ($tgStorage."tg_get_updates.txt")
	:local logfile ($tgStorage."tg_fetch_log.txt")
	#get 1 message per time
	:local url ("https://api.telegram.org/bot".$tgBotAPI."/getUpdates?timeout=$tgTimeout&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 [$tgGetkey key="message_id" text=$content]
	:if ($msgid="") do={ 
		:put "No new updates"
		:return 0 
	} else={
		:set tgLastMsgID $msgid
		:local updid [$tgGetkey key="update_id" text=$content]
		:set tgLastUPDID $updid

		:local tgFromID [$tgGetkey block="from" key="id" text=$content]
		:local tgUsername [$tgGetkey block="from" key="username" text=$content]
		:local tgFirstName [$tgGetkey block="from" key="first_name" text=$content]
		:local tgLastName [$tgGetkey block="from" key="last_name" text=$content]
		:local tgID [$tgGetkey block="chat" key="id" text=$content]
		:local tgMessage [$tgGetkey block="chat" key="text" text=$content]
		:local tgName "$tgFirstName $tgLastName"

		:put "message id=$msgid"
		:put "update id=$updid"
		:put "from id=$tgFromID"
		:put "first name=$tgFirstName"
		:put "last name=$tgLastName"
		:put "username=$tgUsername"
		:if ([:len $tgName]<2) do {
			:if  ([:len $tgUsername]>0) do={
				:set tgName $tgUsername
			} else={
				:set tgName "Unknown"
			}
		}
		:put "name=$tgName"
		:put "in chat=$tgID"
		:put "command=$tgMessage"

		:local allowed ( [:type [:find $tgTrusted $tgFromID]]!="nil" or [:type [:find $tgTrusted $tgID]]!="nil")
		:if (!$allowed) do={
			:put "Unknown sender, keep silence"
			:return -1
		} else={
			:local cmd ""
			:local params ""
			:local ltext [:len $tgMessage]

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

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

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

			: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=$tgID from=$tgName
		}
	}
}
tgSendMessage work from mikrotik's terminal command line, But from another script it's not running :\ Any idea why?

From mikrotik command line I wrote (this is work):
 [$tgSendMessage chat=XXXXXXXXX text="test message"]
From another script I wrote (this is not working :( ):
:global tgSendMessage
 [$tgSendMessage chat=XXXXXXXXX text="test message"]
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Tue Feb 13, 2018 1:07 pm

I'm trying to make telegram available by global (enviroment), This is the complete script:

tgSendMessage work from mikrotik's terminal command line, But from another script it's not running :\ Any idea why?
How do you call another script - from terminal manualy or , for example, via scheduler?
If from terminal you should see error messages to get issue why it happens.
PS: calling from another script are you 100% sure that needed globals exist? Due to globals live only by next reboot. It is the reason why I use "config" script.
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Tue Feb 13, 2018 5:58 pm

I'm trying to make telegram available by global (enviroment), This is the complete script:

tgSendMessage work from mikrotik's terminal command line, But from another script it's not running :\ Any idea why?
How do you call another script - from terminal manualy or , for example, via scheduler?
If from terminal you should see error messages to get issue why it happens.
PS: calling from another script are you 100% sure that needed globals exist? Due to globals live only by next reboot. It is the reason why I use "config" script.
Everything working... I modified your script, now it's create scheduler every 15mins check telegram updates and if telegram's global not exists create it...
integrated all command into one "telegram" global, commands:
Receive messages (get updates): $telegram / $telegram action=receive
Send messages: $telegram action=send chat=<id> text=<text> mode=<mode>

BTW- Added "if tg_cmd script not found, create temporary script running the incoming message as command", for example: if income message is "/interface disable ether1" the script will do it. -not sure how much it's secured, I'm still work on limitations

About the config script, you right. I'll move back to config script. about "telegram" global it's not problem, as I said the scheduler recreate global if not exists and check for updates.
:global tgBotAPI "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
:global tgDefaultChatID "AAAAAAAAA,BBBBBBBBB,CCCCCCCC"
:global tgTrusted "AAAAAAAAA,BBBBBBBBB,CCCCCCCC"
:global tgStorage ""
:global tgTimeout 1

/system scheduler add name=telegram interval=15m on-event="
:if ([:len [/system script environment find name=telegram]]=0) do={
	:global telegram do={
		#send message
		:local tgSendMessage do={
			:global tgBotAPI;
			:global tgStorage;
			:global tgDefaultChatID;
			:local tgID \$tgDefaultChatID

			:if ([:len \$chat]>0) do={ set tgID \$chat }

			:foreach chatID in=[:toarray \$tgID] do={
				:local fail false;
				:local url \"https://api.telegram.org/bot\$tgBotAPI/sendmessage\?chat_id=\$chatID&text=\$text\"
				:if ([:len \$mode]>0) do={:set url (\$url.\"&parse_mode=\$mode\")}
				:do {
					/tool fetch url=\$url keep-result=no
				} on-error={
					:log error \"failed to send telegram message to '\$chatID'.\"
					:set fail true;
				}
				:if (!\$fail) do={
					:log info \"telegram message has been sent to '\$chatID'\"
				}
			}
		}
		#receive message
		:local tgReceiveMessage do={
			:global tgLastMsgID
			:global tgLastUPDID

			:local tgGetkey do={
				:local cur 0
				:local lkey [:len \$key]
				:local res \"\"
				:local p

				:if ([:len \$block]>0) do={
	 				:set p [:find \$text \$block \$cur]
	 				:if ([:type \$p]=\"nil\") do={
			  			:return \$res
	 				}
	 				:set cur (\$p+[:len \$block]+2)
				}

				:set p [:find \$text \$key \$cur]
				:if ([:type \$p]!=\"nil\") do={
	 				:set cur (\$p+lkey+2)
	 				:set p [:find \$text \",\" \$cur]
	 				:if ([:type \$p]!=\"nil\") do={
	   					:if ([:pick \$text \$cur]=\"\\\"\") do={
	    					:set res [:pick \$text (\$cur+1) (\$p-1)]
	   					} else={
	    					:set res [:pick \$text \$cur \$p]
   						}
					}
				}
				:return \$res	
			}

			:local http do={
				:local res \"fetchRESULT.txt\"
				:if ([:len \$resfile]>0) do={:set res \$resfile}
				#:put \$res

				:local cmd \"/tool fetch\"
				:if ([:len \$mode]>0) do={:set cmd \"\$cmd mode=\$mode\"}
				:if ([:len \$upload]>0) do={:set cmd \"\$cmd upload=\$upload\"}
				:if ([:len \$user]>0) do={:set cmd \"\$cmd user=\\\"\$user\\\"\"}
				:if ([:len \$password]>0) do={:set cmd \"\$cmd password=\\\"\$password\\\"\"}
				:if ([:len \$address]>0) do={:set cmd \"\$cmd address=\\\"\$address\\\"\"}
				:if ([:len \$host]>0) do={:set cmd \"\$cmd host=\\\"\$host\\\"\"}
				:if ([:len \$\"http-data\"]>0) do={:set cmd \"\$cmd http-data=\\\"\$\"http-data\"\\\"\"}
				:if ([:len \$\"http-method\"]>0) do={:set cmd \"\$cmd http-method=\\\"\$\"http-method\"\\\"\"}
				:if ([:len \$\"check-certificate\"]>0) do={:set cmd \"\$cmd check-certificate=\\\"\$\"check-certificate\"\\\"\"}
				:if ([:len \$\"src-path\"]>0) do={:set cmd \"\$cmd src-path=\\\"\$\"src-path\"\\\"\"}
				:if ([:len \$\"dst-path\"]>0) do={:set cmd \"\$cmd dst-path=\\\"\$\"dst-path\"\\\"\"}
				:if ([:len \$ascii]>0) do={:set cmd \"\$cmd ascii=\\\"\$ascii\\\"\"}
				:if ([:len \$url]>0) do={:set cmd \"\$cmd url=\\\"\$url\\\"\"}

				:put \">> \$cmd\"

				:global fetchRESULT
				:set fetchRESULT \"none\"

				:local script \"\
	 			:global fetchRESULT;\
	 			:do {\
	   				\$cmd;\
	   				:set fetchRESULT \\\"success\\\";\
	 			} on-error={\
	  				:set fetchRESULT \\\"failed\\\";\
	 			}\
				\"
				:execute script=\$script file=\$res
				:local cnt 0
				#:put \"\$cnt -> \$fetchRESULT\"
				:while (\$cnt<100 and \$fetchRESULT=\"none\") do={ 
	 				:delay 1s
	 				:set \$cnt (\$cnt+1)
	 				#:put \"\$cnt -> \$fetchRESULT\"
				}
				:local content [/file get [find name=\$res] content]
				#:put \$content
				if (\$content~\"finished\") do={:return \"success\"}
				:return \$fetchRESULT
			}

			:global tgTrusted [:toarray \$tgTrusted];
			:global tgBotAPI;
			:global tgStorage;
			:global tgTimeout;

			:put \"cfg=\$cfg\"
			:put \"trusted=\$tgTrusted\"
			:put \"botID=\$tgBotAPI\"
			:put \"storage=\$tgStorage\"
			:put \"timeout=\$tgTimeout\"

			:local file (\$tgStorage.\"tg_get_updates.txt\")
			:local logfile (\$tgStorage.\"tg_fetch_log.txt\")
			#get 1 message per time
			:local url (\"https://api.telegram.org/bot\".\$tgBotAPI.\"/getUpdates?timeout=\$tgTimeout&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 [\$tgGetkey key=\"message_id\" text=\$content]
			:if (\$msgid=\"\") do={ 
				:put \"No new updates\"
				:return 0 
			} else={
				:set tgLastMsgID \$msgid
				:local updid [\$tgGetkey key=\"update_id\" text=\$content]
				:set tgLastUPDID \$updid

				:local tgFromID [\$tgGetkey block=\"from\" key=\"id\" text=\$content]
				:local tgUsername [\$tgGetkey block=\"from\" key=\"username\" text=\$content]
				:local tgFirstName [\$tgGetkey block=\"from\" key=\"first_name\" text=\$content]
				:local tgLastName [\$tgGetkey block=\"from\" key=\"last_name\" text=\$content]
				:local tgID [\$tgGetkey block=\"chat\" key=\"id\" text=\$content]
				:local tgMessage [\$tgGetkey block=\"chat\" key=\"text\" text=\$content]
				:local tgName \"\$tgFirstName \$tgLastName\"

				:put \"message id=\$msgid\"
				:put \"update id=\$updid\"
				:put \"from id=\$tgFromID\"
				:put \"first name=\$tgFirstName\"
				:put \"last name=\$tgLastName\"
				:put \"username=\$tgUsername\"
				:if ([:len \$tgName]<2) do {
					:if  ([:len \$tgUsername]>0) do={
						:set tgName \$tgUsername
					} else={
						:set tgName \"Unknown\"
					}
				}
				:put \"name=\$tgName\"
				:put \"in chat=\$tgID\"
				:put \"command=\$tgMessage\"

				:local allowed ( [:type [:find \$tgTrusted \$tgFromID]]!=\"nil\" or [:type [:find \$tgTrusted \$tgID]]!=\"nil\")
				:if (!\$allowed) do={
					:put \"Unknown sender, keep silence\"
					:return -1
				} else={
					:local cmd \"\"
					:local params \"\"
					:local ltext [:len \$tgMessage]

					:local pos [:find \$tgMessage \" \"]
					:if ([:type \$pos]=\"nil\") do={
						:set cmd [:pick \$tgMessage 1 \$ltext]
					} else={
						:set cmd [:pick \$tgMessage 1 \$pos]
						:set params [:pick \$tgMessage (\$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

					:if ([:len [/system script find name=\"tgCmd_\$cmd\"]]>0) do={
						:put \"Try to invoke external script tg_cmd_\$cmd\"
						:local script [:parse [/system script get \"tg_cmd_\$cmd\" source]]
						\$script params=\$params chatid=\$tgID from=\$tgName
					} else={
						:log warning \"command (\$tgMessage) has been received from '\$tgName' (\$tgID) via telegram\";
						:local tgScriptFile \"tgTemp\";
						:local tgScriptSource (\"
							:global tgSendMessage
							:local tgSend \\\$tgSendMessage

							:do {
								:local fail false;
								\$tgMessage
							} on-error={
								:set \\\$fail true;
							}

							:if (!\\\$fail) do={
								\\\$tgSend chat=\$tgID text=\\\"Command '\$tgMessage' has been done.\\\"
								:log warning \\\"telegram command '\$tgMessage' received from '\$tgName' (\$tgID) has been done.\\\"
							} else={
								\\\$tgSend chat=\$tgID text=\\\"Error command '\$tgMessage'.\\\"
								:log error \\\"telegram command '\$tgMessage' received from '\$tgName' (\$tgID) has been failed.\\\"
							}
							/system script remove [/system script find name=\\\"\$tgScriptFile\\\"]
						\")
						/system script add name=\$tgScriptFile source=\$tgScriptSource;
						/system script run \$tgScriptFile;
					}
				}
			}
			/system script environment remove [/system script environment find name=\"fetchRESULT\"];
		}

		:if (([:len \$action]=0) or (\$action=\"receive\")) do={
			\$tgReceiveMessage;
		} else={
			:if (\$action=\"send\") do={
				\$tgSendMessage chat=\$chat text=\$text;
			}
		}
	}
}

:global telegram
\$telegram
"
:execute script=[/system scheduler get value-name=on-event telegram]
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Wed Feb 14, 2018 1:58 am

Any idea how to build string for telegram message (new line and etc,,..), for example I would like to do foreach on every hotspot active connection create $str and send it by telegram message...


Attached example code that I would like to send, I'm getting failed when I'm trying to send $mailBody via telegram message...
I'm think that because I used '\n' for newline... anything I can do to send it? any alternative to '\n' ?
:foreach userIndex in=[/ip hotspot user find profile=generated and server=guests] do={
  :local loginName [/ip hotspot user get value-name=name $userIndex];
  :local loginPass [/ip hotspot user get value-name=password $userIndex];
  :local loginMAC [/ip hotspot user get value-name=mac-address $userIndex];
  :local loginComment [/ip hotspot user get value-name=comment $userIndex];
  :if ([:len [:find [/ip hotspot user get value-name=comment $userIndex] "last connection was at"]]>0) do={
    :local loginLastTime [:pick [/ip hotspot user get value-name=comment $userIndex] ([:find [/ip hotspot user get value-name=comment $userIndex] "last connection was at"]+23) ([:find [/ip hotspot user get value-name=comment $userIndex] "last connection was at"]+23+11)];
    :local loginDaysAgo [$calcDays $loginLastTime [/system clock get date]];
    :set loginComment [:pick [/ip hotspot user get value-name=comment $userIndex] 0 ([:find [/ip hotspot user get value-name=comment $userIndex] "last connection was at"]-2)];
    :if ($loginDaysAgo>30) do={
      /ip hotspot user remove $userIndex;
      :log warning "The user '$loginName' was removed. The account not being use more then 30 days.";
      :set loginComment "<expired>";
      :set mailSend true;
    }
    :set loginComment ($loginComment."\nLast seen: $loginLastTime ($loginDaysAgo days ago)");
  }
  :if ([:len $loginMAC]>0) do={
    :set mailBody ($mailBody."\nUsername: $loginName\nPassword: $loginPass\nMAC Address: $loginMAC\nComment: $loginComment\n");
  } else={
    :set loginMAC "<unsigned>";
    :set mailBody ("\nUsername: $loginName\nPassword: $loginPass\nMAC Address: $loginMAC\nComment: $loginComment\n".$mailBody);
  }
}
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Feb 14, 2018 1:01 pm

Everything working... I modified your script...
This forum needs "Like" button %) Good job!
 
User avatar
BlackVS
Member Candidate
Member Candidate
Topic Author
Posts: 165
Joined: Mon Feb 04, 2013 7:00 pm
Contact:

Re: Mikrotik and Telegram

Wed Feb 14, 2018 1:06 pm

Any idea how to build string for telegram message (new line and etc,,..), for example I would like to do foreach on every hotspot active connection create $str and send it by telegram message...
Check tg_cmd_health code for multi-line.
If shortly - new line is coded as "%0A" not "\n". It is from URL encoding rules.
Also check https://core.telegram.org/bots/api#markdown-style (markdown style) for simplified formatting in Telegram.
 
zivtal
newbie
Posts: 46
Joined: Sun Feb 05, 2017 6:22 pm

Re: Mikrotik and Telegram

Fri Feb 16, 2018 8:36 am

Great thanks ! Started to work on addons (cmd): viewtopic.php?f=9&t=130984
CCR1009-8G-S+S+PC | RB962UiGS-5HacT2HnT | RBOmniTikPG-5HacD | RB750Gr3 | RBwAPG-5HacT2HnD
 
doblonk
just joined
Posts: 1
Joined: Thu Aug 02, 2018 3:06 am

Re: Mikrotik and Telegram

Sat Sep 01, 2018 9:08 pm

Hi,

Script is work.
When I run script from terminal I get message in Telegram.
But when I reply /hi and /health, bot not respond.
Please someone help me :)
 
Xi2
just joined
Posts: 2
Joined: Sat Jul 27, 2013 3:05 pm

Re: Mikrotik and Telegram

Mon Oct 01, 2018 8:57 am

Hi!
Have tested the script and got an answer on Hi command from bot:

Code: Select all

Hi \u0421\u0435\u0440\u0433\u0435\u0439 , how are you?

Who is online

Users browsing this forum: No registered users and 11 guests