Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save xdenb43/b6c5044baccd8c8136d40b40adf7d3a0 to your computer and use it in GitHub Desktop.

Select an option

Save xdenb43/b6c5044baccd8c8136d40b40adf7d3a0 to your computer and use it in GitHub Desktop.
Mikrotik forward selected log events to Telegram bot

logEventTGInformer | by xdenb43
Sends log events filtered by condition(s) to specific topic of telegram super-group

Specs

  • Created to post messages to dedicated topic of the specified supergroup telegram instance
  • Default filtering conditions: topics~"(error|critical|netwatch)" || message~"([fF]ailure|router rebooted|checkOSUpdate)"
  • NO time-format related troubles, mikrotik internal function totime used
  • Executes every 60 seconds
  • Uses limit to 4096 message symbols

Logic

  • Adds scheduler automatically with the first manual execution
  • Selects all log events then filter by specified conditions starting from last successfull execution time
  • Saves last successfull execution time to COMMENT of the scheduled task

How to use

  • Create telegram bot and connect to your channel/group/supergorup before usage
  • Insert your own values instead of $TOKEN, $CHATID and $GROUPTOPICID variables

Warning

Known issue: log text parser failes for keyword "HTTP"

An example of notifications

Screenshot 2025-10-09 205733

Script

# BEGIN SETUP
# logEventTGInformer | by xdenb43
# tested on RoS 7.17.2

:local tgBotToken "$TOKEN";
:local tgChatId "$CHATID";
:local tgTopicId "$GROUPTOPICID";

:local tgUrl "https://api.telegram.org/bot$tgBotToken/sendMessage?chat_id=$tgChatId&message_thread_id=$tgTopicId&text=";
:local mikrotId ("\E2\9D\97"." `".[/system identity get name]." ".[/system resource get board-name]."` \E2\9D\97");
:local scheduleName "logEventTGInformer";
:local logsBuffer [:toarray [/log find topics~"(error|critical|netwatch)" || message~"([fF]ailure|router rebooted|checkOSUpdate)"]]
:local ignoreInLog {"static dns entry changed"; "changed script settings"; "HTTP"; "changed scheduled script setting"}
#:local ignoreInLog [:toarray " "]
# Telegram messages can currently hold up to 4KB of text (4096 latin characters).
:local symbolsLimit 4096
# END SETUP

# SCHEDULER
# warn if schedule does not exist and create it
:if ([:len [/system scheduler find name="$scheduleName"]] = 0) do={
    /log warning "[logEventTGInformer] Alert : Schedule does not exist. Creating schedule ...."
    :delay 1
    /system scheduler add name=$scheduleName interval=60s start-time=startup on-event=logEventTGInformer policy=read,write,test
    /log warning "[logEventTGInformer] Alert : Schedule created!"
}

# MAIN PART
# for checking time of each log entry
:local currentTime
:local result ""
# get last time from scheduler's comment
:local lastTime [/system scheduler get [find name="$scheduleName"] comment]
:local firstRun false

:if ([:len $logsBuffer] > 0) do={
    :if ([:len $lastTime] = 0) do={
        :set lastTime [:totime [/log get [:pick $logsBuffer 0] time]];
        :set firstRun true
    }

    # loop through all filtered log entries
    :foreach line in=$logsBuffer do={
        :set currentTime [:totime [/log get $line time]]
        :local message [/log get $line message]
        :local tempResult ([/log get $line time]."%0A".$message."%0A%0A")
        :if (( $currentTime > $lastTime) || ($firstRun = true)) do={
            :set firstRun false
            # loop through all ignoreInLog array items
            :local keepLog true
            :foreach j in=$ignoreInLog do={
                # if this log entry contains any of them, it will be ignored
                :if ($message ~ "$j") do={
                    :set keepLog false
                }
            }
            :if ($keepLog = true) do={
                :if (([:len "$mikrotId%0A%0A$result"] + [:len "$tempResult"]) < $symbolsLimit) do={
                    :set result ($result.$tempResult);
                    :set lastTime $currentTime;
                }
            }
        }
    }
}

# if no internet connection then script need to know informer is not sent
if ([:len $result] > 0) do={
    :local fetchResult [/tool fetch url="$tgUrl$mikrotId%0A%0A$result&parse_mode=markdown" keep-result=no as-value];
    :if ($fetchResult->"status" = "finished") do={
        /system scheduler set [find name="$scheduleName"] comment=$lastTime
    }
}

UI окно System - Scripts

Screenshot 2025-10-09 210029
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment