Telegram SMS bridge/gateway

Once in a while I am just considering doing things just because ¬†they can be done ūüėČ

Actually, the topic of this article might be helpful for others if they depend on SMS to control devices or refrain from carrying more than one phone around.

So, for this new weekend project, what do we need?

  • a UMTS stick (available on ebay starting at 5 EUR ūüėČ ), old phone with USB or serial connection or similar
  • a telegram bot (telepot)
  • a simcard which is active and can send SMs

Expected outcome: a bot that will relay SMs to a given cellphone number and print incoming SMs to a private telegram channel.

right now there are five commands:

  1. \setrcpt <number> (to set a receipient number we want to chat to obviously)
  2. \open (enable relay)
  3. \close (disable relay)
  4. \status  (if you are not certain which number is set or to retrieve other information)
  5. \terminate (terminate the script)

setting up smstools on ubuntu can be done as described here

so, as soon as you got sms tools running, all we need is some python script-foo ūüėÄ

required software:

apt install python-pip
pip install telepot
import sys
import time
import telepot
import re
import string
import random
import os

class smsbot(telepot.Bot):
    
    def __init__ (self, uid, token, spooldir):
        super(smsbot, self).__init__(token)
        self._mode = 0
        self._recipient = ""
        self._active = 1
        self._user = uid
        self._spooldir = spooldir
        self.notifyOnMessage(self.handle)
    
    def handle (self, msg):
        chat_id = msg['chat']['id']
        command = msg['text']
        if chat_id != self._user:
            self.sendMessage( chat_id, "unauthorized user")
            return 0
        res = re.match(r'^\\(\w+)\s?([\w\d]*)$', command, flags=0)
        if res:
            if      res.group(1) == "status":
                self.status()
            elif    res.group(1) == "setrcpt":
                self._receipient = res.group(2)
                self.sendMessage( chat_id, "recipient set to: %s" % self._recipient)
            elif    res.group(1) == "open":
                if self._recipient != "":
                    self._mode = 1
                    self.sendMessage( chat_id, "relay active")
                else:
                    self.sendMessage( chat_id, "set recipient first!")
            elif    res.group(1) == "close":
                self.sendMessage( chat_id, "relay deactived")
                self._mode = 0
            elif    res.group(1) == "terminate":
                self._active = 0
            else:
                self.sendMessage( chat_id, "unrecognized command!")
        else:
            if self._mode == 1 and self._recipient != "":
                self.sendsm ( command )
            else:
                self.sendMessage( chat_id, "relay not enabled")
    
    def id_generator(self, size=8, chars=string.ascii_uppercase + string.digits):
        return ''.join(random.choice(chars) for _ in range(size))
    
    def status (self): # needs some improvement
        self.sendMessage( self._user , "status")
    
    def sendsm (self, msg):
        output = "To: %s \n\n%s" % (self._recipient, msg)
        filename = os.path.join (self._spooldir, "outgoing", self.id_generator())
        fh = open (filename, "w")
        fh.write (output)
        fh.close()
    
    def recvsm (self ):
        for x in os.listdir(self._spooldir+"incoming/"):
            f = open(self._spooldir+"incoming/"+x, 'r')
            cont = []
            for line in f:
                cont.append(line)
            self.sendMessage(self._user, cont[0]+"\n"+cont[3]+"\n"+cont[12])
            f.close()
            os.remove(self._spooldir+"incoming/"+x)

    
    def checkerr ( self ): #some more work here
        for x in os.listdir(self._spooldir+"failed/"):
            self.sendMessage(self._user, "FAILED:")
            f = open(self._spooldir+"failed/"+x, 'r')
            ln=0
            for line in f:
                self.sendMessage(self._user, str(ln)+line)
                ln=ln+1
            f.close()
            os.remove(self._spooldir+"failed/"+x)
    
    def run (self ):
        while self._active == 1:
            self.recvsm ()
            self.checkerr ()
            time.sleep(5)
    
    
mybot = smsbot (<your_uid_here>, "<telepot_token_here", "/var/spool/sms/")
mybot.run()

run that script and enjoy ūüėČ

smsrelay