HASS TeleBot (Telegram Bot)

I’ve been thinking about that… filtering incoming commands could be quite easy to do, but how to shape a response depending on user id?

How about something like this…

hass_telepot:
  bot_token: [your bot token]
    set1:
      allowed_chat_ids:
        - [user id 1]
      commands:
        - command: /hello
          response:
            text: 'Hello Obiwan'
    set2:
      allowed_chat_ids:
        - [user id 2]
      commands:
        - command: /hello
          response:
            text: 'Hello Luke'

With the above, when Obiwan send /hello, it will responds “Hello Obiwan”. When Luke send it, it will responds back “Hello Luke”.

If you add another set with both user IDs in it and the set contain the same command, the latest (or the one at bottom-most) will take into consideration. For example…

hass_telepot:
  bot_token: [your bot token]
    set1:
      allowed_chat_ids:
        - [user id 1]
      commands:
        - command: /hello
          response:
            text: 'Hello Obiwan'
    set2:
      allowed_chat_ids:
        - [user id 2]
      commands:
        - command: /hello
          response:
            text: 'Hello Luke'
    set3:
      allowed_chat_ids:
        - [user id 1]
        - [user id 2]
      commands:
        - command: /hello
          response:
            text: 'Hello there'

In the above example, when Obiwan send /hello, instead of “Hello Obiwan”, he will receive “Hello there”.

Does it makes sense?

Not sure if I understand. In your example the “hello obiwan” and “hello Luke” is never executed…
Another approach would be:

hass_telepot:
  allowed_chat_ids: # the default allowed ids.
  - id1
  - id2
  - id3
  commands:
  - command: /hello
    allowed_chat_ids:  # optional
    - id1  # only id1 is allowed to send this command.
    response:
      text: 'hello.."  # we could use templates to extract the name of the sender.
  - command: /hi
    response:
      text: 'hi stranger'

Would that make sense ?

let me explain a bit more on my example.

when the telepot receives a command such as /hello, it should check from whom this command is from.

if it is from [user id 1], then it will check which set does this user is in.

if the user and the command are in a particular set, it will send the response or run the services that is contained in that set.

That way, different users with the same command will receive different results such as different custom keyboard, run different scripts or different text response.

Maybe from your example, can it be like this?

hass_telepot:
  allowed_chat_ids: # the default allowed ids.
    - id1
    - id2
    - id3
  commands:
  - command: /hello
    allowed_chat_ids: 
     - id1
    response:
      text: 'Hello Kenobi"
    allowed_chat_ids: 
     - id2
    script:
      service: input_boolean.turn_on
      entity_id: input_boolean.hello_luke

When /hello is received from id1; it will reply “Hello Kenobi”. From id2; it will turn on input_boolean.hello_luke. From id3; do nothing.

My intention is to make the result depend on who the sender is.

Ok.

Let’s do it like this:

hass_telepot:
  allowed_chat_ids: # the default allowed ids.
  - id1
  - id2
  - id3
  commands:
  - command: /hello
    allowed_chat_ids: # optional
    - id1  # only id1 is allowed to send this command.
    response:
      text: "hello Luke.."
    script:
      service: some.service
  - command: /hello
    allowed_chat_ids: id2
    response:
      text: "hello Kenobi"

This can keep the current structure intact and allows for the optional addition of a allow_chat_ids addition when required.
Would that work for you ?

I don’t know if it helps, but here’s what I did with the original hass-telebot (not the component):

  • in the cfg file I put something like:

    users = “{-chat_id_1-: {‘name’: ‘user1’, ‘profile’: ‘admin’, ‘other_parameter’: False},-chat_id_2-: { ‘name’: ‘user2’, ‘profile’: ‘user’, ‘other_parameter’: True}, -chat_id_3-: { ‘name’: ‘user3’, ‘profile’: ‘user’, ‘other_parameter’: False}}”

so I added 3 users, one of which is ‘admin’ (-chat_id_1- must be the actual Telegram chat id number).

then in hass-telebot.py, first you import the users profiles:

users = eval(config['users'])

then you can build a list of admins (optional):

admins = []
for chat_id in users:
if users[chat_id][‘profile’] == ‘admin’:
admins.append(chat_id)

then, once you get chat_id from the incoming message, you can decide the actions you take with:

