Community discussions

MikroTik App
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Bug: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 1:02 pm

I have a script/function for sending messages to Telegram. It generally works well, but if I try to send more than 2 messages in a row from a third-party script, a phantom empty message appears. This only happens between the 2nd and 3rd messages. After the third message, there can be a couple dozen more, and no more phantom messages appear. This issue only occurs when sending from a single third-party script. If I place the sending logic within the script containing the function, this problem doesn’t happen. For now, I’ve come up with a few workarounds to deal with this phantom message: 1. Add a check for empty messages in the function. 2. Create some kind of wrapper when sending messages from a third-party script. Here is the text of my script with the message-sending function:
# Bot configuration
:global botConfig
:if ([:typeof $botConfig] != "array") do={ :set botConfig [:toarray ""] }
:set ($botConfig->"Telegram") {
    "botToken"="XXXXXXXXXXXXXXXXXXXXX";
    "mainID"="XXXXXXXXXXXX"
}

# Function to form URL
:global botUrl do={
    :global botConfig
    :return ("https://api.telegram.org/bot" . ($botConfig->"Telegram"->"botToken"))
}

# Function to serialize array to JSON
:global arrayToJson do={
    :local array $1
    :local result "{"
    :local first true
    :foreach key,value in=$array do={
        :if ($first) do={:set first false} else={:set result ($result . ",")}
        :set result ($result . "\"" . $key . "\": \"" . $value . "\"")
    }
    :set result ($result . "}")
    :return $result
}

# Function to send message
:global sendTelegramMessage
:set sendTelegramMessage do={
    :global botUrl
    :global botConfig
    :global arrayToJson
    
    :local message $1
    :local chatId $2
    
    :if ([:typeof $chatId] = "nothing" || $chatId = "") do={
        :set chatId ($botConfig->"Telegram"->"mainID")
    }
    
    # Protection against empty message
    :if ([:len $message] = 0) do={
        :put "Skipping empty message"
        :return false
    }
    
    :local data {"chat_id"=$chatId; "text"=$message}
    :local jsonString [$arrayToJson $data]
    :put "Sending: $jsonString"
    
    :local url ([$botUrl] . "/sendMessage")
    :local result [/tool fetch mode=https \
        url=$url \
        http-method=post \
        http-header-field="Content-Type: application/json" \
        http-data=$jsonString \
        output=user \
        as-value]
    :put "Result: $result"
    
    # Fix: extract data into a variable
    :local response ($result->"data")
    :put "Response: $response"
    
    :return ($result->"status" = "finished")
}

# Test sending
[$sendTelegramMessage "Test message 1"]
[$sendTelegramMessage "Another test message 2" "XXXXXXXXX"]
[$sendTelegramMessage "Test message 3"]
[$sendTelegramMessage "Test message 4"]
If I send from another script like this:
:global sendTelegramMessage
  [$sendTelegramMessage "Test message 1"]
  [$sendTelegramMessage "Another test message 2" "XXXXXXXXXX"]
  [$sendTelegramMessage "Test message 3"]
  [$sendTelegramMessage "Test message 4"]
Then a silly message appears. But if I wrap it like this:
:global sendTelegramMessage
    :put [$sendTelegramMessage "Test message 1"]
    :put [$sendTelegramMessage "Another test message 2" "XXXXXXXXXXXX"]
    :put [$sendTelegramMessage "Test message 3"]
    :put [$sendTelegramMessage "Test message 4"]
Or like this:
:global sendTelegramMessage
    :local result1 [$sendTelegramMessage "Test message 1"]
    :put "Result 1: $result1"
    :local result2 [$sendTelegramMessage "Another test message 2" "XXXXXXXXXXXX"]
    :put "Result 2: $result2"
    :local result3 [$sendTelegramMessage "Test message 3"]
    :put "Result 3: $result3"
    :local result4 [$sendTelegramMessage "Test message 4"]
    :put "Result 4: $result4"
Then the phantom message does not appear. Can someone tell me where this phantom message comes from and how to deal with it?
I have RouterOS 7.10.2
Last edited by DyadyaGenya on Sun Mar 30, 2025 9:34 pm, edited 2 times in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 1:16 pm

Too many mistakes and too many times to do 2 + 2
do instead (4 / 2) + (((7 + 9) / 2²) * ½)
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 1:49 pm

