åæžãïŒ
ç§ã¯ãã®èšäºã®å·çãé·ãé延æããŸããããTelegramã¡ãã»ã³ãžã£ãŒããããæè¿ã®åºæ¥äºã¯ãç§ã®èšç»ãåŒãç¶ãããã®æ°ãããšãã«ã®ãŒã§ç§ãåºæ¿ããŸããã Telegramã¯ããšããããæ å ±ã€ã³ã¿ã©ã¯ãã£ããµãŒãã¹ã®ããã®äŸ¿å©ãªããããã©ãããã©ãŒã ã§ããã人çºçãªå¶éãªãã«ä»ã®ã·ã¹ãã ãšå ±åãã競åããå¿ èŠããããšæããŸãã ãã®èšäºãTelegramã®ãµããŒããžã®ãããããªè²¢ç®ãšããŸãããã
質åã«çããåã«ãWebhookãæ©èœããããã«ããããã©ãããã©ãŒã ã«æäœéå¿ èŠãªãã®ãç解ããå¿ èŠããããŸãã SSLã䜿çšããWEBãµãŒããŒã®ååšãæå¹ãªSSL蚌ææžããŸãã¯Telegram APIã«èªã¿èŸŒãŸããèªå·±çœ²å蚌ææžãWebhookãåŠçããããã®WEBãµãŒããŒã®URLã ãŸããã€ã³ã¿ãŒãããïŒå®éã®IPããã¡ã€ã³åïŒããã«ãŒã¿ãŒãžã®ã¢ã¯ã»ã¹ãæäŸã§ããå ŽåãMikrotikã«ã¯WEBãµãŒããŒã«åé¡ãããïŒSSLããªããªããŸãïŒããŠãŒã¶ãŒãµãŒããŒã¯ãããŸããã ãããããã®åé¡ã¯åé¿ã§ããŸãã解決çã以äžã«ææ¡ããŸãã
Mikrotikã®Telegramãããã¯ããæ°·å±±ã®äžè§ãã«ãããŸããã ããã¯ãMikrotikã¹ã¯ãªããèšèªã§èšè¿°ãããïŒå¯èœãªéãïŒæ¬æ ŒçãªJSONããŒãµãŒã«åºã¥ããŠããŸãã äžè¬ã«ãå¹³åçãªããããèšè¿°ããããã«ãJSONã®å®å šãªåæãè¡ãå¿ èŠã¯ãããŸãããå®å šã«ç®¡çããŠè¡ãã³ããŒã§ããŸãããå¥ã®ãã¹ãéžæããŸããã 次ã«ãããŒãµãŒãšãäœæ¥äžã«ãã¹ã¿ãŒãããMikrotikã¹ã¯ãªããã®ããã°ã©ãã³ã°ææ³ã«ã€ããŠèª¬æããŸãã
Mikrotikèšèªã®ããŒãµãŒJSONæåå
Mikrotikã¹ã¯ãªããèšèªã§JSONããŒãµãŒãäœæããããšã¯ç§ã«ãšã£ãŠã¹ããŒãã§ããã Mikrotikã¹ã¯ãªããèšèªã®å¶éãèãããšãããããŸã£ããå¯èœãã©ããã¯é¢çœãã£ãã§ãã ããããã³ãŒãã®å¥¥ã«è¡ãã»ã©ãæçµç®æšãžã®éãã¯ã£ãããšèŠããŠããŸããã 以åãç§ã¯1ã€ã®SCADAã·ã¹ãã ã®ããŒãºã®ããã«ããªãŒãã³ã¹ããŒã¹ã«ããVBScriptã®åæ§ã®ããŒãµãŒãæãæµ®ãã¹ãŸããããã®ããããã®VBScriptå®è£ ã®ããžãã¯ãåºç€ãšããŠãMikrotikèšèªã®æ§ç¯ãèæ ®ããŠåŠçããé¢æ°ã®ã©ã€ãã©ãªã®åœ¢ã§ã³ãŒããèšèšããŸããã ãã®éçšã§ãã¹ã¯ãªããèšèªã®èå³æ·±ãæ©èœãããã€ãçºèŠããŸãããããã«ã€ããŠã¯ã以äžã§åãã§å ±æããŸãã å¶éäºé ã«ã€ããŠäžèšã ãŸããMikrotikå€æ°ã®æååã®é·ãã¯4096ãã€ãã§ããäœãããå¿ èŠã¯ãããŸããããã¹ãŠã®å€æ°ã¯ãã¯ãå€æ°ã«å²ãåœãŠãããŠããŸããã 2çªç®ïŒMikrotikã¯å®æ°ã«ã€ããŠäœãç¥ããªããããããŒãµãŒã¯floatãæååå€æ°ãšããŠä¿åããŸããboolãintãstringåã¯éåžžãå éšè¡šçŸã«è§£æãããŸãã
JSONããŒãµãŒã䜿çšãã
é¢æ°ã¯ãé¢æ°ã³ãŒããã°ããŒãã«å€æ°ã«ãæ¡åŒµãããJParseFunctionsã©ã€ãã©ãªãã¡ã€ã«ã«ãã£ãŠè¡šãããŸãã ãã®ã©ã€ãã©ãªã¯ãããã©ãŒãã³ã¹ãå€§å¹ ã«äœäžãããããšãªããã¹ã¯ãªããå ã§äœåºŠã§ãåŒã³åºãããšãã§ããŸããåé¢æ°ã«ã€ããŠãã¢ã¯ã·ã§ã³ã®éè€ãé¿ããããã«ã°ããŒãã«å€æ°ã®ãæ¡åŒµãããã§ãã¯ãããŸãã ã©ã€ãã©ãªãã¡ã€ã«ãç·šéãããšãã¯ãã°ããŒãã«å€æ°ïŒé¢æ°ã³ãŒãïŒãåé€ããŠãæŽæ°ã§ãåäœæãããå¿ èŠããããŸãã
JParseFunctionsã©ã€ãã©ãªã³ãŒãïŒ
JParseFunctions
# -------------------------------- JParseFunctions --------------------------------------------------- # ------------------------------- fJParsePrint ---------------------------------------------------------------- :global fJParsePrint :if (!any $fJParsePrint) do={ :global fJParsePrint do={ :global JParseOut :local TempPath :global fJParsePrint :if ([:len $1] = 0) do={ :set $1 "\$JParseOut" :set $2 $JParseOut } :foreach k,v in=$2 do={ :if ([:typeof $k] = "str") do={ :set k "\"$k\"" } :set TempPath ($1. "->" . $k) :if ([:typeof $v] = "array") do={ :if ([:len $v] > 0) do={ $fJParsePrint $TempPath $v } else={ :put "$TempPath = [] ($[:typeof $v])" } } else={ :put "$TempPath = $v ($[:typeof $v])" } } }} # ------------------------------- fJParsePrintVar ---------------------------------------------------------------- :global fJParsePrintVar :if (!any $fJParsePrintVar) do={ :global fJParsePrintVar do={ :global JParseOut :local TempPath :global fJParsePrintVar :local fJParsePrintRet "" :if ([:len $1] = 0) do={ :set $1 "\$JParseOut" :set $2 $JParseOut } :foreach k,v in=$2 do={ :if ([:typeof $k] = "str") do={ :set k "\"$k\"" } :set TempPath ($1. "->" . $k) :if ($fJParsePrintRet != "") do={ :set fJParsePrintRet ($fJParsePrintRet . "\r\n") } :if ([:typeof $v] = "array") do={ :if ([:len $v] > 0) do={ :set fJParsePrintRet ($fJParsePrintRet . [$fJParsePrintVar $TempPath $v]) } else={ :set fJParsePrintRet ($fJParsePrintRet . "$TempPath = [] ($[:typeof $v])") } } else={ :set fJParsePrintRet ($fJParsePrintRet . "$TempPath = $v ($[:typeof $v])") } } :return $fJParsePrintRet }} # ------------------------------- fJSkipWhitespace ---------------------------------------------------------------- :global fJSkipWhitespace :if (!any $fJSkipWhitespace) do={ :global fJSkipWhitespace do={ :global Jpos :global JSONIn :global Jdebug :while ($Jpos < [:len $JSONIn] and ([:pick $JSONIn $Jpos] ~ "[ \r\n\t]")) do={ :set Jpos ($Jpos + 1) } :if ($Jdebug) do={:put "fJSkipWhitespace: Jpos=$Jpos Char=$[:pick $JSONIn $Jpos]"} }} # -------------------------------- fJParse --------------------------------------------------------------- :global fJParse :if (!any $fJParse) do={ :global fJParse do={ :global Jpos :global JSONIn :global Jdebug :global fJSkipWhitespace :local Char :if (!$1) do={ :set Jpos 0 } $fJSkipWhitespace :set Char [:pick $JSONIn $Jpos] :if ($Jdebug) do={:put "fJParse: Jpos=$Jpos Char=$Char"} :if ($Char="{") do={ :set Jpos ($Jpos + 1) :global fJParseObject :return [$fJParseObject] } else={ :if ($Char="[") do={ :set Jpos ($Jpos + 1) :global fJParseArray :return [$fJParseArray] } else={ :if ($Char="\"") do={ :set Jpos ($Jpos + 1) :global fJParseString :return [$fJParseString] } else={ # :if ([:pick $JSONIn $Jpos ($Jpos+2)]~"^-\?[0-9]") do={ :if ($Char~"[eE0-9.+-]") do={ :global fJParseNumber :return [$fJParseNumber] } else={ :if ($Char="n" and [:pick $JSONIn $Jpos ($Jpos+4)]="null") do={ :set Jpos ($Jpos + 4) :return [] } else={ :if ($Char="t" and [:pick $JSONIn $Jpos ($Jpos+4)]="true") do={ :set Jpos ($Jpos + 4) :return true } else={ :if ($Char="f" and [:pick $JSONIn $Jpos ($Jpos+5)]="false") do={ :set Jpos ($Jpos + 5) :return false } else={ :put "Err.Raise 8732. No JSON object could be fJParseed" :set Jpos ($Jpos + 1) :return [] } } } } } } } }} #-------------------------------- fJParseString --------------------------------------------------------------- :global fJParseString :if (!any $fJParseString) do={ :global fJParseString do={ :global Jpos :global JSONIn :global Jdebug :global fUnicodeToUTF8 :local Char :local StartIdx :local Char2 :local TempString "" :local UTFCode :local Unicode :set StartIdx $Jpos :set Char [:pick $JSONIn $Jpos] :if ($Jdebug) do={:put "fJParseString: Jpos=$Jpos Char=$Char"} :while ($Jpos < [:len $JSONIn] and $Char != "\"") do={ :if ($Char="\\") do={ :set Char2 [:pick $JSONIn ($Jpos + 1)] :if ($Char2 = "u") do={ :set UTFCode [:tonum "0x$[:pick $JSONIn ($Jpos+2) ($Jpos+6)]"] :if ($UTFCode>=0xD800 and $UTFCode<=0xDFFF) do={ # Surrogate pair :set Unicode (($UTFCode & 0x3FF) << 10) :set UTFCode [:tonum "0x$[:pick $JSONIn ($Jpos+8) ($Jpos+12)]"] :set Unicode ($Unicode | ($UTFCode & 0x3FF) | 0x10000) :set TempString ($TempString . [:pick $JSONIn $StartIdx $Jpos] . [$fUnicodeToUTF8 $Unicode]) :set Jpos ($Jpos + 12) } else= { # Basic Multilingual Plane (BMP) :set Unicode $UTFCode :set TempString ($TempString . [:pick $JSONIn $StartIdx $Jpos] . [$fUnicodeToUTF8 $Unicode]) :set Jpos ($Jpos + 6) } :set StartIdx $Jpos :if ($Jdebug) do={:put "fJParseString Unicode: $Unicode"} } else={ :if ($Char2 ~ "[\\bfnrt\"]") do={ :if ($Jdebug) do={:put "fJParseString escape: Char+Char2 $Char$Char2"} :set TempString ($TempString . [:pick $JSONIn $StartIdx $Jpos] . [[:parse "(\"\\$Char2\")"]]) :set Jpos ($Jpos + 2) :set StartIdx $Jpos } else={ :if ($Char2 = "/") do={ :if ($Jdebug) do={:put "fJParseString /: Char+Char2 $Char$Char2"} :set TempString ($TempString . [:pick $JSONIn $StartIdx $Jpos] . "/") :set Jpos ($Jpos + 2) :set StartIdx $Jpos } else={ :put "Err.Raise 8732. Invalid escape" :set Jpos ($Jpos + 2) } } } } else={ :set Jpos ($Jpos + 1) } :set Char [:pick $JSONIn $Jpos] } :set TempString ($TempString . [:pick $JSONIn $StartIdx $Jpos]) :set Jpos ($Jpos + 1) :if ($Jdebug) do={:put "fJParseString: $TempString"} :return $TempString }} #-------------------------------- fJParseNumber --------------------------------------------------------------- :global fJParseNumber :if (!any $fJParseNumber) do={ :global fJParseNumber do={ :global Jpos :local StartIdx :global JSONIn :global Jdebug :local NumberString :local Number :set StartIdx $Jpos :set Jpos ($Jpos + 1) :while ($Jpos < [:len $JSONIn] and [:pick $JSONIn $Jpos]~"[eE0-9.+-]") do={ :set Jpos ($Jpos + 1) } :set NumberString [:pick $JSONIn $StartIdx $Jpos] :set Number [:tonum $NumberString] :if ([:typeof $Number] = "num") do={ :if ($Jdebug) do={:put "fJParseNumber: StartIdx=$StartIdx Jpos=$Jpos $Number ($[:typeof $Number])"} :return $Number } else={ :if ($Jdebug) do={:put "fJParseNumber: StartIdx=$StartIdx Jpos=$Jpos $NumberString ($[:typeof $NumberString])"} :return $NumberString } }} #-------------------------------- fJParseArray --------------------------------------------------------------- :global fJParseArray :if (!any $fJParseArray) do={ :global fJParseArray do={ :global Jpos :global JSONIn :global Jdebug :global fJParse :global fJSkipWhitespace :local Value :local ParseArrayRet [:toarray ""] $fJSkipWhitespace :while ($Jpos < [:len $JSONIn] and [:pick $JSONIn $Jpos]!= "]") do={ :set Value [$fJParse true] :set ($ParseArrayRet->([:len $ParseArrayRet])) $Value :if ($Jdebug) do={:put "fJParseArray: Value="; :put $Value} $fJSkipWhitespace :if ([:pick $JSONIn $Jpos] = ",") do={ :set Jpos ($Jpos + 1) $fJSkipWhitespace } } :set Jpos ($Jpos + 1) # :if ($Jdebug) do={:put "ParseArrayRet: "; :put $ParseArrayRet} :return $ParseArrayRet }} # -------------------------------- fJParseObject --------------------------------------------------------------- :global fJParseObject :if (!any $fJParseObject) do={ :global fJParseObject do={ :global Jpos :global JSONIn :global Jdebug :global fJSkipWhitespace :global fJParseString :global fJParse # Syntax :local ParseObjectRet ({}) don't work in recursive call, use [:toarray ""] for empty array!!! :local ParseObjectRet [:toarray ""] :local Key :local Value :local ExitDo false $fJSkipWhitespace :while ($Jpos < [:len $JSONIn] and [:pick $JSONIn $Jpos]!="}" and !$ExitDo) do={ :if ([:pick $JSONIn $Jpos]!="\"") do={ :put "Err.Raise 8732. Expecting property name" :set ExitDo true } else={ :set Jpos ($Jpos + 1) :set Key [$fJParseString] $fJSkipWhitespace :if ([:pick $JSONIn $Jpos] != ":") do={ :put "Err.Raise 8732. Expecting : delimiter" :set ExitDo true } else={ :set Jpos ($Jpos + 1) :set Value [$fJParse true] :set ($ParseObjectRet->$Key) $Value :if ($Jdebug) do={:put "fJParseObject: Key=$Key Value="; :put $Value} $fJSkipWhitespace :if ([:pick $JSONIn $Jpos]=",") do={ :set Jpos ($Jpos + 1) $fJSkipWhitespace } } } } :set Jpos ($Jpos + 1) # :if ($Jdebug) do={:put "ParseObjectRet: "; :put $ParseObjectRet} :return $ParseObjectRet }} # ------------------- fByteToEscapeChar ---------------------- :global fByteToEscapeChar :if (!any $fByteToEscapeChar) do={ :global fByteToEscapeChar do={ # :set $1 [:tonum $1] :return [[:parse "(\"\\$[:pick "0123456789ABCDEF" (($1 >> 4) & 0xF)]$[:pick "0123456789ABCDEF" ($1 & 0xF)]\")"]] }} # ------------------- fUnicodeToUTF8---------------------- :global fUnicodeToUTF8 :if (!any $fUnicodeToUTF8) do={ :global fUnicodeToUTF8 do={ :global fByteToEscapeChar # :local Ubytes [:tonum $1] :local Nbyte :local EscapeStr "" :if ($1 < 0x80) do={ :set EscapeStr [$fByteToEscapeChar $1] } else={ :if ($1 < 0x800) do={ :set Nbyte 2 } else={ :if ($1 < 0x10000) do={ :set Nbyte 3 } else={ :if ($1 < 0x20000) do={ :set Nbyte 4 } else={ :if ($1 < 0x4000000) do={ :set Nbyte 5 } else={ :if ($1 < 0x80000000) do={ :set Nbyte 6 } } } } } :for i from=2 to=$Nbyte do={ :set EscapeStr ([$fByteToEscapeChar ($1 & 0x3F | 0x80)] . $EscapeStr) :set $1 ($1 >> 6) } :set EscapeStr ([$fByteToEscapeChar (((0xFF00 >> $Nbyte) & 0xFF) | $1)] . $EscapeStr) } :return $EscapeStr }} # ------------------- End JParseFunctions----------------------
ãã¬ã°ã©ã ãããã³ãŒãã®äŸã䜿çšããŠãããŒãµãŒã®äœæ¥ãæ€èšããŸãã 次ã®ã³ãã³ãã段éçã«å®è¡ããŠã¿ãŸãããã
j.txtãã¡ã€ã«ã§JSONæååãè¿ãgetWebhookInfo Telegram APIé¢æ°ã®ã¹ããŒã¿ã¹ãèŠæ±ããŸãã
:do {/tool fetch url="https://api.telegram.org/bot$TToken/getWebhookInfo" dst-path=j.txt} on-error={:put "getWebhookInfo error"};
[admin@MikroTik] > :put [/file get j.txt contents]; {"ok":true,"result":{"url":"https://*****:8443","has_custom_certificate":false,"pending_update_count":0,"last_error_date":1524565055,"last_error_message":"Connection timed out","max_connections":4 0}}
JSONæååãå ¥åå€æ°ã«ããŒãããïŒ
:set JSONIn [/file get j.txt contents]
$ fJParseããŒãµãŒé¢æ°ãå®è¡ããçµæã$ JParseOutå€æ°ã«ã¢ããããŒããã
:set JParseOut [$fJParse];
$ JParseOutã«ã¯ãå ã®JSONæååããMikrotiké åããã³ããŒã¿åãžã®ãããã³ã°ã§ããé£æ³é åããããŸãã ããã§ã¯ã³ã³ãã³ããæäŸããŸããã以äžã«ç€ºããŸãã
ã°ããŒãã«å€æ°$ JdebugïŒtrueïŒãèšå®ããŠãããæåã¢ãŒãã§ã«ãŒã¿ãŒã®ã³ã³ãœãŒã«ã§é¢æ°ãåŒã³åºããšããããã°ã®å¿ èŠã«å¿ããŠè¿œå ã®åºåãååŸã§ããŸãã
å€æ¬¡å é£æ³é å
Mikrotikã¯ããã¹ããããïŒå€æ¬¡å ïŒé£æ³é åããµããŒãããŠããŸãã
以äžã¯ãããŒãµãŒã®çµæãæžã蟌ãŸããã°ããŒãã«å€æ°$ JParseOutã®åºåäŸã§ãã
[admin@MikroTik] > :put $JParseOut ok=true;result=has_custom_certificate=false;max_connections=40;pending_update_count=0;url=https://*****.ru:8443
[admin@MikroTik] > :put ($JParseOut->"result") has_custom_certificate=false;max_connections=40;pending_update_count=0;url=https://*****:8443
[admin@MikroTik] > :put ($JParseOut->"result"->"max_connections") 40
ããŒã®ãçµæãã«ã¯å€ãšããŠé£æ³é åãå«ãŸããŠãããã->ããã§ãŒã³ã䜿çšããŠãã®èŠçŽ ã«å°éã§ããããšãããããŸãã ããã«ããã¹ãŠã®èŠçŽ ãç¬èªã®ããŒã¿åïŒæ°å€ãæååãããŒã«å€ãé åïŒãæã€ããšãéèŠã§ãã
[admin@MikroTik] > :put [:typeof ($JParseOut->"result")] array
[admin@MikroTik] > :put [:typeof ($JParseOut->"result"->"max_connections")] num
[admin@MikroTik] > :put [:typeof ($JParseOut->"result"->"url")] str
JSONããŒãµãŒãäœæãããšããã¢ã€ãã¢ãä¿ããã®ã¯ããã®ãã«ãã¬ãã«ã®æ§ç¯ã®å®éšã§ããã JSON圢åŒã¯ãMikrotikã¹ã¯ãªããèšèªã®ãã®ãããªå éšè¡šçŸã«ããŸãå€æãããŸãã
é¢æ°ãååž°åŒã³åºã
å€ãã®å Žåãç¬èªã®æ©èœãå®çŸ©ã§ããã®ã¯ç§å¯ã§ã¯ãããŸãã;ãã©ãŒã©ã ãµã€ãwww.mikrotik.comã§ããã®ãããªèšèšã®å€ãã®äŸãèŠã€ããããšãã§ããŸãã ç§ã®ããŒãµãŒã¯ãé¢æ°ããã¹ããããååž°çãªåŒã³åºãã«ãåºã¥ããŠããŸãã ã¯ããååž°çãªé¢æ°åŒã³åºãããµããŒããããŠããŸãïŒ
äŸãšããŠãé£æ³é å$ JParseOutã®å 容ïŒãŸãã¯ãã¹ã¯ãªããã§ã³ããŒããŠé åã®èŠçŽ ã«ã¢ã¯ã»ã¹ããããã«äœ¿çšã§ãããã¹ã®åœ¢åŒïŒãšãã®åŠççµæãå°å·ããããŒãµãŒã»ããã®$ fJParsePrinté¢æ°ã瀺ããŸãã
:global fJParsePrint :if (!any $fJParsePrint) do={ :global fJParsePrint do={ :global JParseOut :local TempPath :global fJParsePrint :if ([:len $1] = 0) do={ :set $1 "\$JParseOut" :set $2 $JParseOut } :foreach k,v in=$2 do={ :if ([:typeof $k] = "str") do={ :set k "\"$k\"" } :set TempPath ($1. "->" . $k) :if ([:typeof $v] = "array") do={ :if ([:len $v] > 0) do={ $fJParsePrint $TempPath $v } else={ :put "$TempPath = [] ($[:typeof $v])" } } else={ :put "$TempPath = $v ($[:typeof $v])" } } }}
[admin@MikroTik] > $fJParsePrint $JParseOut->"ok" = true (bool) $JParseOut->"result"->"has_custom_certificate" = false (bool) $JParseOut->"result"->"last_error_date" = 1524483204 (num) $JParseOut->"result"->"last_error_message" = Connection timed out (str) $JParseOut->"result"->"max_connections" = 40 (num) $JParseOut->"result"->"pending_update_count" = 0 (num) $JParseOut->"result"->"url" = https://*****.ru:8443 (str)
çŸåšã®æ·»ä»ãã¡ã€ã«ã®ã¬ãã«ãšãµãé åèŠçŽ ãé¢æ°ã«æž¡ãé¢æ°ã³ãŒãã§ååž°åŒã³åºãã確èªã§ããŸããããã«ããã$ JParseOutå€æ°ã§é åããªãŒå šäœãèµ°æ»ããŸãã
$fJParsePrint $TempPath $v
èå³æ·±ãããšã«ãã³ã³ãœãŒã«ãããã©ã¡ãŒã¿ãŒãæå®ããŠãã®é¢æ°ãåŒã³åºããåæåºåãã¹ïŒãhomeããªã©ïŒãšé åå€æ°ãæåã§æå®ã§ããŸãã
[admin@MikroTik] > $fJParsePrint "home" $JParseOut home->"ok" = true (bool) home->"result"->"has_custom_certificate" = false (bool) home->"result"->"last_error_date" = 1524483204 (num) home->"result"->"last_error_message" = Connection timed out (str) home->"result"->"max_connections" = 40 (num) home->"result"->"pending_update_count" = 0 (num) home->"result"->"url" = https://*****.ru:8443 (str)
ãã®é¢æ°ã¯ããã©ã¡ãŒã¿ãŒãããšãã©ã¡ãŒã¿ãŒãªãã®åŒã³åºããåŠçããããã«èšè¿°ãããŠããŸãã å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã䜿çšãããŸãã åŸæ¥ãåŒã³åºãåã«ããããã¯å ããã®å Žåã¯é¢æ°ã®æ¬äœã§ã°ããŒãã«å€æ°ãšé¢æ°ã宣èšããïŒãŸãã¯å®£èšããïŒå¿ èŠããããŸãã ãïŒglobal fJParsePrintããšãã宣èšãååšããããšã«æ³šæããŠãã ããã é¢æ°èªäœã宣èšãããŠãããååž°åŒã³åºãã«å¿ èŠãªã®ãåœç¶ã§ãã
ããªã³ã¶ãã©ã€ãã³ãŒããšãã®å®è¡ã§è¡ã解æãã
$ fByteToEscapeCharé¢æ°ãèŠãŠã¿ãŸãããïŒ
:global fByteToEscapeChar :if (!any $fByteToEscapeChar) do={ :global fByteToEscapeChar do={ # :set $1 [:tonum $1] :return [[:parse "(\"\\$[:pick "0123456789ABCDEF" (($1 >> 4) & 0xF)]$[:pick "0123456789ABCDEF" ($1 & 0xF)]\")"]] }}
ãã®é¢æ°ã¯ããã©ã¡ãŒã¿ãŒ$ 1ïŒãã€ãæ°ïŒãæååæåã«å€æããŸãã ASCIIã³ãŒããæåã«å€æããŸãã ããšãã°ãèšå·ã+ãã«å¯Ÿå¿ããã³ãŒã0x2BããããŸãã ãšã¹ã±ãŒã "\ NN"ã䜿çšããŠæåã³ãŒããæå®ã§ããŸããNNã¯ASCIIã³ãŒãã§ããã次ã®è¡ã®ã¿ã§ãã
[admin@MikroTik] > :put "\2B" +
ãããããœãŒã¹ã³ãŒããæ°åïŒãã€ãïŒã§è¡šãããŠããå ŽåãæåãååŸããããšã¯ç°¡åãªäœæ¥ã§ã¯ãããŸãããããã«ã¯ãæ¢è£œã®çµã¿èŸŒã¿é¢æ°ããªãããã§ãã ããã§ãå¥ã®çµã¿èŸŒã¿è§£æé¢æ°ã圹ç«ã¡ãŸããããã«ãããæååãåéã§ããŸããããã¯ããïŒ\ 2BïŒããªã©ã®å ã®æ°å€ã«åºã¥ããŠã·ãŒã±ã³ã¹ãå¶åŸ¡ããåŒã§ãã
ãã©ãŒã ã®è¡šçŸïŒ
:put [:parse "(\"\\$[:pick "0123456789ABCDEF" ((0x2B >> 4) & 0xF)]$[:pick "0123456789ABCDEF" (0x2B & 0xF)]\")"] (<%% + )
-åºåã§æååæåãååŸããããã«å®è¡ããå¿ èŠãããã³ãŒãè¡ãåéããŸãã 解æåŸã«åãåã£ãã³ãŒãã®2åç®ã®å®è¡ã¯ãåãè§æ¬åŒ§[...]ã䜿çšããŠè¡ããããããæçµåŒã¯ããè€éãªå€èŠ³ãåããäºéè§æ¬åŒ§[[...]]ã§ãã¬ãŒãã³ã°ããŸãã
[admin@MikroTik] > :put [[:parse "(\"\\$[:pick "0123456789ABCDEF" ((0x2B >> 4) & 0xF)]$[:pick "0123456789ABCDEF" (0x2B & 0xF)]\")"]] +
JSONããŒãµãŒã«åºã¥ããã¬ã°ã©ã ããã
ããŒãªã³ã°ããã
Telegram APIããJSONå¿çã®ã³ã³ãã³ãã«ç°¡åã«ã¢ã¯ã»ã¹ã§ããããã«ãªã£ãã®ã§ãããŒãªã³ã°ã¢ãŒãã§åäœãããããã®æåã®ããŒãžã§ã³ãã€ãŸã Telegram APIã®å®æçãªãªã¯ãšã¹ãã ããšãã°ãuptime-ã«ãŒã¿ãŒã®åäœæéã®èŠæ±ãip-ãã¹ãŠã®DHCPã¯ã©ã€ã¢ã³ãIPã¢ãã¬ã¹ã®èŠæ±ãparse-å€æ°$ JParseOutã®å 容ã®è¡šç€ºãã€ãŸã æåŸã®ãªã¯ãšã¹ãã«å¯Ÿãã解æãããJSONã¬ã¹ãã³ã¹ã ä»ã®ã³ãã³ããæåãå ¥åãããšããããã¯åã«ãšã³ãŒããŸãã
ãã®ãããã¯ã1åã«1åãªã©ãã¹ã±ãžã¥ãŒã©ããå®æçã«åŒã³åºãããgetUpdatesãã¬ã°ã©ã APIé¢æ°ãèªã¿åã1ã€ã®ã¹ã¯ãªããã§ããå¿çã解æããåŸãif-elseã¯å€æ°$ v-> "message"-> "text"ã®ã¢ã¯ã·ã§ã³ãéžæããŸãã ãŸãã$ JParseOutã®å 容ãèªã¿åãå¯èœãªåœ¢åŒã§è¿ãäžé£ã®ããŒãµãŒé¢æ°ããã®é¢æ° "text = $ [$ fJParsePrintVar]"ã®åŒã³åºãã«ã泚æãæããããšæããŸãã å®å šãªãããã³ãŒãã以äžã«ç€ºããŸãã
é·æããïŒã¹ã¯ãªããã亀æãéå§ãããããèšå®ãªãã§NATãä»ããŠæ©èœããŸãã
ãã®å®è£ ã®æ¬ ç¹ïŒèŠæ±ã«å¯ŸããMikrotikã®å¿çé床ã¯ãã¹ã¯ãªããåŒã³åºãã®é »åºŠã«ãã£ãŠæ±ºãŸããŸããååŒã³åºãã§getUpdatesèŠæ±ãå®è¡ãããäžè¬ã«ãããã»ããµãããŒãããå®å šãªèŠæ±åæãµã€ã¯ã«ã解æããŸãã ååŒã³åºãã¯j.txtãã¡ã€ã«ã®æžã蟌ã¿ã«ã€ãªãããŸãããã©ãã·ã¥ãã©ã€ãäžã®ããŒãã£ã·ã§ã³ã®å Žåãããã¯æªãããšã§ããRAMãã©ã€ãã®å Žåã¯æããããŸããã
ããŒãªã³ã°ãããã¹ã¯ãªããã³ãŒãïŒ
TelegramPollingBot
/system script run JParseFunctions :global TToken "12312312:32131231231" :global TChatId "43242342423" :global Toffset :if ([:typeof $Toffset] != "num") do={:set Toffset 0} /tool fetch url="https://api.telegram.org/bot$TToken/getUpdates\?chat_id=$TChatId&offset=$Toffset" dst-path=j.txt #:delay 2 :global JSONIn [/file get j.txt contents] :global fJParse :global fJParsePrintVar :global Jdebug false :global JParseOut [$fJParse] :local Results ($JParseOut->"result") :if ([:len $Results]>0) do={ :foreach k,v in=$Results do={ :if (any ($v->"message"->"text")) do={ :if ($v->"message"->"text" ~ "uptime") do={ /tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[/system resource get uptime]" keep-result=no } else={ :if ($v->"message"->"text" ~ "ip") do={ /tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[/ip dhcp-client print as-value]" keep-result=no } else={ :if ($v->"message"->"text" ~ "parse") do={ /tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[$fJParsePrintVar]" keep-result=no } else={ /tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$($v->"message"->"text")" keep-result=no } } } } :set $Toffset ($v->"update_id" + 1) } } else={ :set $Toffset 0 }
Webhookããã
ãããã®ãã€ãã¹ãåãé€ãããã«ãWebhookãåŠçããã¹ã¯ãªããã®2çªç®ã®ããŒãžã§ã³ãäœæããŸãã Telegram APIèªäœããæ°ããã¡ãã»ãŒãžãéä¿¡ããããã«ãæå®ãããã¢ãã¬ã¹ã§ã«ãŒã¿ãŒã«ãã¹ã©ã ããããšãã
ãã¡ãããMikrotikã¯ãTelegram APIããã®Webhookéç¥ãå®å šã«æäœããããã«å¿ èŠãªãã«ã¹ã¿ã WebãµãŒããŒãå éšã«äœæããæ¹æ³ãç¥ããŸããã ãããããã®åé¡ãå·§åŠã«åé¿ã§ããŸãã ãããè¡ãã«ã¯ãWebhookããã¯ã©ãã·ã¥ãããååšããªãTCPãœã±ãããç£èŠããå¿ èŠããããŸããããã¯ããã³ã°ã«ïŒãŸãã¯ãã¡ã€ã¢ãŠã©ãŒã«ïŒã«ãŒã«ã䜿çšããŠè¡ãããŸãã Telegram APIã«ã¯ãWebhookã®åäœïŒsetWebhook APIé¢æ°ïŒãå«ãŸããã«ãŒã¿ãŒã®ãã¡ã€ã³åãšTCPããŒãã瀺ãããŸããSSL蚌ææžã¯ããã§ã¯åœ¹å²ãæãããŸããã å¿ èŠãããŸããïŒ Mangleã«ãŒã«ã®ãã±ããã«ãŠã³ã¿ãŒã®å€ãå€æŽããããšã«ãããWebhookãååšããªãTCPããŒãïŒãŸãã¯ä»ã®äœãïŒã«ãåãåããããããšãç解ã§ããŸããsrc-address= 149.154.167.192 / 26ãã£ã«ã¿ãŒã§è¶ éåãã«ããã§ããŸãã æ®å¿µãªããããã³ã°ã«ã«ãŒã«ã¯ãŠãŒã¶ãŒå®çŸ©ã®ã¹ã¯ãªãããçŽæ¥åŒã³åºãããšã¯ã§ããŸããïŒãã®ãããªã¢ã¯ã·ã§ã³ã¯ãããŸããïŒããã¹ã¯ãªãããããã±ããã«ãŠã³ã¿ãŒãããŒãªã³ã°ããããšã¯ã§ããŸãã ã¹ã¯ãªãããã¹ã±ãžã¥ãŒã«ã©ããã«å®è¡ãããŸãããæå°ééã¯1ç§ã§ãã ã¢ã€ãã«ç¶æ ã§ã¯ããã±ããã«ãŠã³ã¿ãŒå€ã®å€åã®ã¿ããã§ãã¯ãããŸãã æ°ããçä¿¡ãã±ãããæ€åºããåŸãWebhookãç¡å¹ã«ããèŠæ±ãTelegram APIã«éä¿¡ãããã¡ãã»ãŒãžãæåã®ã¹ã¯ãªããïŒããŒãªã³ã°ïŒã®ããã«èªã¿åãããŠåŠçãããŸãããã®åŸãWebhookãåã³ãªã³ã«ãªããã¹ã¿ã³ãã€ç¶æ ã«æ»ããŸãã äž»ãªæé ã¯ãã¹ã¯ãªããã®å³ã«ç€ºãããŠããŸãã
æ¢ã«è¿°ã¹ãããã«ãã¹ã¯ãªããã¯é »ç¹ã«å®è¡ãããåŒã³åºãããã¹ã¯ãªããã®ã€ã³ã¹ã¿ã³ã¹ã®éè€ãé¿ããããã«ãã¹ã¯ãªããã®å é ã§éè€ã«å¯Ÿããä¿è·ãè¡ãããŸãããã®ã¹ã¯ãªããã®ååãããã«ç€ºãå¿ èŠããããŸãã
:if ([:len [/system script job find script=TelegramWebhookBot]] <= 1) do={...}
Webhookãããã¹ã¯ãªããã³ãŒãïŒ
TelegramWebhookBot
:if ([:len [/system script job find script=TelegramWebhookBot]] <= 1) do={ #:while (true) do={ :global TelegramWebhookPackets :local TWebhookURL "https://www.yourdomain" :local TWebhookPort "8443" # Create Telegram webhook mangle action :if ([:len [/ip firewall mangle find dst-port=$TWebhookPort]] = 0) do={ /ip firewall mangle add action=accept chain=prerouting connection-state=new dst-port=$TWebhookPort protocol=tcp src-address=149.154.167.192/26 comment="Telegram" } :if ([/ip firewall mangle get [find dst-port=$TWebhookPort] packets] != $TelegramWebhookPackets) do={ /system script run JParseFunctions :local TToken "123123123:123123123123123" :local TChatId "3213123123123" :global TelegramOffset :global fJParse :global fJParsePrintVar :global Jdebug false :global JSONIn :global JParseOut :if ([:typeof $TelegramOffset] != "num") do={:set TelegramOffset 0} :put "getWebhookInfo" :do {/tool fetch url="https://api.telegram.org/bot$TToken/getWebhookInfo" dst-path=j.txt} on-error={:put "getWebhookInfo error"} :set JSONIn [/file get j.txt contents] :set JParseOut [$fJParse] :put $JParseOut :if ($JParseOut->"result"->"pending_update_count" > 0) do={ :put "pending_update_count > 0" :do {/tool fetch url="https://api.telegram.org/bot$TToken/deleteWebhook" http-method=get keep-result=no} on-error={:put "deleteWebhook error"} :put "getUpdates" :do {/tool fetch url="https://api.telegram.org/bot$TToken/getUpdates\?chat_id=$TChatId&offset=$TelegramOffset" dst-path=j.txt} on-error={:put "getUpdates error"} :set JSONIn [/file get j.txt contents] :set JParseOut [$fJParse] :put $JParseOut :if ([:len ($JParseOut->"result")] > 0) do={ :foreach k,v in=($JParseOut->"result") do={ :if (any ($v->"message"->"text")) do={ :if ($v->"message"->"text" ~ "uptime") do={ :do {/tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[/system resource get uptime]" keep-result=no} on-error={:put "sendmessage error"} } else={ :if ($v->"message"->"text" ~ "ip") do={ :do {/tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[/ip dhcp-client print as-value]" keep-result=no} on-error={:put "sendmessage error"} } else={ :if ($v->"message"->"text" ~ "parse") do={ :do {/tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$[$fJParsePrintVar]" keep-result=no} on-error={:put "sendmessage error"} } else={ :if ($v->"message"->"text" ~ "add") do={ :local addIP [:toip [:pick ($v->"message"->"text") 4 [:len ($v->"message"->"text")]]] :if ([:typeof $addIP] = "ip") do={ :do {/ip firewall address-list add address=$addIP list=ExtAccessIPList timeout=10m comment="temp"} on-error={:put "ip in list error"} } :local Str1 "" :foreach item in=[/ip firewall address-list print as-value where list=ExtAccessIPList and dynamic] do={:set Str1 ($Str1 . "$($item->"address") $($item->"timeout") $($item->"comment")\r\n")} :do {/tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$Str1" keep-result=no} on-error={:put "sendmessage error"} } else={ :put ($v->"message"->"text") :do {/tool fetch url="https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId" http-method=post http-data="text=$($v->"message"->"text")" keep-result=no} on-error={:put "sendmessage error"} } } } } } :set $TelegramOffset ($v->"update_id" + 1) } } else={ # :set $TelegramOffset 0 } :put "getUpdates" :do {/tool fetch url="https://api.telegram.org/bot$TToken/getUpdates\?chat_id=$TChatId&offset=$TelegramOffset" keep-result=no} on-error={:put "getUpdates error"} :put "setWebhook" :do {/tool fetch url="https://api.telegram.org/bot$TToken/setWebhook\?url=$TWebhookURL:$TWebhookPort" keep-result=no} on-error={:put "setWebhook error"} } else={ :if ($JParseOut->"result"->"url"="") do={ :put "setWebhook" :do {/tool fetch url="https://api.telegram.org/bot$TToken/setWebhook\?url=$TWebhookURL:$TWebhookPort" keep-result=no} on-error={:put "setWebhook error"} } } :set TelegramWebhookPackets [/ip firewall mangle get [find dst-port=$TWebhookPort] packets] :put "--------------------------------------------------" } }
ãã®ãããã¹ã¯ãªããã«addã³ãã³ããè¿œå ãããExtAccessIPListã¢ãã¬ã¹ã®è§£æ±ºãªã¹ãã«10åéIPã¢ãã¬ã¹ãè¿œå ãããŸããã
Telegramã§ã®ãªã¯ãšã¹ããšã¬ã¹ãã³ã¹ã®äŸã æåŸã®è¡ã¯ãIPãªã¹ãã«æ¢ã«è¿œå ãããŠããäžæã¢ãã¬ã¹ã§ãã
>add 1.1.1.1
>> 90.0.0.97 h*******
100.0.0.157 6*******
90.0.0.2 i*******.ru
100.00.66 b*******.ru
1.1.1.1 00:10:00 temp
ãã®ã¢ãããŒãã®é·æãšçæã瀺ãããã«æ®ã£ãŠããŸãã çæïŒWebhookã¯ã€ã³ã¿ãŒãããããã«ãŒã¿ãŒã®IPããã³æå®ãããTCPããŒããžã®ã¢ã¯ã»ã¹ãå¿ èŠãšããŸããå®éã«ã¯å®éã®IPã¢ãã¬ã¹ã§ãããã§ããã°ãã¡ã€ã³ã«ãã€ã³ããããŠããŸãã ãã¡ã€ã³åã®å¯çšæ§ã«é¢ããŠãTelegram APIããã¹ã¢ãŒã¯ãããå¿ èŠããããã©ããã¯ããããŸããããããããIPãµãŒããŒã§Webhookãäœæã§ããªãã§ãããã åçãªå®IPã¢ãã¬ã¹ãšåçãªDNSãµãŒãã¹ã§åäœããŸãã
é·æïŒã¹ã¯ãªããã®äž»èŠéšåã¯å®éã«åžžã«ã¹ãªãŒãç¶æ ã«ãªãã代çãœã±ãããžã®çä¿¡ãã±ãããåŸ æ©ããŸãã ã¹ã¯ãªãããé »ç¹ã«åŒã³åºããšïŒ1ç§éã«1åïŒãéåžžã®ãã¬ã°ã©ã ãããã®ããã«ãWebhookãéåžžã«é«éã«å®è¡ãããŸãã
ãŸãããœãŒã¹ã³ãŒãã¯ãã¡ãã«ãããŸã ã
ãããŠããã€ãã®ãããªïŒ