iro/newinterface.py
author Sandro Knauß <knauss@netzguerilla.net>
Sat, 10 Mar 2012 19:00:12 +0100
branchdevel
changeset 219 4e9d79c35088
parent 85 edf7e94cd607
permissions -rw-r--r--
iro.model.schema.__tables__ is available under Base.metadata.sorted_tables

# -*- coding: utf-8 -*-
#Copyright (C) 2009  Sandro Knauß <bugs@sandroknauss.de>

#This program is free software; you can redistribute it and/or modify it under the terms
#of the GNU General Public License as published by the Free Software Foundation;
#either version 3 of the License, or any later version.
#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#See the GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, see <http://www.gnu.org/licenses/>.
from twisted.web import soap, xmlrpc, resource, server
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s(%(processName)s)-%(levelname)s: %(message)s')


class User(object):
    def __init__(self,name,userhash):
        self.name=name
        self.userhash=userhash
    
    def __repr__(self):
        return"User<'%s','%s'>"%(self.name,self.userhash)

users={"1":User("spam","1"),
       "2":User("foo","2")
}

def getuser(userhash):
    try:
        return users[userhash]
    except KeyError:
        raise UserNotFound()

def with_user(f):
    def new_f(*args,**kargs):
        args=list(args)
        logging.debug("Entering %s"%f.__name__)
        try:
            kargs["user"]=getuser(kargs["apikey"])
            del kargs["apikey"]
        except KeyError:
            kargs["user"]=getuser(args[1])
            del args[1]
        ret=f(*args,**kargs)
        logging.debug("Exited %s"%f.__name__)
        return ret
    new_f.__name__ = f.__name__
    return new_f


class InterfaceException(Exception):
    def __init__(self, code=999, msg="Unbekannter Fehler."):
        self.code=code
        self.msg=msg

    def dict(self):
        return {"code":self.code,
                "msg":self.msg,
                }
    def __str__(self):
        return "%i:%s"%(self.code,self.msg)

class UserNotFound(InterfaceException):
    def __init__(self):
        InterfaceException.__init__(self, 901, "Der API-Key ist ungültig.")

class ExternalException(InterfaceException):
    def __init__(self):
        InterfaceException.__init__(self, 950, "Fehler in externer API.")


class Interface(object):
    '''class for a xmlrpc user
    '''
    
    @with_user
    def status(self, user, id=None, detailed=False):
        '''Gibt den aktuellen Status eines Auftrages oder Mehreren zurück.

        Keywords:
        apikey[string]: Der API Key
        id[hash]: Eine Auftragsnummer
        detailed[boolean]: Details ausgeben

        Return:
        jobs[list]: Eine Liste der Aufträge.
        job.name[string]: Angebener Name
        job.status[string]: Status des Auftrages


        '''
        #return user.status(id,detailed)
        return ""

    @with_user
    def stop(self, user, id):
        '''Stoppt den angegeben Auftrag.

        Keywords:
        apikey[string]: Der API Key
        id[hash]: Eine Auftragsnummer

        Return:

        '''
        return ""
    
    @with_user
    def sms(self, user, message, recipients, route="default"):
        '''Versendet eine SMS.

        Keywords:
        apikey[string]: Der API Key
        message[string]: Nachricht
        recipients[list]: eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
        route[string|list]: Route über den geschickt werden soll, 
                            oder eine Liste von Routen, um Fallbacks anzugeben

        Return:
        id[hash]: Die ID des Auftrages

        '''
        return ""
   
    @with_user
    def fax(self, user, subject, fax, recipients, route="default"):
        '''Versendet ein FAX.

        Keywords:
        apikey[string]: Der API Key
        subject[string]: Der Betreff
        fax[string]: Das PDF base64 kodiert
        recipients[list]: Eine Liste von Emfänger-Nummern (gemäß ITU-T E.123)
        route[string|list]: Route über den geschickt werden soll, 
                            oder eine Liste von Routen, um Fallbacks anzugeben

        Return:
        id[hash]: Die ID des Auftrages

        '''
        return ""

    @with_user
    def mail(self, user, subject,  body, recipients, frm, route="default"):
        '''Versendet eine Email.

        Keywords:
        apikey[string]: Der API Key
        subject[string]: Der Betreff
        body[string]: Der Email Body
        recipients[list]: Eine Liste von Emailadressen
        frm[string]: Die Absender Emailadresse
        route[string|list]: Route über den geschickt werden soll, 
                            oder eine Liste von Routen, um Fallbacks anzugeben

        Return:
        id[hash]: Die ID des Auftrages

        '''
        return ""
       
    @with_user
    def routes(self, user, typ):
        '''Gibt eine Liste aller verfügbaren Provider zurück.

        Keywords:
        apikey[string]: Der API Key
        typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll
                     Einer der Liste ["sms","fax","mail"]

        Return:
        providerlist[list]: Eine Liste aller möglichen Provider

        '''
        return ""
        
    @with_user
    def defaultRoute(self, user, typ):
        '''Gibt den Standardprovider zurück.
 
        Keywords:
        apikey[string]: Der API Key
        typ[string]: Der Typ zu dem die Providerloste ausgeben werden soll
                     Einer der Liste ["sms","fax","mail"]

        Return:
        provider[string]: Der Standardprovider für den angeben Typ


        '''
        return ""

    @with_user
    def statistic(self, user):
        '''Gibt eine Statik zurück über die versendendeten Nachrichten und des Preises.

        Keywords:
        apikey[string]: Der API Key

        Return:
        statistic[list]: Eine Liste nach Nachrichtentypen
        '''
        return ""

    def listMethods(self):
        """Since we override lookupProcedure, its suggested to override
        listProcedures too.
        """
        return self.listProcedures()
  

    def listProcedures(self):
        """Since we override lookupProcedure, its suggested to override
        listProcedures too.
        """
        return ['listMethods','status','stop','sms','fax','mail','routes','defaultRoute','statistic']


class XMLRPCInterface(Interface,xmlrpc.XMLRPC): 
    def __init__(self):
        xmlrpc.XMLRPC.__init__(self) 
        Interface.__init__(self)
    
    def lookupProcedure(self, procedurePath):
        logging.debug("lookupProcedure('%s')"%procedurePath)
        if procedurePath not in self.listProcedures():
            raise xmlrpc.NoSuchFunction(self.NOT_FOUND,
                        "procedure %s not found" % procedurePath)
        try:
            return getattr(self,procedurePath)
        except KeyError:
            raise xmlrpc.NoSuchFunction(self.NOT_FOUND,
                        "procedure %s not found" % procedurePath)

class SOAPInterface(Interface,soap.SOAPPublisher): 
    def __init__(self):
        soap.SOAPPublisher.__init__(self) 
        Interface.__init__(self)
        
    def lookupFunction(self, functionName):
        """Lookup published SOAP function.

        Override in subclasses. Default behaviour - publish methods
        starting with soap_, if they have true attribute useKeywords
        they are expected to accept keywords.
        
        @return: tuple (callable, useKeywords), or (None, None) if not found.
        """
        if functionName in self.listProcedures():
            function = getattr(self, functionName, None)
            if function:
                return function, getattr(function, "useKeywords", False)
            return None
        else:
            return None


def main():
    from twisted.internet import reactor
    root = resource.Resource()
    root.putChild('RPC2', XMLRPCInterface())
    root.putChild('SOAP', SOAPInterface())
    reactor.listenTCP(7080, server.Site(root))
    reactor.run()

if __name__ == '__main__':
    main()