Too many mistakes and too many times to do 2 + 2
I apologize. I respect you very much, you have done a lot for the forum, but I don't write code often. I understand that there may be an easier way to send a message, but I don't know it and do it the way I know how/invented. Could you please tell me how to do it easier and more correctly? Or give me a link to the correct option, because what I found is at least based on GET requests, which in my opinion is not correct.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 1:58 pm

There are dozens of threads on this topic on the forum.
Sorry, but I don't use Telegram and I don't tinker with things I can't test.
 
User avatar
loloski
Member
Member
Posts: 481
Joined: Mon Mar 15, 2021 9:10 pm
Location: Philippines

Re: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 2:00 pm

you can use e-worm comprehensive script available at https://github.com/eworm-de/routeros-scripts you don't have to code anything
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Phantom empty message in Telegram when sending from a third-party script

Sat Mar 29, 2025 2:36 pm

you can use e-worm comprehensive script available at https://github.com/eworm-de/routeros-scripts you don't have to code anything
Yes, progress does not stand still. I will try to update and test, but at first glance the risk of phantom messages remains. But I will try and write. The main thing is to update without problems )))
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Phantom empty message in Telegram when sending from a third-party script

Sun Mar 30, 2025 12:57 am

There are dozens of threads on this topic on the forum.
Sorry, but I don't use Telegram and I don't tinker with things I can't test.
It's a pity that you don't use Telegram. And you're right, there are many topics on the forum about Telegram bots. But they all have their downsides. For example, tech support suggested using a script from Christian Hesse. With all due respect to the man's work, his version of the script suffers from many downsides. First of all, the complexity of installation and configuration. Too many dependencies. It's like if I wanted to drive a certain brand of car, I would have to make a separate road for it or even set up my own traffic police. In addition, in the version proposed by tech support, a string is sent to Telegram, not JSON. And in my version, I send JSON. Which is more correct according to the standard. So far, I have not met Telegram bots for Mikrotik that would send JSON. I'm not even talking about the backup in case the power goes out. In Hesseth's script, the deferred messages in the queue will disappear, but I made it so that they don't disappear. There are other differences. So not always, when it seems to you that a person wants to add 2 + 2 and get 4, he really wants it. For 2 + 2, the script of the same Heseth will do. But I want more.
you can use e-worm comprehensive script available at https://github.com/eworm-de/routeros-scripts you don't have to code anything
Thanks for the advice. I was wrong with the first glance. The proposed version does not have such a problem. But there are a lot of others. But thanks anyway. Now I know that Mikrotik already has some ways to work with JSON. And now I have something to look at to finish what I want.
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Phantom empty message in Telegram when sending from a third-party script

Sun Mar 30, 2025 9:43 pm

you can use e-worm comprehensive script available at https://github.com/eworm-de/routeros-scripts you don't have to code anything
Probably this version is still subject to the same problem, only apparently it has filters for such situations. But I can be wrong about the filters, because sometimes phantom messages slip through in Hesse's script. And it seems to be a problem (BUG) of Mikrotik. And here is a simple test for this.
Run this code and see if there are gaps or not.
:global testFunc do={ :put "Called with: $1" }
[$testFunc "One"]
[$testFunc "Two"]
[$testFunc "Three"]
I get the same result no matter how many experiments I do.
/system script run fantom
Called with: One
Called with: Two
Called with: 
Called with: Three
Called with: 4
Called with: 5
Called with: 6
Called with: 7
Called with: 8
Called with: 9
Tell me what I'm doing wrong?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Mon Mar 31, 2025 12:02 pm

You are not telling us the truth.
Only that line cannot give that result.
I have already seen errors on the second run, they depend on syntax errors made previously, but if you only show that line, no one can help you... or not?

expected from what you write terminal code

[rex@test] > :global testFunc do={ :put "Called with: $1" }
[rex@test] > [$testFunc "One"]
Called with: One
[rex@test] > [$testFunc "Two"]
Called with: Two
[rex@test] > [$testFunc "Three"]
Called with: Three
[rex@test] >

what you really do wrong on terminal code

