Creating Twig templates with Shiiinabot

Creating Twig templates with Shiiinabot

@shiiinabot


Hi there! 👋🏻 This is a brief explanation about how you can use Twig in @shiiinabot.

Remember, if you can use Regex, use it. Regex is easier and faster. Just use Twig if you really can't use Regex.


Introduction

1) First of all, read all the Twig Documentation for Template Designers.

2) Second of all, take just a quick look at the Twig Reference. You don't need to read them all, just need to have an idea about some of the avaiable tags and functions.

3) Take a look at the avaiable message update types Shiiina can receive.

Great! If you read the documentation you are half step away to write your own Twig Templates.


How it works

When you submit a new Template to Shiiina, she will take a look on it to see if everything is alright. If something is wrong (if you mistyped a function name for example) she will try to tell you what happened. If there is nothing wrong with your template, Shiiina will accept it.

Every time someone send a message in your group, Shiiina will run your Template. She will automatically set some variables, for example message(containing the received BotAPI message), admins (an array with the IDs of group admins), db (a constant variable you can use as a simple Database), etc.

If your template return any errors, Shiiina will send a notification to the admin who submitted it, and will remove the template (Don't worry your Database won't be lost, if you want to erase your Database, press the "Erase Twig Database" button).


Global Variables

Currently there are 5 Global Variables:

update: An array with the exact update received from Telegram

message: An array with the message received from Telegram, it can be a message, or a edited_message.

admins: An array with the IDs of the group administrators

user_channel: If the message has an username of a channel, this variable will contain it. If not, this variable will be "false"

db: A consistent variable that can be used as a Database. That means, if you change this variable to "12345" it's value will remain "12345" for all the other updates you receive. If you Erase the Database, this variable will return to it's default value: "false".


Deleting messages

To delete a message, just use the command {{true}}.

For example, if you want to delete all messages, submite the template:

{{true}}

When you reply to the received update with the command {{true}}, Shiiina will instantly delete the message. That means if you submite the template:

{{false}}
{{true}}
{{false}}

Shiiina will also delete all the messages.


Examples:

All right, you already knows the basic stuff, here I will put a few examples of what is possible for you to do using Twig. Let's begin with the simple ones, and keep making it better 😺.


Is possible to delete messages with apk files? (@xeniun)

Too easy. Take a look:

{% if message.document.file_name ends with '.apk'%} 
  {{true}}
{% endif %}

@LouCypher thinks 3 lines is a lot, so he managed to do it using just one. Check it out:

{{ message.document.file_name ends with '.apk'}}

Simple, isn't it?


➲ Can you add up to 100mb files locking feature to shiiina? (@Ericjohnn)

Too easy. Take a look:

{% if message.document.file_size >100000000 %} 
  {{true}}
{% endif %}


Can you add whitelists for stickers? (@AdemGuz)

Yes, it's possible! For example, if you want to only alow the t.me/addstickers/PikachuDetective and t.me/addstickers/docedesenho sticker pack:

{% if message.sticker %}
   {% set whitelist = ['PikachuDetective', 'docedesenho'] %}
   {% if message.sticker.set_name in whitelist %}
      {{false}}
   {% else %}
      {{true}} {# deletes the message #}
   {% endif %}
{% endif %}

Seven lines is a lot? No problem, you can do it in one:

{{ message.sticker and message.sticker.set_name not in ['PikachuDetective', 'docedesenho'] }}


Can I programate Shiina to block with Arabic language nickname? (Tammy)

Yes, it's possible! Remember you should escape Regex characters twice. Check bellow:

{% if update.message.from.first_name matches "/[\\p{Arabic}]/u" %}
 {{true}}
{% endif %}


Is it possible to remove all posts except those forwarded of a specific channel? (@bayernminga)

Yeap, it's possible. Check template below, it will delete all messages forwarded from public channels, except the one with the ID -1001234567890.

{% if message.forward_from_chat.username and message.forward_from_chat.id != -1001234567890 %}
   {{true}}
{% endif %}


Delete all messages between 10 PM and 9 AM. (@tWiTfAcE)

Sure, just change the "UTC" variable to the UTC code of your country. Brazil for example is UTC -3.

{% set UTC = -3 %}
{% set from = 22 %}
{% set to = 9 %}

{% set hour = (message.date+(UTC*3600))|date("H") %}
{% if to-from > 0 %}
 {{ hour >= from and hour < to }}
{% else %}
 {{ hour >= from or hour < to }}
{% endif %}


➲ How to block 2 consecutive stickers? (@gabriel)

If someone send a sticker, set db to "1", if someone send something else, set db to "0". If db is "1" and a sticker was received, delete it. The template will be like this:

{% if db is not iterable %}
       {% set db = [] %}
{% endif %}
{% if message.sticker and db.consecutive_stickers==1 %}
  {{true}}
{% elseif message.sticker and db.consecutive_stickers==0 %}
  {% set db = db|merge({"consecutive_stickers":1}) %}
{% else %}
  {% set db = db|merge({"consecutive_stickers":0}) %}
{% endif %}


➲ If the same text message is sent twice by the same user, Shiiina must delete. Is this possible? (@RazaQuadri)

Sure! Check it out:

{% if db is not iterable %}
      {% set db = [] %}
{% endif %}
{% if db.text_message==message.text and db.id_user==message.from.id %}
 {{true}}
{% elseif message.text %}
 {% set db = db|merge({"id_user":message.from.id}) %}
 {% set db = db|merge({"text_message":message.text}) %}
{% endif %}



How can I whitelist a channel link in my channel? (@zaidALKH)

You can do it like this:

{% if message.entities %}
   {% for value in message.entities %}
      {% if 
         (value.type=='url' or value.type=='text_link')
         and 
         (value.url matches '/t\\.me\\//' or message.text matches '/t\\.me\\//')
      %}
         {% if value.url matches '/t\\.me\\/ShiiinaGroup/i' or message.text matches '/t\\.me\\/ShiiinaGroup/i' %}
           {{false}}
         {% else %}         
            {{true}}
         {% endif %}
      {% endif %}
   {% endfor %}
{% endif %}

It may looks complex, but it's really simple:
1) If there are entities in Telegram update, check if there are entities from "url" or "text_link".
2) If there are entities from "url" or "text_link", check if they have "t.me".
3) If they have "t.me", check if they have "t.me/Shiiinagroup".
4) If they have "t.me/ShiiinaGroup" do not delete. Else, delete the message.

