iro/newinterface.py
branchdevel
changeset 240 3406d3bf05d4
parent 239 4cf5e664c847
child 241 546316b0b09c
equal deleted inserted replaced
239:4cf5e664c847 240:3406d3bf05d4
     1 # -*- coding: utf-8 -*-
       
     2 #Copyright (C) 2009  Sandro Knauß <bugs@sandroknauss.de>
       
     3 
       
     4 #This program is free software; you can redistribute it and/or modify it under the terms
       
     5 #of the GNU General Public License as published by the Free Software Foundation;
       
     6 #either version 3 of the License, or any later version.
       
     7 #This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
       
     8 #without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
     9 #See the GNU General Public License for more details.
       
    10 
       
    11 #You should have received a copy of the GNU General Public License
       
    12 #along with this program; if not, see <http://www.gnu.org/licenses/>.
       
    13 from twisted.web import soap, xmlrpc, resource, server
       
    14 import logging
       
    15 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s(%(processName)s)-%(levelname)s: %(message)s')
       
    16 
       
    17 
       
    18 class User(object):
       
    19     def __init__(self,name,userhash):
       
    20         self.name=name
       
    21         self.userhash=userhash
       
    22     
       
    23     def __repr__(self):
       
    24         return"User<'%s','%s'>"%(self.name,self.userhash)
       
    25 
       
    26 users={"1":User("spam","1"),
       
    27        "2":User("foo","2")
       
    28 }
       
    29 
       
    30 def getuser(userhash):
       
    31     try:
       
    32         return users[userhash]
       
    33     except KeyError:
       
    34         raise UserNotFound()
       
    35 
       
    36 def with_user(f):
       
    37     def new_f(*args,**kargs):
       
    38         args=list(args)
       
    39         logging.debug("Entering %s"%f.__name__)
       
    40         try:
       
    41             kargs["user"]=getuser(kargs["apikey"])
       
    42             del kargs["apikey"]
       
    43         except KeyError:
       
    44             kargs["user"]=getuser(args[1])
       
    45             del args[1]
       
    46         ret=f(*args,**kargs)
       
    47         logging.debug("Exited %s"%f.__name__)
       
    48         return ret
       
    49     new_f.__name__ = f.__name__
       
    50     return new_f
       
    51 
       
    52 
       
    53 class InterfaceException(Exception):
       
    54     def __init__(self, code=999, msg="Unbekannter Fehler."):
       
    55         self.code=code
       
    56         self.msg=msg
       
    57 
       
    58     def dict(self):
       
    59         return {"code":self.code,
       
    60                 "msg":self.msg,
       
    61                 }
       
    62     def __str__(self):
       
    63         return "%i:%s"%(self.code,self.msg)
       
    64 
       
    65 class UserNotFound(InterfaceException):
       
    66     def __init__(self):
       
    67         InterfaceException.__init__(self, 901, "Der API-Key ist ungültig.")
       
    68 
       
    69 class ExternalException(InterfaceException):
       
    70     def __init__(self):
       
    71         InterfaceException.__init__(self, 950, "Fehler in externer API.")
       
    72 
       
    73 
       
    74 class Interface(object):
       
    75     '''class for a xmlrpc user
       
    76     '''
       
    77     
       
    78     @with_user
       
    79     def status(self, user, id=None, detailed=False):
       
    80         '''Gibt den aktuellen Status eines Auftrages oder Mehreren zurück.
       
    81 
       
    82         Keywords:
       
    83         apikey[string]: Der API Key
       
    84         id[hash]: Eine Auftragsnummer
       
    85         detailed[boolean]: Details ausgeben
       
    86 
       
    87         Return:
       
    88         jobs[list]: Eine Liste der Aufträge.
       
    89         job.name[string]: Angebener Name
       
    90         job.status[string]: Status des Auftrages
       
    91 
       
    92 
       
    93         '''
       
    94         #return user.status(id,detailed)
       
    95         return ""
       
    96 
       
    97     @with_user
       
    98     def stop(self, user, id):
       
    99         '''Stoppt den angegeben Auftrag.
       
   100 
       
   101         Keywords:
       
   102         apikey[string]: Der API Key
       
   103         id[hash]: Eine Auftragsnummer
       
   104 
       
   105         Return:
       
   106 
       
   107         '''
       
   108         return ""
       
   109     
       
   110     @with_user
       
   111     def sms(self, user, message, recipients, route="default"):
       
   112         '''Versendet eine SMS.
       
   113 
       
   114         Keywords:
       
   115         apikey[string]: Der API Key
       
   116         message[string]: Nachricht
       
   117         recipients[list]: eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
       
   118         route[string|list]: Route über den geschickt werden soll, 
       
   119                             oder eine Liste von Routen, um Fallbacks anzugeben
       
   120 
       
   121         Return:
       
   122         id[hash]: Die ID des Auftrages
       
   123 
       
   124         '''
       
   125         return ""
       
   126    
       
   127     @with_user
       
   128     def fax(self, user, subject, fax, recipients, route="default"):
       
   129         '''Versendet ein FAX.
       
   130 
       
   131         Keywords:
       
   132         apikey[string]: Der API Key
       
   133         subject[string]: Der Betreff
       
   134         fax[string]: Das PDF base64 kodiert
       
   135         recipients[list]: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
       
   136         route[string|list]: Route über den geschickt werden soll, 
       
   137                             oder eine Liste von Routen, um Fallbacks anzugeben
       
   138 
       
   139         Return:
       
   140         id[hash]: Die ID des Auftrages
       
   141 
       
   142         '''
       
   143         return ""
       
   144 
       
   145     @with_user
       
   146     def mail(self, user, subject,  body, recipients, frm, route="default"):
       
   147         '''Versendet eine Email.
       
   148 
       
   149         Keywords:
       
   150         apikey[string]: Der API Key
       
   151         subject[string]: Der Betreff
       
   152         body[string]: Der Email Body
       
   153         recipients[list]: Eine Liste von Emailadressen
       
   154         frm[string]: Die Absender Emailadresse
       
   155         route[string|list]: Route über den geschickt werden soll, 
       
   156                             oder eine Liste von Routen, um Fallbacks anzugeben
       
   157 
       
   158         Return:
       
   159         id[hash]: Die ID des Auftrages
       
   160 
       
   161         '''
       
   162         return ""
       
   163        
       
   164     @with_user
       
   165     def routes(self, user, typ):
       
   166         '''Gibt eine Liste aller verfügbaren Provider zurück.
       
   167 
       
   168         Keywords:
       
   169         apikey[string]: Der API Key
       
   170         typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll
       
   171                      Einer der Liste ["sms","fax","mail"]
       
   172 
       
   173         Return:
       
   174         providerlist[list]: Eine Liste aller möglichen Provider
       
   175 
       
   176         '''
       
   177         return ""
       
   178         
       
   179     @with_user
       
   180     def defaultRoute(self, user, typ):
       
   181         '''Gibt den Standardprovider zurück.
       
   182  
       
   183         Keywords:
       
   184         apikey[string]: Der API Key
       
   185         typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll
       
   186                      Einer der Liste ["sms","fax","mail"]
       
   187 
       
   188         Return:
       
   189         provider[string]: Der Standardprovider für den angeben Typ
       
   190 
       
   191 
       
   192         '''
       
   193         return ""
       
   194 
       
   195     @with_user
       
   196     def statistic(self, user):
       
   197         '''Gibt eine Statik zurück über die versendendeten Nachrichten und des Preises.
       
   198 
       
   199         Keywords:
       
   200         apikey[string]: Der API Key
       
   201 
       
   202         Return:
       
   203         statistic[list]: Eine Liste nach Nachrichtentypen
       
   204         '''
       
   205         return ""
       
   206 
       
   207     def listMethods(self):
       
   208         """Since we override lookupProcedure, its suggested to override
       
   209         listProcedures too.
       
   210         """
       
   211         return self.listProcedures()
       
   212   
       
   213 
       
   214     def listProcedures(self):
       
   215         """Since we override lookupProcedure, its suggested to override
       
   216         listProcedures too.
       
   217         """
       
   218         return ['listMethods','status','stop','sms','fax','mail','routes','defaultRoute','statistic']
       
   219 
       
   220 
       
   221 class XMLRPCInterface(Interface,xmlrpc.XMLRPC): 
       
   222     def __init__(self):
       
   223         xmlrpc.XMLRPC.__init__(self) 
       
   224         Interface.__init__(self)
       
   225     
       
   226     def lookupProcedure(self, procedurePath):
       
   227         logging.debug("lookupProcedure('%s')"%procedurePath)
       
   228         if procedurePath not in self.listProcedures():
       
   229             raise xmlrpc.NoSuchFunction(self.NOT_FOUND,
       
   230                         "procedure %s not found" % procedurePath)
       
   231         try:
       
   232             return getattr(self,procedurePath)
       
   233         except KeyError:
       
   234             raise xmlrpc.NoSuchFunction(self.NOT_FOUND,
       
   235                         "procedure %s not found" % procedurePath)
       
   236 
       
   237 class SOAPInterface(Interface,soap.SOAPPublisher): 
       
   238     def __init__(self):
       
   239         soap.SOAPPublisher.__init__(self) 
       
   240         Interface.__init__(self)
       
   241         
       
   242     def lookupFunction(self, functionName):
       
   243         """Lookup published SOAP function.
       
   244 
       
   245         Override in subclasses. Default behaviour - publish methods
       
   246         starting with soap_, if they have true attribute useKeywords
       
   247         they are expected to accept keywords.
       
   248         
       
   249         @return: tuple (callable, useKeywords), or (None, None) if not found.
       
   250         """
       
   251         if functionName in self.listProcedures():
       
   252             function = getattr(self, functionName, None)
       
   253             if function:
       
   254                 return function, getattr(function, "useKeywords", False)
       
   255             return None
       
   256         else:
       
   257             return None
       
   258 
       
   259 
       
   260 def main():
       
   261     from twisted.internet import reactor
       
   262     root = resource.Resource()
       
   263     root.putChild('RPC2', XMLRPCInterface())
       
   264     root.putChild('SOAP', SOAPInterface())
       
   265     reactor.listenTCP(7080, server.Site(root))
       
   266     reactor.run()
       
   267 
       
   268 if __name__ == '__main__':
       
   269     main()