[rex@test] > {
{... :global testFunc do={ :put "Called with: $1" }
{... [$testFunc "One"]
{... [$testFunc "Two"]
{... [$testFunc "Three"]
{... }
Called with: One
Called with: Two
Called with: 
Called with: Three
[rex@test] > 
[rex@test] > 
Error: double execution on 2nd run, like another 2nd run without parameters.


one of the way of correctly do on terminal code

[rex@test] > :global testFunc do={ :return "Called with: $1" }
[rex@test] > {
{... :put [$testFunc "One"]
{... :put [$testFunc "Two"]
{... :put [$testFunc "Three"]
{... }
Called with: One
Called with: Two
Called with: Three
[rex@test] > 

example of global function defined later on terminal code

[rex@test] > :global testFunc "nothing, just for example"
[rex@test] > {
{... :set testFunc do={ :return "Called with: $1" }
{... :put [$testFunc "One"]
{... :put [$testFunc "Two"]
{... :put [$testFunc "Three"]
{... }
Called with: One
Called with: Two
Called with: Three
[rex@test] > 

The three rules for prevent that error are very simple, one mandatory, the other almost, the last one depends:
1) :global should never be created inside any parenthesis or any subscript called inside parenthesis (updated is not the same as created)
2) always use :return <something> at the end of a function, "" suffice, and avoid empty :return for exit prematurely from a function.
if is present something in function like :if (x) do={:return y} else={:return z}, this rule obviously is not applied.
3) do not use "do { }" to completely enclose a script or similar bulls–t.
Last edited by rextended on Fri Apr 04, 2025 9:15 pm, edited 2 times in total.
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Thu Apr 03, 2025 10:05 pm

You are not telling us the truth.
Only that line cannot give that result.
I have already seen errors on the second run, they depend on syntax errors made previously, but if you only show that line, no one can help you... or not?
The only thing I hid was not showing the entire code, considering that the call in the script is repeated further and there is no point in it. To make it clearer, here are the screenshots. And I want to say that I apply your rules, but it looks more like fighting symptoms, not the disease. Maybe I'm wrong, unfortunately, this week has been very busy and there is no time to delve into your examples.
You do not have the required permissions to view the files attached to this post.
 
DyadyaGenya
Member Candidate
Member Candidate
Topic Author
Posts: 249
Joined: Mon May 08, 2023 10:34 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Fri Apr 04, 2025 7:17 pm

The three rules for prevent that error are very simple, one mandatory, the other almost, the last one depends:
1) :global should never be created inside any parenthesis or any subscript called inside parenthesis (updated is not the same as created)
2) always use :return <something> at the end of a function, "" suffice, and avoid empty :return for exit prematurely from a function.
if is present something in function like :if (x) do={:return y} else={:return z}, this rule obviously is not applied.
3) do not use "do { }" to completely enclose a script or similar bulls–t.
Did I understand correctly how the function should be formatted? Or am I doing something wrong again? I don't understand how the function, the "do" block, can't be wrapped in curly brackets "{}"

I apologize for using your nickname in the function, but I wanted to make it clear that I don't have anything like that hanging in my global variables.
You do not have the required permissions to view the files attached to this post.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Fri Apr 04, 2025 8:39 pm

3) do not use "do { }" to completely enclose a script or similar bulls–t.
I don't understand how the function, the "do" block, can't be wrapped in curly brackets "{}"

Is do { } not do={...}
Read better: completely enclose a script
do {
<all the script here>
}

////////////////////////////



script worng:
:global echo do={
    :put "Called with: $1"
    :return ""
}
[$echo "A"]
[$echo "B"]
[$echo "C"]
[$echo "D"]
[$echo "E"]
[$echo "F"]

script correct:
:global echo do={
    :return "Called with: $1"
}
:put [$echo "A"]
:put [$echo "B"]
:put [$echo "C"]
:put [$echo "D"]
:put [$echo "E"]
:put [$echo "F"]

wrong coding reveal bug on code

[rex@test-v7] /system/script> export      
# 2025-04-04 17:46:40 by RouterOS 7.16.2
# software id = CHR
#
/system script
add dont-require-permissions=no name=script1 owner=admin policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":glo\
    bal echo do={\r\
    \n    :put \"Called with: \$1\"\r\
    \n    :return \"\"\r\
    \n}\r\
    \n[\$echo \"A\"]\r\
    \n[\$echo \"B\"]\r\
    \n[\$echo \"C\"]\r\
    \n[\$echo \"D\"]\r\
    \n[\$echo \"E\"]\r\
    \n[\$echo \"F\"]\r\
    \n"
[rex@test-v7] /system/script> run script1             
Called with: A
Called with: B
Called with: 
Called with: C
Called with: D
Called with: E
Called with: F

correct coding no bug code

[rex@test-v7] /system/script> export      
# 2025-04-04 17:46:40 by RouterOS 7.16.2
# software id = CHR
#
/system script
add dont-require-permissions=no name=script1 owner=admin \
    policy="ftp,reboot,read,write,policy,test,password,sniff,sen\
    sitive,romon" source=":global echo do={\r\
    \n    :return \"Called with: \$1\"\r\
    \n}\r\
    \n:put [\$echo \"A\"]\r\
    \n:put [\$echo \"B\"]\r\
    \n:put [\$echo \"C\"]\r\
    \n:put [\$echo \"D\"]\r\
    \n:put [\$echo \"E\"]\r\
    \n:put [\$echo \"F\"]\r\
    \n"
[rex@test-v7] /system/script> run script1 
Called with: A
Called with: B
Called with: C
Called with: D
Called with: E
Called with: F
[rex@test-v7] /system/script> 
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Fri Apr 04, 2025 9:03 pm

How to fix that? (whitout define global "echo" outside the script)

NEVER CALL TWO TIMES THE SAME FUNCTION WITHOUT USE OR ASSIGN THE RETURNED VALUE

Simply add void variable for ignore useless return from the function (return everytime something no matter if :return is used [as must be] inside)
:local void
:global echo do={
    :put "Called with: $1"
    :return ""
}
:set void [$echo "A"]
:set void [$echo "B"]
:set void [$echo "C"]
:set void [$echo "D"]
:set void [$echo "E"]
:set void [$echo "F"]

terminal output rules code

[rex@test-v7] /system/script> run script1 
Called with: A
Called with: B
Called with: C
Called with: D
Called with: E
Called with: F
 
User avatar
Sertik
Member
Member
Posts: 494
Joined: Fri Sep 25, 2020 3:30 pm
Location: Russia, Moscow

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 9:47 am

Rex answered you.
This is a long-known bug of RouterOS, which I described, for example, here https://habr.com/ru/articles/646663/. It concerns not your function for Telegram, but all functions in general. If you call any function twice in a row (without assigning a result), it will be executed three times! You can check it yourself on any of your functions. A simple check in the function body fixes the problem: :if ([$len $0]!=0) do={ }.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 10:57 am

Coming here and writing "there is an alternative solution to your solution, but it is more complex" (and it doesn't work) is not a great solution...

A simple check in the function body fixes the problem: :if ([$len $0]!=0) do={ }.
and something should be put in there anyway, so why not JUST :return "" at the end instead of :if ([$len $0]!=0) do={ } at the start???

and anyway $len IS WRONG, (is :len) so what test did he ever do?
:if ([$len [:nothing]]!=0) do={:put true} else={:put false}

:if ([$len ""]!=0) do={:put true} else={:put false}

:if ([$len "xxx"]!=0) do={:put true} else={:put false}
everytime is true
 
optio
Forum Guru
Forum Guru
Posts: 1106
Joined: Mon Dec 26, 2022 2:57 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 6:30 pm

Am I missing something or why just not call function without placing it in square brackets [$echo "<something>"] and there is no issue with return value if called multiple times?
:local echo do={
  :put "Called with: $1"
  <also can be here useless return>
}
$echo "A"
$echo "B"
$echo "C"
$echo "D"
$echo "E"
$echo "F"

> /system/script/run script1 
Called with: A
Called with: B
Called with: C
Called with: D
Called with: E
Called with: F

or some combination like this:
:local echo do={
  :return "Called with: $1"
}
:put [$echo "A"]
$echo
:put [$echo "B"]
$echo 1
:put [$echo "C"]
$echo "something"
:put [$echo "D"]
$echo nil
:put [$echo "E"]
$echo [:nothing]
:put [$echo "F"]

> /system/script/run script1 
Called with: A
Called with: B
Called with: C
Called with: D
Called with: E
Called with: F

Anyway, calling function inside square brackets should be used only when return value is handled...
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 7:54 pm

I think you missed the previous pieces, it all started from this post:
viewtopic.php?t=215841#p1135988
and we're talking about how that script was written and why it causes errors when written that way.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 13099
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 7:58 pm

<also can be here useless return>
Honestly, I'm tired of writing the same thing a hundred times everywhere on the forum.
Make do.
I'm tired of always having to prove everything and that people constantly try to refute (even writing wrong things before even checking them, like the post before yours).

If you're so good at trying endlessly to disprove the obvious, you also know how to make your own scripts.

If you don't like what I write, don't read it.
Last edited by rextended on Tue Apr 29, 2025 7:59 pm, edited 1 time in total.
 
optio
Forum Guru
Forum Guru
Posts: 1106
Joined: Mon Dec 26, 2022 2:57 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 7:59 pm

Ok, I see, bad OP script in general… Regarring topic name, “bug” is resolvable by correctly calling functions.
 
optio
Forum Guru
Forum Guru
Posts: 1106
Joined: Mon Dec 26, 2022 2:57 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Tue Apr 29, 2025 8:03 pm

Regarding useless return placeholder, I was just trying to point out that it doesn't make affect on producing “bug” even if exists for some reason when function is called without square brackets, not related to your example.
 
User avatar
Sertik
Member
Member
Posts: 494
Joined: Fri Sep 25, 2020 3:30 pm
Location: Russia, Moscow

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 9:36 am

Well, I'll quote an excerpt from my own article (2022):
https://habr.com/ru/articles/646663/

Fortunately, as it turned out, the erroneous third function call is made without passing the $0 parameter (function name) to the function. Yes, yes, for some reason, with this erroneous call, $0 is empty. This allows you to implement software insurance against erroneous execution within the function itself. Let's do it this way, let's say there is a function:

:global myFunc do={:log info "Hello world !"}


If we ask you to do it twice:

[$myFunc]; [$myFunc]


As we have already found out, it will be executed three times.

Adding a name check in $0 fixes the problem.:

:global myFunc do={
:if ([:len $0]!=0) do={
:log info "Hello world !"}
}


If there is a check for $0, then if the third run is erroneous, the body of the function code will simply be ignored (it will not be executed). This check is performed by checking the condition string : if ([$len $0]!=0) do={ }.

Unfortunately, this error has not yet been fixed by the developers of Microtik. For correct operation, such a check can be inserted into each user function.
Last edited by Sertik on Wed Apr 30, 2025 10:56 am, edited 1 time in total.
 
User avatar
Sertik
Member
Member
Posts: 494
Joined: Fri Sep 25, 2020 3:30 pm
Location: Russia, Moscow

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 9:43 am

Why would I insert :return "" (return "nothing") into a working function that normally should return something meaningful. I'd rather insert my own :len check for the function name, which is empty with a false third trigger (Microtik idiocy) and the function body will not work.
 
jaclaz
Forum Guru
Forum Guru
Posts: 2904
Joined: Tue Oct 03, 2023 4:21 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 10:47 am

Not that I understand much of what you (and rextended and optio) posted :shock: , but let's disambiguate this not-so-trifling detail, it is
EITHER:
if ([$len $0]!=0) do={ }
OR:
if ([:len $0]!=0) do={ }

tertium non datur https://en.wiktionary.org/wiki/tertium_non_datur
 
User avatar
Sertik
Member
Member
Posts: 494
Joined: Fri Sep 25, 2020 3:30 pm
Location: Russia, Moscow

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 10:53 am

Well, it's a typo, I wrote it quickly. It's clear to a fool that : instead of $. What's the difference? Why find fault with this? The principle and solution are shown.
 
optio
Forum Guru
Forum Guru
Posts: 1106
Joined: Mon Dec 26, 2022 2:57 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 10:59 am

[$myFunc]; [$myFunc]
But it is not necessary to call functions inside square brackets in case where return value is not handled and then there will be no issues. This is not ObjC :)
 
jaclaz
Forum Guru
Forum Guru
Posts: 2904
Joined: Tue Oct 03, 2023 4:21 pm

Re: Bug: Phantom empty message in Telegram when sending from a third-party script

Wed Apr 30, 2025 11:07 am

Well, it's a typo, I wrote it quickly. It's clear to a fool that : instead of $. What's the difference? Why find fault with this? The principle and solution are shown.

Yep, if it is a typo, now that it has been noticed, please correct it, this way there won't be any doubt.
In this particular case using $ instead of : does not cause an error (in which case a fool would notice that), but rather it returns always true (which may well go unnoticed).