*Remember in Twig you should escape regex characters twice.


➲ How do I whitelist links? (@gabriel)

This Twig will delete all links except whitelisted. In this example, it only allows example.com and telegram.org.

{% set whitelist = [
"telegram.org",
"example.com",
]%}

{% set text = message.text ?? message.caption ?? false %}

{% if message.entities is defined or message.caption_entities is defined %}
 {% set entities = message.entities ?? message.caption_entities %}
 {% set url_not_white=true %}
 {% set link_not_white=true %}
 {% for entity in entities %}
   {% if entity.type == "url" %}
       {% for whiteurl in whitelist %}
           {% if whiteurl in text|lower %}
               {% set url_not_white = false %}
           {% endif %}
       {% endfor %}
       {{ url_not_white }}
   {% elseif entity.type == "text_link" %}
       {% for whiteurl in whitelist %}
           {% if whiteurl in entity.url|lower %}
               {% set link_not_white = false %}
           {% endif %}
       {% endfor %}
       {{ link_not_white }}
   {% endif %}
 {% endfor %}
{% endif %}


How we can configure Shiiina to delete the sticker if an user try to send more than 1 sticker in less than 30 seconds? (@gabriel)

For that we will need to use the db global variable. Check the template below:

If you want to copy the code to try it by yourself:

{% if message.sticker %}
   {% set user_id = message.from.id %}
   {% set time = message.date %}
   {% set delete_message=false %}
      {% for db_user, db_time in db.users %}
         {% if db_user==user_id and db_time > time-30 %}
            {% set delete_message = true %}
         {% endif %}
      {% endfor %}
      {% if delete_message == true %}
        {{true}}
      {% else %}
      {% set user_data = {(user_id):(time)} %}
      {% if db is not iterable %}
        {% set db = [] %}
      {% endif %}
      {% set db = db|merge({'users':(user_data)}) %}
   {% endif %}
{% endif %}


How can I delete messages with urls if it's one of the user's first 2 messages after join the group? (@gabriel)

You can do it like this:

If you want to copy the code to try it by yourself:

{% if message.new_chat_members.0.id %}
  {% set user_id = message.new_chat_members.0.id %}
  {% set user_data = {(user_id):"1"} %}
  {% if db is not iterable %}
      {% set db = [] %}
  {% endif %}
  {% set db = db|merge({'users':(user_data)}) %}
{% else %}
   {% set user_id = message.from.id %}
   {% set there_is_entitie = false %}
   {% for value in message.entities %}
      {% if value.type =="url" or value.type =="text_link" %}
         {% set there_is_entitie = true %}
      {% endif %}
   {% endfor %}
   {% for db_user, db_msg in db.users %}
      {% if db_user==user_id and db_msg < 3 and there_is_entitie %}
         {{true}}
      {% elseif db_user==user_id and db_msg < 3 %}
         {% set value = {(db_user):(db_msg+1)} %}
         {% set db = db|merge({'users':(value)}) %}
      {% else %}
         {{false}}
      {% endif %}
   {% endfor %}
{% endif %}


