sms: remove all but passerelle provider (#39088)
This commit is contained in:
parent
fd45925d20
commit
3d2c05b87a
|
@ -486,7 +486,7 @@ def test_workflows_check_available_actions(pub):
|
|||
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
||||
pub.site_options.write(fd)
|
||||
|
||||
pub.cfg['sms'] = {'mode': 'foobar'}
|
||||
pub.cfg['sms'] = {'passerelle_url': 'xx', 'sender': 'xx'}
|
||||
pub.write_cfg()
|
||||
workflow.criticality_levels = [WorkflowCriticalityLevel(name='green')]
|
||||
workflow.store()
|
||||
|
@ -814,7 +814,7 @@ def test_workflows_edit_sms_action(pub):
|
|||
workflow.add_status(name='baz')
|
||||
workflow.store()
|
||||
|
||||
pub.cfg['sms'] = {'mode': 'foobar'}
|
||||
pub.cfg['sms'] = {'passerelle_url': 'xx', 'sender': 'xx'}
|
||||
pub.write_cfg()
|
||||
|
||||
app = login(get_app(pub))
|
||||
|
|
|
@ -3419,7 +3419,7 @@ def test_per_user_view_tracking_code(pub, emails, sms_mocking):
|
|||
user_view_resp = app.get('/backoffice/management/users/%s/' % user.id)
|
||||
assert 'Send tracking code' in user_view_resp.text
|
||||
|
||||
pub.cfg['sms'] = {'mode': 'none'}
|
||||
pub.cfg['sms'] = {}
|
||||
pub.write_cfg()
|
||||
resp = user_view_resp.click('Send tracking code')
|
||||
assert not 'sms' in resp.form.fields
|
||||
|
@ -3431,7 +3431,7 @@ def test_per_user_view_tracking_code(pub, emails, sms_mocking):
|
|||
assert emails.get('Tracking Code reminder')['email_rcpt'] == [user.email]
|
||||
assert form_class.get(number31.id).tracking_code in emails.get('Tracking Code reminder')['payload']
|
||||
|
||||
pub.cfg['sms'] = {'mode': 'xx'}
|
||||
pub.cfg['sms'] = {'passerelle_url': 'xx', 'sender': 'xx'}
|
||||
pub.write_cfg()
|
||||
resp = user_view_resp.click('Send tracking code', index=0)
|
||||
resp.form['method'].value = 'SMS'
|
||||
|
|
|
@ -2341,7 +2341,7 @@ def test_jump_missing_previous_mark(two_pubs):
|
|||
|
||||
|
||||
def test_sms(pub, sms_mocking):
|
||||
pub.cfg['sms'] = {'mode': 'xxx'}
|
||||
pub.cfg['sms'] = {'sender': 'xxx', 'passerelle_url': 'http://passerelle.invalid/'}
|
||||
formdef = FormDef()
|
||||
formdef.name = 'baz'
|
||||
formdef.fields = []
|
||||
|
|
|
@ -398,21 +398,16 @@ class HttpRequestsMocking(object):
|
|||
return len(self.requests)
|
||||
|
||||
|
||||
class SMSMocking(wcs.qommon.sms.MobytSMS):
|
||||
def get_sms_class(self, mode):
|
||||
if mode == 'none':
|
||||
return None
|
||||
return self
|
||||
class SMSMocking(wcs.qommon.sms.PasserelleSMS):
|
||||
def get_sms_class(self):
|
||||
sms_cfg = get_publisher().cfg.get('sms', {})
|
||||
if sms_cfg.get('sender') and sms_cfg.get('passerelle_url'):
|
||||
return self
|
||||
return None
|
||||
|
||||
def send(self, sender, destinations, text, quality=None):
|
||||
def send(self, sender, destinations, text):
|
||||
self.sms.append({'sender': sender, 'destinations': destinations, 'text': text})
|
||||
|
||||
def get_sms_left(self, type='standard'):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_money_left(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __enter__(self):
|
||||
self.sms = []
|
||||
self.wcs_get_sms_class = wcs.qommon.sms.SMS.get_sms_class
|
||||
|
|
|
@ -425,7 +425,7 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
'template', 'emails', 'debug_options', 'language',
|
||||
('import', 'p_import'), 'export', 'identification', 'sitename',
|
||||
'sms', 'certificates', 'texts', 'install_theme',
|
||||
'session', 'download_theme', 'smstest', 'postgresql',
|
||||
'session', 'download_theme', 'postgresql',
|
||||
('admin-permissions', 'admin_permissions'), 'geolocation',
|
||||
'theme_preview', 'filetypes',
|
||||
('user-template', 'user_template'),
|
||||
|
@ -1101,103 +1101,22 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _('SMS Options')
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
mode = sms_cfg.get('mode', 'none')
|
||||
sms = SMS.get_sms_class(mode)
|
||||
if sms:
|
||||
r += htmltext('<ul>')
|
||||
try:
|
||||
try:
|
||||
r += htmltext('<li>%s %s</li>') % (_('SMS Credit:'), sms.get_money_left())
|
||||
except NotImplementedError:
|
||||
pass
|
||||
try:
|
||||
r += htmltext('<li>%s %s</li>') % (_('SMS Left:'), sms.get_sms_left())
|
||||
except NotImplementedError:
|
||||
pass
|
||||
except errors.SMSError:
|
||||
r += htmltext("<p>%s</li>") % _("Connection with SMS provider failed")
|
||||
r += htmltext('</ul>')
|
||||
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.add(SingleSelectWidget, 'mode', title = _('SMS Mode'),
|
||||
value = mode,
|
||||
options = [(str('none'), _('No support'), str('none'))]+
|
||||
[(str(k), _(SMS.providers.get(k)[0]), str(k)) for k in SMS.providers.keys()])
|
||||
|
||||
form.add(StringWidget, 'sender', title=_('Sender (number of name)'),
|
||||
value=sms_cfg.get('sender'))
|
||||
form.add(StringWidget, 'passerelle_url', title=_('URL'),
|
||||
value=sms_cfg.get('passerelle_url'))
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_widget('cancel').parse():
|
||||
return redirect('.')
|
||||
|
||||
if sms:
|
||||
for widget, name, title in sms.parameters:
|
||||
form.add(widget, name, title=_(title),
|
||||
value=sms_cfg.get(name, ''),
|
||||
required=True)
|
||||
if form.get_submit() and not form.has_errors():
|
||||
cfg_submit(form, 'sms', ['mode'] + [x[1] for x in sms.parameters])
|
||||
if mode != form.get_widget('mode').parse():
|
||||
return redirect('sms')
|
||||
else:
|
||||
return redirect('.')
|
||||
elif mode != form.get_widget('mode').parse():
|
||||
cfg_submit(form, 'sms', ['mode',])
|
||||
return redirect('sms')
|
||||
else:
|
||||
if form.get_submit() and form.get_widget('mode').parse() == str('none'):
|
||||
return redirect('.')
|
||||
|
||||
if form.get_submit() and not form.has_errors():
|
||||
cfg_submit(form, 'sms', ['mode',])
|
||||
return redirect('sms')
|
||||
else:
|
||||
r += form.render()
|
||||
cfg_submit(form, 'sms', ['sender', 'passerelle_url'])
|
||||
return redirect('.')
|
||||
|
||||
if mode != 'none':
|
||||
r += htmltext('<p><a href="smstest">%s</a></p>') % _('SMS Test')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
|
||||
def smstest(self):
|
||||
form = Form(enctype='multipart/form-data', action='smstest')
|
||||
form.add(StringWidget, 'sender', title=_('Sender'), required=True)
|
||||
form.add(StringWidget, 'destinations', title=_('Destinations'), required=True)
|
||||
form.add(StringWidget, 'text', title=_('Text'), required=True)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_widget('cancel').parse():
|
||||
return redirect('sms')
|
||||
|
||||
get_response().breadcrumb.append(('sms', _('SMS')))
|
||||
get_response().breadcrumb.append(('smstest', _('SMS Test')))
|
||||
html_top('settings', title = _('SMS Test'))
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _('SMS Test')
|
||||
r += form.render()
|
||||
|
||||
if form.get_submit() and not form.has_errors():
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
mode = sms_cfg.get('mode', 'none')
|
||||
sms = SMS.get_sms_class(mode)
|
||||
|
||||
sender = str(form.get_widget('sender').parse())
|
||||
destinations = str(form.get_widget('destinations').parse()).split(str(','))
|
||||
text = str(form.get_widget('text').parse())
|
||||
|
||||
try:
|
||||
sms.send(sender, destinations, text)
|
||||
except Exception as e:
|
||||
r += htmltext('<pre>')
|
||||
r += repr(e)
|
||||
r += htmltext('</pre>')
|
||||
else:
|
||||
r += htmltext('<p>')
|
||||
r += _('The SMS has been sent successfully.')
|
||||
r += htmltext('</p>')
|
||||
|
||||
return r.getvalue()
|
||||
|
||||
def postgresql(self):
|
||||
|
|
|
@ -146,9 +146,7 @@ class SendCodeFormdefDirectory(Directory):
|
|||
value=submitter_email)
|
||||
sms_class = None
|
||||
if get_publisher().use_sms_feature:
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
mode = sms_cfg.get('mode', 'none')
|
||||
sms_class = sms.SMS.get_sms_class(mode)
|
||||
sms_class = sms.SMS.get_sms_class()
|
||||
if sms_class:
|
||||
form.add(StringWidget, 'sms', title=_('SMS Number'), required=False)
|
||||
form.add(RadiobuttonsWidget, 'method',
|
||||
|
@ -180,6 +178,7 @@ class SendCodeFormdefDirectory(Directory):
|
|||
if sms_class and form.get_widget('method').parse() == 'sms':
|
||||
# send sms
|
||||
sitename = get_cfg('misc', {}).get('sitename') or 'w.c.s.'
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
sender = sms_cfg.get('sender', sitename)[:11]
|
||||
message = Template(message).render(data)
|
||||
try:
|
||||
|
|
|
@ -24,188 +24,7 @@ from .form import StringWidget, PasswordWidget
|
|||
from wcs.wscalls import call_webservice
|
||||
|
||||
|
||||
class MobytSMS(object):
|
||||
"""This class allows to send a SMS using Mobyt provider"""
|
||||
parameters = [
|
||||
(StringWidget, 'sender', N_('Sender (number or name)')),
|
||||
(StringWidget, 'mobyt_username', N_('Username')),
|
||||
(PasswordWidget, 'mobyt_password', N_('Password')),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
self.user = sms_cfg.get('mobyt_username', '')
|
||||
self.password = sms_cfg.get('mobyt_password', '')
|
||||
|
||||
def send(self, sender, destinations, text, quality='l'):
|
||||
""" Send a sms using Mobyt provider"""
|
||||
rcpt = ""
|
||||
for dest in destinations:
|
||||
rcpt += "%s," % dest
|
||||
rcpt = rcpt[:len(rcpt) - 1]
|
||||
params = urllib.urlencode({
|
||||
'user': self.user,
|
||||
'pass': self.password,
|
||||
'rcpt': rcpt,
|
||||
'data': text,
|
||||
'sender': sender,
|
||||
'qty': quality
|
||||
})
|
||||
try:
|
||||
r = misc.urlopen("http://multilevel.mobyt.fr/sms/batch.php", params)
|
||||
except misc.ConnectionError as e:
|
||||
raise errors.SMSError("failed to POST to mobyt.fr (%s)" % e)
|
||||
answer = r.read()
|
||||
r.close()
|
||||
if answer[:2] == "KO":
|
||||
raise errors.SMSError(answer[3:])
|
||||
|
||||
def get_credit(self, type):
|
||||
params = urllib.urlencode({
|
||||
'user': self.user,
|
||||
'pass': self.password,
|
||||
'type': type
|
||||
})
|
||||
try:
|
||||
r = misc.urlopen("http://multilevel.mobyt.fr/sms/credit.php", params)
|
||||
except misc.ConnectionError as e:
|
||||
raise errors.SMSError("failed to POST to mobyt.fr (%s)" % e)
|
||||
answer = r.read()
|
||||
r.close()
|
||||
if answer[:2] == "KO":
|
||||
raise errors.SMSError(answer[3:])
|
||||
else:
|
||||
return answer[3:]
|
||||
|
||||
def get_sms_left(self, type="standard"):
|
||||
"""
|
||||
type (mobyt provider): standard, lowcost or top
|
||||
"""
|
||||
if type == "standard":
|
||||
return self.get_credit("l")
|
||||
elif type == "lowcost":
|
||||
return self.get_credit("ll")
|
||||
elif type == "top":
|
||||
return self.get_credit("n")
|
||||
else:
|
||||
raise errors.SMSError("%s is invalid type for provider Mobyt" % type)
|
||||
|
||||
def get_money_left(self):
|
||||
""" return money left in euros """
|
||||
return self.get_credit("credit")
|
||||
|
||||
|
||||
class OxydSMS(object):
|
||||
"""This class allows to send a SMS using Oxyd provider"""
|
||||
parameters = [
|
||||
(StringWidget, 'oxyd_username', N_('Username')),
|
||||
(PasswordWidget, 'oxyd_password', N_('Password')),
|
||||
(StringWidget, 'oxyd_default_country_code', N_('Default Country Code')),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
self.user = sms_cfg.get('oxyd_username', '')
|
||||
self.password = sms_cfg.get('oxyd_password', '')
|
||||
self.default_country_code = sms_cfg.get('oxyd_default_country_code')
|
||||
if not self.default_country_code:
|
||||
self.default_country_code = '33' # arbitrary
|
||||
|
||||
def send(self, sender, destinations, text, quality=None):
|
||||
"""Send a SMS using Oxyd provider"""
|
||||
# unfortunately it lacks a batch API...
|
||||
for dest in destinations:
|
||||
# oxyd needs the number prefixed by the country code, this is
|
||||
# really unfortunate.
|
||||
number = ''.join(re.findall(r'\d', dest))
|
||||
if dest.startswith('+'):
|
||||
pass # it already is fully qualified
|
||||
elif number.startswith('00'):
|
||||
# assumes 00 is international access code, remove it
|
||||
number = number[2:]
|
||||
elif number.startswith('0'):
|
||||
# local prefix, remove 0 and add default country code
|
||||
number = self.default_country_code + number[1:]
|
||||
params = urllib.urlencode({
|
||||
'id': self.user,
|
||||
'pass': self.password,
|
||||
'num': number,
|
||||
'sms': text,
|
||||
'flash': '0'
|
||||
})
|
||||
try:
|
||||
r = misc.urlopen('http://sms.oxyd.fr/send.php', params)
|
||||
except misc.ConnectionError as e:
|
||||
# XXX: add proper handling of errors
|
||||
raise errors.SMSError("failed to POST to oxyd.fr (%s)" % e)
|
||||
r.close()
|
||||
|
||||
def get_sms_left(self, type='standard'):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_money_left(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class ChoositSMS(object):
|
||||
"""This class allows to send a SMS using the Choosit provider
|
||||
|
||||
http://sms.choosit.com/documentation_technique.html
|
||||
"""
|
||||
parameters = [
|
||||
(StringWidget, 'choosit_key', N_('Key')),
|
||||
(StringWidget, 'choosit_default_country_code', N_('Default Country Code')),
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
self.key = sms_cfg.get('choosit_key', '')
|
||||
self.default_country_code = sms_cfg.get('choosit_default_country_code')
|
||||
if not self.default_country_code:
|
||||
self.default_country_code = '33' # arbitrary
|
||||
|
||||
def send(self, sender, destinations, text, quality=None):
|
||||
"""Send a SMS using the Choosit provider"""
|
||||
# unfortunately it lacks a batch API...
|
||||
for dest in destinations:
|
||||
# choosit needs the number prefixed by the country code, this is
|
||||
# really unfortunate.
|
||||
number = ''.join(re.findall(r'\d', dest))
|
||||
if dest.startswith('+'):
|
||||
pass # it already is fully qualified
|
||||
elif number.startswith('00'):
|
||||
# assumes 00 is international access code, remove it
|
||||
number = number[2:]
|
||||
elif number.startswith('0'):
|
||||
# local prefix, remove 0 and add default country code
|
||||
number = self.default_country_code + number[1:]
|
||||
params = urllib.urlencode({
|
||||
'key': self.key,
|
||||
'recipient': number,
|
||||
'content': text[:160],
|
||||
})
|
||||
try:
|
||||
r = misc.urlopen('http://sms.choosit.com/webservice', params)
|
||||
except misc.ConnectionError as e:
|
||||
# XXX: add proper handling of errors
|
||||
raise errors.SMSError("failed to POST to choosit.com (%s)" % e)
|
||||
r.close()
|
||||
|
||||
def get_sms_left(self, type='standard'):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_money_left(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PasserelleSMS(object):
|
||||
"""This class allows to send a SMS using Passerelle
|
||||
"""
|
||||
parameters = [
|
||||
(StringWidget, 'sender', N_('Sender (number or name)')),
|
||||
(StringWidget, 'passerelle_url', N_('URL')),
|
||||
]
|
||||
|
||||
TIMEOUT = 10
|
||||
|
||||
def __init__(self):
|
||||
|
@ -214,7 +33,6 @@ class PasserelleSMS(object):
|
|||
self.url = sms_cfg.get('passerelle_url', '')
|
||||
|
||||
def send(self, sender, destinations, text, quality=None):
|
||||
"""Send a SMS using the Choosit provider"""
|
||||
sender = sender or self.sender
|
||||
payload = {
|
||||
'from': sender,
|
||||
|
@ -227,27 +45,12 @@ class PasserelleSMS(object):
|
|||
get_logger().debug('sms %r sent using passerelle to %r, result: %r',
|
||||
text, destinations, data)
|
||||
|
||||
def get_sms_left(self, type='standard'):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_money_left(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class SMS(object):
|
||||
providers = {
|
||||
'mobyt': (N_('Mobyt provider'), MobytSMS),
|
||||
'oxyd': (N_('Oxyd provider'), OxydSMS),
|
||||
'choosit': (N_('Choosit provider'), ChoositSMS),
|
||||
'passerelle': (N_('Passerelle provider'), PasserelleSMS),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_sms_class(cls, provider_id):
|
||||
if not provider_id:
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
provider_id = sms_cfg.get('mode', '')
|
||||
if provider_id in cls.providers:
|
||||
return cls.providers.get(provider_id)[1]()
|
||||
else:
|
||||
return None
|
||||
def get_sms_class(cls):
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
if sms_cfg.get('sender') and sms_cfg.get('passerelle_url'):
|
||||
return PasserelleSMS()
|
||||
return None
|
||||
|
|
|
@ -2826,8 +2826,8 @@ class SendSMSWorkflowStatusItem(WorkflowStatusItem):
|
|||
|
||||
@classmethod
|
||||
def is_available(cls, workflow=None):
|
||||
sms_mode = get_cfg('sms', {}).get('mode') or 'none'
|
||||
return sms_mode != 'none'
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
return bool(sms_cfg.get('sender') and sms_cfg.get('passerelle_url'))
|
||||
|
||||
def get_parameters(self):
|
||||
return ('to', 'body', 'condition')
|
||||
|
@ -2868,9 +2868,8 @@ class SendSMSWorkflowStatusItem(WorkflowStatusItem):
|
|||
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
sender = sms_cfg.get('sender', 'AuQuotidien')[:11]
|
||||
mode = sms_cfg.get('mode', 'none')
|
||||
try:
|
||||
sms.SMS.get_sms_class(mode).send(sender, destinations, sms_body)
|
||||
sms.SMS.get_sms_class().send(sender, destinations, sms_body)
|
||||
except errors.SMSError as e:
|
||||
get_logger().error(e)
|
||||
|
||||
|
|
Loading…
Reference in New Issue