Source code for iro.offer.smstrade

# -*- coding: utf-8 -*-

# Copyright (c) 2012 netzguerilla.net <iro@netzguerilla.net>
# 
# This file is part of Iro.
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
# #Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


import urllib
from functools import partial
from decimal import Decimal
#import copy

from ..config import Option
from ..model.status import Status
from .provider import Provider, providers
from ..error import RejectRecipient, ExternalException

#import logging
#logger=logging.getLogger("smstrade")

statusCodes = {10 : "Empfaengernummer nicht korrekt.",
    20 : "Absenderkennung nicht korrekt.",
    30 : "Nachrichtentext nicht korrekt.",
    31 : "Messagetyp nicht korrekt.",
    40 : "SMS Route nicht korrekt.",
    50 : "Identifikation fehlgeschlagen.",
    60 : "nicht genuegend Guthaben.",
    70 : "Netz wird von Route nicht abgedeckt.",
    71 : "Feature nicht ueber diese Route moeglich.",
    80 : "Uebergabe an SMS-C fehlgeschlagen.",
    90 : "Versand nicht moeglich.",
    100 : "SMS wurde versendet.",
    }
"""statuscodes of external smstrade API"""


[docs]class SmstradeException(ExternalException): """An excetion that connects the status code with the excetion string (see :attr:`statusCodes`)""" def __init__(self,status): ExternalException.__init__(self) self.status = status self.str_=str(status) def __str__(self): return "%s\n%s"%(ExternalException.__str__(self),self.str_)
[docs]class StatusCode: """Class that represents the output of one smstrade request.""" def __init__(self,code, exID=None, costs=Decimal("0.0"), count=0): self.code = code self.exID = exID self.costs = Decimal(costs) self.count = int(count) def __str__(self): if self.code in statusCodes.keys(): return "%i: %s"%(self.code, statusCodes[self.code]) return "%i: unknown statuscode."%self.code def __int__(self): return self.code
[docs]class Smstrade(Provider): """A Provider to send SMS to recipients using smstrade. Smstrade only supports to send SMS and four diffrent routes: ``["basic","economy","gold","direct"]``. It needs a smstrade Gateway Key https://login.smstrade.de/index.php?gateway in configuration file. smstrade API documentation: http://kundencenter.smstrade.de/sites/smstrade.de.kundencenter/__pdf/SMS-Gateway_HTTP_API_v2.pdf The smstrade API supports a debug mode, that can be set with :attr:`~iro.offer.provider.Provider.testmode`. """ _params= {"debug":("boolean",False), "concat_sms":('boolean',False), "message_id":('boolean',False), "count":('boolean',False), "cost":('boolean',False), } '''dict for standrd values of the smstrade api, it is used to get the right values to the API.''' def __init__(self, name): self.url = "https://gateway.smstrade.de" options =[("key", Option(lambda x,y:x,long="smstrade Gateway Key https://login.smstrade.de/index.php?gateway", must=True)),] Provider.__init__(self, name, {"sms":["basic","economy","gold","direct"]},options)
[docs] def send(self, route, recipient, sms): """send one SMS to recipient via route :param string route: A valid route ``["basic", "economy", "gold", "direct"]`` :param `iro.telnumber.Telnumber` recipient: Mobilenumber of recipient :param `iro.model.message.SMS` sms: the sms to send :return: - All went ok -- :class:`iro.model.status.Status` object - otherwise -- an exception """ #logger.debug('smstrade.sendSMS(%s,%s)'%(sms, recipient)) route = unicode(route) if recipient.land != '49' and route == "basic": raise RejectRecipient(recipient) to ='00'+recipient.land+recipient.number s = self.__send(route, to, sms) if int(s) in (100,): return Status(self,route, exID=s.exID, costs=s.costs, count=s.count) elif int(s) in (70,71,): raise RejectRecipient(recipient, status=s) else: raise SmstradeException(s)
def __send(self, route, to, sms): """ This is the main function to request to the sms service. :param string route: A valid route ``["basic", "economy", "gold", "direct"] :param string recipient: Mobilenumber of recipient :param `iro.model.message.sms` sms: the sms to send :return: a :class:`.StatusCode` object """ #logger.debug('smstrade._send(%s,%s,%s)'%( route, to, sms)) parameters= {"key": self.key, "route": route, "to": to, "message": sms.content, "charset":"utf-8", "debug": self.testmode, "message_id":True, "count":True, "cost":True, } doubleChar="€[]{}|\\^~" #these charactar need two GSM Chars if sms.from_ is not None: parameters["from"] = sms.from_ length=len(sms.content) for s in doubleChar: length += sms.content.count(s) parameters["concat_sms"] = True if length > 160 else False ps={} for p in parameters: if p in self._params.keys(): if self._params[p][0] == "boolean": if parameters[p] != self._params[p][1]: ps[p]=int(bool(parameters[p])) else: ps[p] = parameters[p] params = urllib.urlencode(ps) #dp=copy.deepcopy(ps) #dp["key"]="<KEY>" #print 'smstrade._send-parameters:%s\n\t->%s'%(str(dp), urllib.urlencode(dp)) response = urllib.urlopen(self.url, params) data = response.readlines() if len(data) == 1: return StatusCode(int(data[0])) return StatusCode(int(data[0]),exID=data[1],costs=data[2],count=data[3])
[docs] def getSendFunc(self, typ, route): """returns a partial :meth:`send` methed with bounded route, if typ and route is valid.""" Provider.getSendFunc(self, typ, route) return partial(self.send,route)
providers["smstrade"]=Smstrade