➲ How about delete flood? (@usernein)

Yeah! That's also possible to create an antiflood using Twig! For example, if you want to allow people so send a max of 4 messages every 5 seconds you can do like this:

Copy the code bellow and try it by yourself:

{# CHANGE HERE THE NUMBER OF MESSAGES PER SECOND #}
{% set af_msgs = 4 %}
{% set af_time = 5 %}

{% if db is not iterable %}
   {% set db = [] %}
{% endif %}
{% if update.message.from.id %}
   {% set user_id = update.message.from.id %}
   {% set actual_time = update.message.date %}
   {% set all_times = [] %}
   {% for ids, times in db.antiflood %}
      {% if ids==user_id %}
         {% for times2 in times|reverse %}   
            {% set loop_value = loop.index %}
            {% if loop_value >= af_msgs %}
               {# do nothing #}
            {% else %}
               {% set all_times = all_times|merge([times2]) %}
            {% endif %}
         {% endfor %}
      {% endif %}
   {% endfor %}
   {% set all_times = all_times|merge([actual_time]) %}
   {% set all_times = all_times|sort() %}
   
   {# update database #}
   {% set db = db|merge({'antiflood':({(user_id):(all_times)})}) %}

   {% if ((all_times|last() - all_times|first()) <= af_time) and (all_times|length >= af_msgs) %}
      {{true}}
   {% endif %}
{% endif %}


➲  I want any user to message only 5 msg a day. After 5 msg the rest would be deleted until next day. (@Bohthardbohthard)

Yes, thats possible.

Copy the code bellow and try it by yourself:

{# CHANGE HERE THE NUMBER OF MESSAGES EACH USER CAN SEND PER DAY #}
{% set msgs_per_day = 3 %}

{% if db is not iterable %}
   {% set db = [] %}
{% endif %}
{% set today_unix = date(false, 'Europe/Paris')%}
{% set day_of_month = today_unix|date("d") %}
{% set user_id = message.from.id %}
{% set user_id = ["u", user_id]|join() %}
{% if day_of_month != db.day_month %}
   {% set db = db|merge({'day_month':(day_of_month)}) %}
   {% set db = db|merge({'msgs_users':( {(user_id): 1} )} ) %}
{% elseif db.msgs_users[user_id] >= msgs_per_day %}
   {{true}}
{% else %}
   {% set msg_users = db.msgs_users %}
   {% set msgs_sent_today = (db.msgs_users[user_id]|default(0)) + 1 %}
   {% set msg_users = msg_users|merge({ (user_id) : msgs_sent_today }) %}
   {% set db = db|merge({'msgs_users': msg_users}) %}
{% endif %}



Things people asks


Can I submit 2 templates to Shiiina?

No. You can only use 1 template per group. But you can mix as many templates you want in just one. Just put one bellow the other, it will work most of the time ;)


I've build a huge template, I can't send it in only one message. How do I send it to Shiiina?

No problem! Put your template in a .twig, .txt, or .iloveshiiina file. Go to the Twig section and reply to Shiiina's message with the file. Shiiina will download it and read it.


I made this Regex and it isn't working in the Twig template. I've received a "fatal_error". What should I do?

Probably your Regex is wrong. Remember in Twig's Regex you should escape some characters twice. That means you can't use /t\.me\//, you should use /t\.me\\//.


My template has a "for" statement and isn't working as it should.

Variables declared inside a for loop are not accessible outside the loop itself. If you want to access the variable, declare it before the loop and just edit it inside the loop.


I've tried to set a array like this: {% set db.index=variable %}. But it didn't work.

In Twig you can't do it like this. You should use the merge filter instead, see:

{% set db = db|merge({"index":(variable)}) %}


I've received a "Database was too big" error. What should I do?

If your db variable got too big (something like 50kb) Shiiina will disable your template and erase the db variable. The recomendation is: if it's possible that your database becomes too huge, erase the useless data as soon as you can.


What's the best way to debug my template?

1) Reply to any message in your group with "/jsondump", (if you are admin and Shiiina isn't set to delete this kind of message) Shiiina will send you the Json data of the message you replied to.
2) Acess https://twigfiddle.com.
3) In the left put your template, in the right put the Json Shiiina gave you
4) Choose the option "JSON"
5) Press "RUN"!



Support Group

As you can see, most of the time it's very easy to create your own Templates, sometimes it's hard, sometimes you just don't know how finish a template, sometimes the template doesn't work cause you mistyped a variable name... Who knows?

These guys: @ShiiinaGroup

Do you have any question about Shiiina, Regex or Twig? Don't hesitate in sending the question in the group. They are cool! 😸

Oh, if you have a good question, it may appear here in the Examples section. 👍🏻


Report Page