Advertisement
Guest User

Untitled

a guest
Jan 30th, 2014
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.90 KB | None | 0 0
  1. # -*- coding: utf- 8 -*-
  2.  
  3. try:
  4.     version = 'git ' + open(os.path.join(os.path.dirname(__file__), '.git/refs/heads/master')).read().strip()
  5. except:
  6.     version = 'unknown'
  7.  
  8. import os, signal, sys, time, traceback, xmpp
  9. import config, xmlconfig
  10. import json, urllib, urllib2
  11. import threading
  12. from xmpp.browser import *
  13.  
  14. class MyHandler(urllib2.HTTPHandler):
  15.     def http_response(self, req, response):
  16.         return response
  17.  
  18. class Transport:
  19.  
  20.     online = 1
  21.     restart = 0
  22.     offlinemsg = ''
  23.  
  24.     def __init__(self,jabber):
  25.         self.jabber = jabber
  26.         self.mappings = [mapping.split('=') for mapping in config.domains]
  27.  
  28.     def register_handlers(self):
  29.         self.jabber.RegisterHandler('message',self.xmpp_message)
  30.         self.jabber.RegisterHandler('presence',self.xmpp_presence)
  31.         self.disco = Browser()
  32.         self.disco.PlugIn(self.jabber)
  33.         self.disco.setDiscoHandler(self.xmpp_base_disco,node='',jid=config.jid)
  34.  
  35.     # Disco Handlers
  36.     def xmpp_base_disco(self, con, event, type):
  37.         fromjid = event.getFrom().__str__()
  38.         to = event.getTo()
  39.         node = event.getQuerynode();
  40.         #Type is either 'info' or 'items'
  41.         if to == config.jid:
  42.             if node == None:
  43.                 if type == 'info':
  44.                     return {
  45.                         'ids':[
  46.                             {'category':'gateway','type':'smtp','name':config.discoName}],
  47.                         'features':[NS_VERSION,NS_COMMANDS]}
  48.                 if type == 'items':
  49.                     return []
  50.             else:
  51.                 self.jabber.send(Error(event,ERR_ITEM_NOT_FOUND))
  52.                 raise NodeProcessed
  53.         else:
  54.             self.jabber.send(Error(event,MALFORMED_JID))
  55.             raise NodeProcessed
  56.  
  57.     #XMPP Handlers
  58.     def xmpp_presence(self, con, event):
  59.         # Add ACL support
  60.         fromjid = event.getFrom()
  61.         type = event.getType()
  62.         to = event.getTo()
  63.         if type == 'subscribe':
  64.             self.jabber.send(Presence(to=fromjid, frm = to, typ = 'subscribe'))
  65.         elif type == 'subscribed':
  66.             self.jabber.send(Presence(to=fromjid, frm = to, typ = 'subscribed'))
  67.         elif type == 'unsubscribe':
  68.             self.jabber.send(Presence(to=fromjid, frm = to, typ = 'unsubscribe'))
  69.         elif type == 'unsubscribed':
  70.             self.jabber.send(Presence(to=fromjid, frm = to, typ = 'unsubscribed'))
  71.         elif type == 'probe':
  72.             self.jabber.send(Presence(to=fromjid, frm = to))
  73.         elif type == 'unavailable':
  74.             self.jabber.send(Presence(to=fromjid, frm = to, typ = 'unavailable'))
  75.         elif type == 'error':
  76.             return
  77.         else:
  78.             self.jabber.send(Presence(to=fromjid, frm = to))
  79.  
  80.     def xmpp_message(self, con, event):
  81.         # print "Outgoing event. Hello, bluronair!"
  82.         type = event.getType()
  83.         fromjid = event.getFrom()
  84.         msg_from = fromjid.getStripped()
  85.         msg_to = event.getTo()
  86.         msg_body = event.getBody()
  87.  
  88.         cid = None
  89.         handler = None
  90.         arg1 = None
  91.         arg2 = None
  92.         # здесь будет обработка гейта для отсылки смс.
  93.  
  94.  
  95.         # determine caller id
  96.         for mapping in self.mappings:
  97.             if mapping[1] == msg_from:
  98.                 cid = mapping[0]
  99.                 handler = mapping[2]
  100.                 arg1 = mapping[3]
  101.                 arg2 = mapping[4]
  102.         # if cid empty
  103.         if not arg1:
  104.             logstr = "[ERROR] Cannot determine send handler for jid [%s]." % msg_from
  105.             logAppend(logstr)
  106.             return
  107.  
  108.         # determine phonenum to
  109.         to_arr = msg_to.__str__().split("@")
  110.         to = to_arr[0]
  111.  
  112.         # send
  113.         msg = urllib.quote_plus(msg_body.encode('utf-8'))
  114.         url = "http://%s?secret=%s&action=sendSms&cid=%s&to=%s&msg=%s&handler=%s&arg1=%s&arg2=%s" % (config.apiServer, config.apiSecret, cid, to, msg, handler, arg1, arg2)
  115.  
  116.         handler = urllib2.build_opener(MyHandler())
  117.         thread = threading.Thread(target=handler.open, args=(url,))
  118.         thread.start()
  119.         thread.join()
  120.         logstr = "[INFO] [%s] with CallerID [%s] has sent message to [%s]" % (msg_from, cid, to)
  121.         logAppend(logstr)
  122.  
  123.         # messtr = "Ваше сообщение успешно отправлено на [%s]. Результат: [%s]" % (to, answer)
  124.         # print "to %s from %s body %s" % (msg_from, msg_to, messtr)
  125.         # mes = Message(to = msg_from, frm = msg_to, body = messtr, typ = "chat")
  126.         # self.jabber.send(mes)
  127.  
  128.     def mail_check(self):
  129.  
  130.         if time.time() < self.lastcheck + 5:
  131.             return
  132.         self.lastcheck = time.time()
  133.  
  134.         url = "http://%s?secret=%s&action=getEvents" % (config.apiServer, config.apiSecret)
  135.  
  136.         request = urllib2.urlopen(url)
  137.         answer = request.read()
  138.         messages = json.loads(answer)
  139.  
  140.         if not messages:
  141.             return
  142.  
  143.         for sms in messages:
  144.             jfrom = "%s@%s" % (sms["from_num"], config.jid)
  145.             jto = None
  146.             # determine jTo
  147.             for mapping in self.mappings:
  148.                 if mapping[0] == sms["to_num"]:
  149.                     jto = mapping[1]
  150.             # continue if mapping not found
  151.             if not jto:
  152.                 logstr = "[ERROR] Cannot route incoming message for [%s]: no route for this number." % sms["to_num"]
  153.                 logAppend(logstr)
  154.                 continue
  155.             # msg?
  156.             body = sms["message"]
  157.             # send
  158.             m = Message(to = jto, frm = jfrom, body = body, typ = "chat")
  159.             if self.jabber.send(m):
  160.                 logstr = "[INFO] New message for [%s] from [%s]: routed to [%s]" % (sms["to_num"], sms["from_num"], jto)
  161.                 logAppend(logstr)
  162.                 # delivery report
  163.                 url = "http://%s?secret=%s&action=markAsRead&id=%s" % (config.apiServer, config.apiSecret, sms["id"])
  164.                 urllib2.urlopen(url)
  165.             else:
  166.                 logstr = "[ERROR] Cannot deliver message for [%s] from [%s]: routed to [%s]" % (sms["to_num"], sms["from_num"], jto)
  167.                 logAppend(logstr)
  168.  
  169.     def xmpp_connect(self):
  170.         connected = self.jabber.connect((config.mainServer,config.port))
  171.         if config.dumpProtocol: print "connected:",connected
  172.         while not connected:
  173.             time.sleep(5)
  174.             connected = self.jabber.connect((config.mainServer,config.port))
  175.             if config.dumpProtocol: print "connected:",connected
  176.         self.register_handlers()
  177.         if config.dumpProtocol: print "trying auth"
  178.         connected = self.jabber.auth(config.saslUsername,config.secret)
  179.         if config.dumpProtocol: print "auth return:",connected
  180.         return connected
  181.  
  182.     def xmpp_disconnect(self):
  183.         time.sleep(5)
  184.         if not self.jabber.reconnectAndReauth():
  185.             time.sleep(5)
  186.             self.xmpp_connect()
  187.  
  188. def loadConfig():
  189.     configOptions = {}
  190.     for configFile in config.configFiles:
  191.         if os.path.isfile(configFile):
  192.             xmlconfig.reloadConfig(configFile, configOptions)
  193.             config.configFile = configFile
  194.             return
  195.     print "Configuration file not found. You need to create a config file and put it in one of these locations:\n    " + "\n    ".join(config.configFiles)
  196.     sys.exit(1)
  197.  
  198. def logError():
  199.     err = '%s - %s\n'%(time.strftime('%a %d %b %Y %H:%M:%S'),version)
  200.     #if logfile != None:
  201.     #    logfile.write(err)
  202.     #    traceback.print_exc(file=logfile)
  203.     #    logfile.flush()
  204.     sys.stderr.write(err)
  205.     traceback.print_exc()
  206.     sys.exc_clear()
  207.  
  208. def logAppend(logmsg):
  209.     toLog = '[%s] %s\n' % (time.strftime('%a %d %b %Y %H:%M:%S'),logmsg)
  210.     if logfile != None:
  211.         logfile.write(toLog)
  212.         logfile.flush()
  213.  
  214. def sigHandler(signum, frame):
  215.     transport.offlinemsg = 'Signal handler called with signal %s'%signum
  216.     if config.dumpProtocol: print 'Signal handler called with signal %s'%signum
  217.     transport.online = 0
  218.  
  219. if __name__ == '__main__':
  220.     if 'PID' in os.environ:
  221.         config.pid = os.environ['PID']
  222.     loadConfig()
  223.     if config.pid:
  224.         pidfile = open(config.pid,'w')
  225.         pidfile.write(`os.getpid()`)
  226.         pidfile.close()
  227.  
  228.     if config.saslUsername:
  229.         sasl = 1
  230.     else:
  231.         config.saslUsername = config.jid
  232.         sasl = 0
  233.  
  234.     logfile = None
  235.     if config.debugFile:
  236.         logfile = open(config.debugFile,'a')
  237.  
  238.     if config.dumpProtocol:
  239.         debug=['always', 'nodebuilder']
  240.     else:
  241.         debug=[]
  242.     connection = xmpp.client.Component(config.jid,config.port,debug=debug,sasl=sasl,bind=config.useComponentBinding,route=config.useRouteWrap)
  243.     transport = Transport(connection)
  244.     if not transport.xmpp_connect():
  245.         print "Could not connect to server, or password mismatch!"
  246.         sys.exit(1)
  247.     logAppend("Connection successfully established.")
  248.     # Set the signal handlers
  249.     signal.signal(signal.SIGINT, sigHandler)
  250.     signal.signal(signal.SIGTERM, sigHandler)
  251.     transport.lastcheck = time.time() + 10
  252.     while transport.online:
  253.         try:
  254.             connection.Process(1)
  255.             transport.mail_check()
  256.         except KeyboardInterrupt:
  257.             _pendingException = sys.exc_info()
  258.             raise _pendingException[0], _pendingException[1], _pendingException[2]
  259.         except IOError:
  260.             transport.xmpp_disconnect()
  261.         except:
  262.             logError()
  263.         if not connection.isConnected():  transport.xmpp_disconnect()
  264.     connection.disconnect()
  265.     if config.pid:
  266.         os.unlink(config.pid)
  267.     if logfile:
  268.         logfile.close()
  269.     if transport.restart:
  270.         args=[sys.executable]+sys.argv
  271.         if os.name == 'nt': args = ["\"%s\"" % a for a in args]
  272.         if config.dumpProtocol: print sys.executable, args
  273.         os.execv(sys.executable, args)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement