Search code examples
pythonbashraspberry-pitelegram-botinteractive-shell

A Telegram bot to control a Raspberry Pi through an interactive shell


I am trying to write the program for a Telegram bot to control my Raspberry Pi, so that every message I send the bot shall be interpreted as a shell command [1][2].

The Raspberry Pi is a version 2 model B and runs Arch Linux ARM. The program is written in Python 3.6.0 with the module Telepot, and is executed from the Pi.

So far, I have been using the module subprocess in order to execute the commands, like this:

# Execute a shell command (assuming that the message received is «text»)
P = subprocess.Popen(text, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
# Store the output and the error
(output, error) = P.communicate()
# Send a message with the output
if str(output) != "b''":
    bot.sendMessage(my_id, output)
# And another message with the error
if str(error) != "b''":
    bot.sendMessage(my_id, error)

The bot works just fine, but the problem is that I cannot execute every command like I would in a real shell. I am talking especially about those interactive commands that bypass the STDOUT and send their output directly to the tty (ssh, ftp... which typically prompt for a password and wait until the user types it). subprocess does not allow to read from or write to the tty. Infact, if I send my bot the command tty, it replies: not a tty.
Additionally, some shell commands update their output dinamically or keep running until some event happens (for example ping 8.8.8.8, or grep pattern), and I have not succeeded in reproduce them neither, because I cannot send a Ctrl+C or Ctrl+D. Note that this second one is a different problem, because it is possible to redirect ping´s output to a file (while it is not possible to redirect [sudo] Password for user:); but in this case I am unable to send input to the shell.
Also, as an optional, it would be fun if the bot could understand pipes, redirections and globbing.
What accomunates these problems is, to my mind, the fact that I cannot interact with the shell. I believe the solution to all of them is just one.

So the question is, broadly, how can I implement such a bot program that allows me to run interactive shell commands through it [3]?

An example of the final result I would like to achieve is (in the form of a conversation between me and the bot):

Me: pwd

Bot: /home/user/some/directory

Me: sudo chmod 777 file.txt

Bot: [sudo] password for user:

Me: qwerty

Me: ssh user@host

Bot: user@host´s password:

Me: qwerty2

Bot: Welcome to host...

or

Me: cat

Me: hello

Bot: hello

Me: test

Bot: test

Me: Ctrl+D

P.S.
I have tried the pexpect module for Python, but I think it is not so good for me because I do not expect any particular output; I just want to get anything the shell gives me. (Perhaps there is a way to do what I want that I do not know?)
I have also tried using fifo files, but they do not work since they are connected to STDIN and STDOUT, not to the tty.

[1] Example: I send the message pwd and the bot replies /working/directory.
[2] True, I could use ssh or similar; however, what intrigues me is that a bot would work independently of the operating system of the machine that performs the request, be it Linux, Windows, Android or anything, without installing additional software (without even installing Telegram, since there exists Telegram web).
[3] The question could also have been: how can I connect directly to a tty through a script? The script can also be written in bash or another language, if it is easier. But I do not want to bias you, I am open to every solution. Once I have the input/output in a variable, sending the messages is not a problem.


Solution

  • Forgive me if I answer my own question, but I have found precisely what I was looking for, and I'd like to share it with you.

    https://jmendeth.com/blog/telegram-shell-bot/

    At the link above you can find the instruction to install and use 'shell bot'; from there you can also reach the source code on github.

    Though not written in Python, but in node.js, it seems perfect to me. It updates the messages on the fly and can also execute graphical commands.

    P.S. You can even run vim through the bot!