📜 ⬆️ ⬇️

We teach Raspberry Pi to accept telegrams with the help of Bot API and Python

I have long wanted to fasten a convenient “communication” interface to my home Raspberry Pi, which would satisfy the main requirement - simplicity and ease, with access from anywhere in the world and using any equipment (but first of all from a smartphone).

Due to the lack of a dedicated IP at home and the presence of harsh and incorruptible NAT, options with SSH clients and web interfaces disappeared immediately. For small needs, the solution should also be simple, fast and, as a bonus, reliable. So the idea of ​​using the protocol of one of the common messengers seemed to me very attractive. Jabber, Telegram and WhatsApp got under the scope.

Jabber played against the reluctance to install an extra client. Well, since Telegram is, IMHO, the same WhatsApp, only better and more convenient (and even a bit safer), it was there that I decided to make my choice. In addition, the opportunity recently appeared in Telegram to create their slave bots and interact with them using a very simple API allows you to get rid of the need to register a new account, as well as provides some very useful and convenient features.
')
In fact, everything is really so simple that even 30 minutes are enough for experienced people to figure out, raise and set up their bot. To the rest: Welcome!

The search result in Runet on the phrase "Telegram & Raspberry" was rich only in the article with Habr "Raspberry and Telegram: prerequisites for creating a smart home" , which describes the basic manipulations with the Telegram client. By the way, I didn’t manage to get enough raw product and make it work normally (out of the blue the same commands refuse to parse one time). But, fortunately, I don’t need it anymore.

So, we need to create a bot, for which in any Telegram client (preferably the latest version) we find a contact with the name BotFather and ask it for / help. To which he will respond with sufficiently detailed instructions and will only have to follow it. Commands for absolutely lazy people:

/newbot <   > <username  > 

Done! Now BotFather will offer us to remember / save the token for access to the bot via the HTTP API, which will come in handy soon.

As a programmer, I am very beginner, I know only Python well, which, nevertheless, is perfect for this task. Let's start.

To make life easier and shorten the code, I suggest installing a library to simplify requests for HTTP requests using the command:

 pip install requests 

Now the whole task is reduced to writing a simple script that, after a specified period of time, will request updates from the server. If there are any and the message is sent by a predetermined user, and also contains a specified command in the text, then the action corresponding to this command will be performed. Such a script I bring to your attention. So far this is just a template that can be adapted to your needs, but over time I plan to make something more decent from it.

telegram.py (python2.7) - updated
 # -*- coding: utf-8 -*- import requests import time import subprocess import os #import mailchecker requests.packages.urllib3.disable_warnings() #  InsecureRequestWarning,        #           Telegram   @BotFather # ADMIN_ID -   (  ),    #    ID,         ()    #         GET  #          ,  <token>   : # https://api.telegram.org/bot<token>/getUpdates # ,     "from":{"id":01234567,"first_name":"Name","username":"username"} #   ,     #   ,     "id" -      #  ADMIN_ID  TOKEN      INTERVAL = 3 #      ()     ADMIN_ID = 12345678 # ID .        URL = 'https://api.telegram.org/bot' #  HTTP Bot API TOKEN = '123456789:???????????????????????????????????' #      offset = 0 # ID    def check_updates(): """      ,    """ global offset data = {'offset': offset + 1, 'limit': 5, 'timeout': 0} #    try: request = requests.post(URL + TOKEN + '/getUpdates', data=data) #    except: log_event('Error getting updates') #   return False #   if not request.status_code == 200: return False #    if not request.json()['ok']: return False #     API for update in request.json()['result']: #     offset = update['update_id'] #  ID  # ,      'message' #     'message'   'text',  if not 'message' in update or not 'text' in update['message']: log_event('Unknown update: %s' % update) #      continue #      from_id = update['message']['chat']['id'] #  ID  () name = update['message']['chat']['username'] #  username  if from_id <> ADMIN_ID: #     ,  send_text("You're not autorized to use me!", from_id) #     log_event('Unautorized: %s' % update) #     continue #       message = update['message']['text'] #    parameters = (offset, name, from_id, message) log_event('Message (id%s) from %s (id%s): "%s"' % parameters) #    ID    #    ,    run_command(*parameters) def run_command(offset, name, from_id, cmd): if cmd == '/ping': #   ping send_text(from_id, 'pong') #   elif cmd == '/help': #   help send_text(from_id, 'No help today. Sorry.') #  elif cmd == '/photo': #     Web- #   If .     -  ,  ,      #     ,     #  ,             if make_photo(offset) or make_photo(offset): # ,       requests.post(URL + TOKEN + '/sendChatAction', data={'chat_id': from_id, 'action': 'upload_photo'}) send_photo(from_id, offset) #     else: send_text(from_id, 'Error occured') # ,    elif cmd == '/mail': check_mail() #     else: send_text(from_id, 'Got it.') #   def log_event(text): """   ToDo: 1)     """ event = '%s >> %s' % (time.ctime(), text) print event def send_text(chat_id, text): """    chat_id ToDo:    """ log_event('Sending to %s: %s' % (chat_id, text)) #     data = {'chat_id': chat_id, 'text': text} #   request = requests.post(URL + TOKEN + '/sendMessage', data=data) # HTTP  if not request.status_code == 200: #    return False #    return request.json()['ok'] #     API def make_photo(photo_id): """   fswebcam     Web-""" photo_name = 'photo/%s.jpg' % photo_id #     subprocess.call('fswebcam -q -r 1280x720 %s' % photo_name, shell=True) #  shell- return os.path.exists(photo_name) # ,       def send_photo(chat_id, photo_id): """      """ data = {'chat_id': chat_id} #    photo_name = 'photo/%s.jpg' % photo_id #     if not os.path.exists(photo_name): return False #    files = {'photo': open(photo_name, 'rb')} #     request = requests.post(URL + TOKEN + '/sendPhoto', data=data, files=files) #   return request.json()['ok'] #  True  False,    ,     def check_mail(): """      """ print "     " return False try: log_event('Checking mail...') #    respond = mailchecker.check_all() #      except: log_event('Mail check failed.') #    return False #     if not respond: respond = 'No new mail.' #   ,       send_text(ADMIN_ID, respond) #     return True if __name__ == "__main__": while True: try: check_updates() time.sleep(INTERVAL) except KeyboardInterrupt: print ' ..' break 


Tips
To run this script in the background on the Raspberry Pi, you can use two methods:
1) Using screen. Instructions for use here .
2) Teams:

 python telegram.py CTRL+Z bg 

If you want to put this script into autorun, you need to add to the /etc/rc.local file, before the line 'exit 0',:
 python <  >/telegram.py 

For example:
 nano /etc/rc.local ... python /home/pi/telegram.py exit 0 


And of course, python2.7 should be installed on your Raspberry.

This, of course, is just the beginning, the outline. A little later I will screw some interesting features. For example, taking a snapshot from a camera on a team and some more difficult, such as managing a garland on WS2801 and others.

I would be very happy with any comments, suggestions and suggestions.

Also, as you have already noticed, the script checks messages with a certain period of time. Implementing a WebHook reception without an intermediary is not possible. It was played with “timeout” values ​​in the “getUpdates” method, to no avail. I would be grateful for any ideas on this matter.

[ Telegram Bot API ]

UPD (03.07). Code updated.

Source: https://habr.com/ru/post/261473/


All Articles