is_admin = users[chat_id]['profile'] == 'admin'

additional profile parameters with:
users[chat_id][‘other_parameter’]

and so on…

hope it helps,
gl

That sounds good :slight_smile:

Check here:

Did little testing. Let me know whether you encounter any issues…

1 Like

Thanks.
If I may suggest you shouldn’t be using eval(config['users']) to parse some json data. You have the json module for that. Not entirely sure why, but eval should be used with a lot of care (I’ve read you can inject python code at runtime through your json which makes it vulnerable to attacks).

Thanks, I didn’t know that.
Being a private installation I don’t think there’s an issue here, but in general yes, it’s a good advice!

gl

@sanders thanks, however it is not working as expected. This is what I have…

bot_token : !secret telegram_api_key
allowed_chat_ids :
  - !secret telegram_chat_id_kenobi
  - !secret telegram_chat_id_luke
commands:
  - command: /hello
    allowed_ids:
      - !secret telegram_chat_id_luke
    response:
      text: 'Hello Luke'
  - command: /hello
    allowed_ids:
      - !secret telegram_chat_id_kenobi
    response:
      text: 'Hello Kenobi'

I am using telegram_chat_id_kenobi and sent /hello. I expect it to reply back ‘Hello Kenobi’. But it replied back ‘Hello Luke’. It seems to use only the first of the same command in the sequence.

By the way, it is possible to use template in the text response? For example text_template: 'Hello Ben. You have {{ states("sensor.appointment_count") }} appointments today.'

Not sure if it makes a difference, but I see that both of your “command:” are labeled /hello
I would think that it the application would always pick the first one. Try changing the name of the second one to something else.

It is allowed to have identical commands. If so it will look at the allowed_ids.
@masterkenobi Not sure why it is not working. Tested it here and it seems to be going alright. Just as a doublecheck: Are you on the right branch (optional_allowed_ids) ?

Thinking of it… I don’t know whether I like this approach after all…anyone any ideas ?

Yes I am. I used https://raw.githubusercontent.com/sander76/hass_telepot/optional_allowed_ids/hass_telepot.py and I reconfirmed again it only execute the response of the same command that appear first.

to be honest, your solution is very good for single user situation. maybe i will use this for myself first and open it for other family members once it is fully supported.

I added some tests (see the git repo) and they all pass. Don’t know what could be wrong on your side. Can you double double check ?
Possibly switched id’s ?
Also: In your example you add an allowed_ids (telegram_chat_id_luke). If you were to omit that in your real config that first command will always be a match and processed…

Sander.

Is there anyway to close the keyboard commands in the app once one of the buttons has been pressed?

Also, is there a way to give them a friendly name in the App? E.g. rather than “/away” show “Away”.

- alias: A1 Telegram Bot Test    
        
  trigger:
    platform: event
    event_type: telegram_command
    event_data:
      command: '/start'
  action:
    - service: notify.telegram
      data:
        message: "Looks like You've left Home. How long will you be gone for?"
        data:
          keyboard:
            - '/away, /holiday'
            - '/still-home'
            
- alias: A1 Telegram Bot Reply Test    
        
  trigger:
    platform: event
    event_type: telegram_command
    event_data:
      command: '/holiday'
  action:
    - service: homeassistant.turn_on
      entity_id: input_boolean.holiday_mode
    - service: notify.telegram
      data:
        message: 'OK, House is now in Holiday Mode. Thanks Michael.'

I also had a go at using inline keyboard which appear better in the app in my opinion, but how do a trigger an automation using an inline_keyboard similar to what I’m doing above with keyboard commands?

Been reading documentation and forum posts for hours but not getting anywhere :slight_smile:
Would appreciate some help, thank you :slight_smile:

Looks like the Keyboard part is available here: Telegram Bot API

one_time_keyboard - Requests clients to hide the keyboard as soon as it’s been used. The keyboard will still be available, but clients will automatically display the usual letter-keyboard in the chat – the user can press a special button in the input field to see the custom keyboard again. Defaults to false.

Anyone know if this has been Implemented into the Home Assistant component?

Thanks

I’m in the same place as you with trying to get one_time_keyboard to work and make user friendly buttons that hide the command like inline keyboards. I could not get either to work, and the closest info I found was this post.

@badgerhome Did you have any luck with either?