Projet

Général

Profil

0001-sms-add-SMS-class-to-store-sms-parameters-21465.patch

Nicolas Roche, 24 avril 2020 18:27

Télécharger (24,2 ko)

Voir les différences:

Subject: [PATCH 1/3] sms: add SMS class to store sms parameters (#21465)

 .../choosit/migrations/0010_choositsms.py     | 33 +++++++++++++++++++
 passerelle/apps/choosit/models.py             | 12 +++++--
 .../apps/mobyt/migrations/0009_mobytsms.py    | 33 +++++++++++++++++++
 passerelle/apps/mobyt/models.py               | 14 +++++---
 .../apps/orange/migrations/0009_orangesms.py  | 33 +++++++++++++++++++
 passerelle/apps/orange/models.py              | 10 +++++-
 passerelle/apps/ovh/migrations/0009_ovhsms.py | 33 +++++++++++++++++++
 passerelle/apps/ovh/models.py                 | 12 +++++--
 .../apps/oxyd/migrations/0009_oxydsms.py      | 33 +++++++++++++++++++
 passerelle/apps/oxyd/models.py                | 12 +++++--
 .../apps/twilio/migrations/0002_twiliosms.py  | 33 +++++++++++++++++++
 passerelle/apps/twilio/models.py              | 12 +++++--
 passerelle/base/models.py                     | 22 +++++++++++++
 13 files changed, 279 insertions(+), 13 deletions(-)
 create mode 100644 passerelle/apps/choosit/migrations/0010_choositsms.py
 create mode 100644 passerelle/apps/mobyt/migrations/0009_mobytsms.py
 create mode 100644 passerelle/apps/orange/migrations/0009_orangesms.py
 create mode 100644 passerelle/apps/ovh/migrations/0009_ovhsms.py
 create mode 100644 passerelle/apps/oxyd/migrations/0009_oxydsms.py
 create mode 100644 passerelle/apps/twilio/migrations/0002_twiliosms.py
passerelle/apps/choosit/migrations/0010_choositsms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('choosit', '0009_choositsmsgateway_max_message_length'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='ChoositSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='choosit.ChoositSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'Choosit SMS',
30
                'db_table': 'sms_choosit_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/choosit/models.py
2 2
import json
3 3
import requests
4 4

  
5 5
from django.utils.six import string_types
6 6
from django.utils.translation import ugettext_lazy as _
7 7
from django.db import models
8 8

  
9 9
from passerelle.utils.jsonresponse import APIError
10
from passerelle.base.models import SMSResource
10
from passerelle.base.models import SMSResource, SMS
11 11

  
12 12

  
13 13
class ChoositSMSGateway(SMSResource):
14 14
    key = models.CharField(verbose_name=_('Key'), max_length=64)
15 15
    default_country_code = models.CharField(verbose_name=_('Default country code'), max_length=3,
16 16
                                            default=u'33')
17 17
    default_trunk_prefix = models.CharField(verbose_name=_('Default trunk prefix'), max_length=2,
18 18
                                            default=u'0')
......
61 61
                }
62 62
            }
63 63

  
64 64
        ],
65 65
    }
66 66
    URL = 'http://sms.choosit.com/webservice'
67 67

  
68 68
    class Meta:
69
        verbose_name = 'Choosit'
69
        verbose_name = _('Choosit')
70 70
        db_table = 'sms_choosit'
71 71

  
72 72
    @classmethod
73 73
    def get_verbose_name(cls):
74 74
        return cls._meta.verbose_name
75 75

  
76 76
    def send_msg(self, text, sender, destinations, **kwargs):
77 77
        """Send a SMS using the Choosit provider"""
......
103 103
                    elif 'error' in output:
104 104
                        results.append(u'Choosit error: %s' % output['error'])
105 105
                    else:
106 106
                        results.append(output)
107 107
        if any(isinstance(result, string_types) for result in results):
108 108
            raise APIError('Choosit error: some destinations failed',
109 109
                           data=list(zip(destinations, results)))
110 110
        return list(zip(destinations, results))
111

  
112

  
113
class ChoositSMS(SMS):
114
    gateway = models.ForeignKey(ChoositSMSGateway, related_name='sms_set')
115

  
116
    class Meta:
117
        verbose_name = _('Choosit SMS')
118
        db_table = 'sms_choosit_sms'
passerelle/apps/mobyt/migrations/0009_mobytsms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('mobyt', '0008_auto_20200310_1539'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='MobytSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='mobyt.MobytSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'Mobyt SMS',
30
                'db_table': 'sms_mobyt_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/mobyt/models.py
1 1
from django.utils.translation import ugettext_lazy as _
2 2
from django.db import models
3 3

  
4 4
import requests
5 5

  
6 6
from passerelle.utils.jsonresponse import APIError
7
from passerelle.base.models import SMSResource
7
from passerelle.base.models import SMSResource, SMS
8 8

  
9 9

  
10 10
class MobytSMSGateway(SMSResource):
11 11
    URL = 'http://multilevel.mobyt.fr/sms/batch.php'
12 12
    MESSAGES_QUALITIES = (
13 13
        ('l', _('sms direct')),
14 14
        ('ll', _('sms low-cost')),
15 15
        ('n', _('sms top')),
......
34 34
        'test_vectors': [
35 35
            {
36 36
                'response': '',
37 37
                'result': {
38 38
                    'err': 1,
39 39
                    'err_desc': 'MobyT error: response is not "OK"',
40 40
                }
41 41
            }
42

  
43 42
        ],
44

  
45 43
    }
46 44

  
47 45
    class Meta:
48
        verbose_name = 'Mobyt'
46
        verbose_name = _('Mobyt')
49 47
        db_table = 'sms_mobyt'
50 48

  
51 49
    def send_msg(self, text, sender, destinations, **kwargs):
52 50
        """Send a SMS using the Mobyt provider"""
53 51
        # unfortunately it lacks a batch API...
54 52
        destinations = self.clean_numbers(destinations,
55 53
                                          self.default_country_code,
56 54
                                          self.default_trunk_prefix)
......
65 63
        }
66 64
        try:
67 65
            r = self.requests.post(self.URL, data=params)
68 66
        except requests.RequestException as e:
69 67
            raise APIError('MobyT error: POST failed, %s' % e)
70 68
        if r.content[:2] != "OK":
71 69
            raise APIError('MobyT error: response is not "OK"')
72 70
        return None
71

  
72

  
73
class MobytSMS(SMS):
74
    gateway = models.ForeignKey(MobytSMSGateway, related_name='sms_set')
75

  
76
    class Meta:
77
        verbose_name = _('Mobyt SMS')
78
        db_table = 'sms_mobyt_sms'
passerelle/apps/orange/migrations/0009_orangesms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('orange', '0008_auto_20200412_1240'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='OrangeSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='orange.OrangeSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'Orange SMS',
30
                'db_table': 'sms_orange_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/orange/models.py
17 17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 18
# GNU Affero General Public License for more details.
19 19
#
20 20
# You should have received a copy of the GNU Affero General Public License
21 21
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 22
from django.db import models
23 23
from django.utils.translation import ugettext_lazy as _
24 24

  
25
from passerelle.base.models import SMSResource
25
from passerelle.base.models import SMSResource, SMS
26 26
from passerelle.utils.jsonresponse import APIError
27 27

  
28 28
BASE_API = 'https://contact-everyone.orange-business.com/api/v1.2/'
29 29
URL_TOKEN = BASE_API + 'oauth/token'
30 30
URL_GROUPS = BASE_API + 'groups'
31 31
URL_DIFFUSION = BASE_API + 'groups/%s/diffusion-requests'
32 32

  
33 33

  
......
109 109
    def send_msg(self, text, sender, destinations, **kwargs):
110 110
        '''Send a SMS using the Orange provider'''
111 111
        destinations = self.clean_numbers(
112 112
            destinations, self.default_country_code, self.default_trunk_prefix)
113 113
        access_token = self.get_access_token()
114 114
        group_id = self.group_id_from_name(access_token)
115 115
        response = self.diffusion(access_token, group_id, destinations, text)
116 116
        return response
117

  
118

  
119
class OrangeSMS(SMS):
120
    gateway = models.ForeignKey(OrangeSMSGateway, related_name='sms_set')
121

  
122
    class Meta:
123
        verbose_name = _('Orange SMS')
124
        db_table = 'sms_orange_sms'
passerelle/apps/ovh/migrations/0009_ovhsms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('ovh', '0008_ovhsmsgateway_max_message_length'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='OVHSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='ovh.OVHSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'OVH SMS',
30
                'db_table': 'sms_ovh_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/ovh/models.py
1 1
import requests
2 2

  
3 3
from django.utils.translation import ugettext_lazy as _
4 4
from django.db import models
5 5
from django.utils.encoding import force_text
6 6

  
7 7
from passerelle.utils.jsonresponse import APIError
8
from passerelle.base.models import SMSResource
8
from passerelle.base.models import SMSResource, SMS
9 9

  
10 10

  
11 11
class OVHSMSGateway(SMSResource):
12 12
    URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi'
13 13
    MESSAGES_CLASSES = (
14 14
        (0, _('Message are directly shown to users on phone screen '
15 15
              'at reception. The message is never stored, neither in the '
16 16
              'phone memory nor in the SIM card. It is deleted as '
......
72 72
                }
73 73
            }
74 74

  
75 75
        ],
76 76

  
77 77
    }
78 78

  
79 79
    class Meta:
80
        verbose_name = 'OVH'
80
        verbose_name = _('OVH')
81 81
        db_table = 'sms_ovh'
82 82

  
83 83
    def send_msg(self, text, sender, destinations, **kwargs):
84 84
        """Send a SMS using the OVH provider"""
85 85
        destinations = self.clean_numbers(destinations,
86 86
                                          self.default_country_code,
87 87
                                          self.default_trunk_prefix)
88 88

  
......
122 122
                        ret['warning'] = ('credit level too low for %s: %s (threshold %s)' %
123 123
                                          (self.slug, credit_left, self.credit_threshold_alert))
124 124
                    ret['credit_left'] = credit_left
125 125
                    ret['ovh_result'] = result
126 126
                    ret['sms_ids'] = result.get('SmsIds', [])
127 127
                    return ret
128 128
                else:
129 129
                    raise APIError('OVH error: %r' % result)
130

  
131

  
132
class OVHSMS(SMS):
133
    gateway = models.ForeignKey(OVHSMSGateway, related_name='sms_set')
134

  
135
    class Meta:
136
        verbose_name = _('OVH SMS')
137
        db_table = 'sms_ovh_sms'
passerelle/apps/oxyd/migrations/0009_oxydsms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('oxyd', '0008_oxydsmsgateway_max_message_length'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='OxydSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='oxyd.OxydSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'Oxyd SMS',
30
                'db_table': 'sms_oxyd_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/oxyd/models.py
1 1
import requests
2 2

  
3 3
from django.db import models
4 4
from django.utils.encoding import force_text
5 5

  
6 6
from passerelle.utils.jsonresponse import APIError
7
from passerelle.base.models import SMSResource
7
from passerelle.base.models import SMSResource, SMS
8 8
from django.utils.translation import ugettext_lazy as _
9 9

  
10 10

  
11 11
class OxydSMSGateway(SMSResource):
12 12
    username = models.CharField(verbose_name=_('Username'), max_length=64)
13 13
    password = models.CharField(verbose_name=_('Password'), max_length=64)
14 14
    default_country_code = models.CharField(verbose_name=_('Default country code'), max_length=3,
15 15
                                            default=u'33')
......
43 43
                    'data': None,
44 44
                }
45 45
            }
46 46
        ],
47 47
    }
48 48
    URL = 'http://sms.oxyd.fr/send.php'
49 49

  
50 50
    class Meta:
51
        verbose_name = 'Oxyd'
51
        verbose_name = _('Oxyd')
52 52
        db_table = 'sms_oxyd'
53 53

  
54 54
    def send_msg(self, text, sender, destinations, **kwargs):
55 55
        """Send a SMS using the Oxyd provider"""
56 56
        # unfortunately it lacks a batch API...
57 57
        destinations = self.clean_numbers(destinations,
58 58
                                          self.default_country_code,
59 59
                                          self.default_trunk_prefix)
......
81 81
                'OXYD error: some destinations failed', data=list(zip(destinations, results)))
82 82
        return None
83 83

  
84 84
    def get_sms_left(self, type='standard'):
85 85
        raise NotImplementedError
86 86

  
87 87
    def get_money_left(self):
88 88
        raise NotImplementedError
89

  
90

  
91
class OxydSMS(SMS):
92
    gateway = models.ForeignKey(OxydSMSGateway, related_name='sms_set')
93

  
94
    class Meta:
95
        verbose_name = _('Oxyd SMS')
96
        db_table = 'sms_oxyd_sms'
passerelle/apps/twilio/migrations/0002_twiliosms.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-04-24 14:50
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6
import django.db.models.deletion
7

  
8

  
9
class Migration(migrations.Migration):
10

  
11
    dependencies = [
12
        ('twilio', '0001_initial'),
13
    ]
14

  
15
    operations = [
16
        migrations.CreateModel(
17
            name='TwilioSMS',
18
            fields=[
19
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
                ('text', models.CharField(blank=True, max_length=256)),
21
                ('sender', models.CharField(blank=True, max_length=128)),
22
                ('destination', models.CharField(blank=True, max_length=256)),
23
                ('stop', models.BooleanField(default=False)),
24
                ('status', models.CharField(choices=[('pending', 'pending'), ('pushed', 'pushed'), ('error', 'error')], default='pending', max_length=32, null=True)),
25
                ('status_details', models.CharField(blank=True, max_length=256)),
26
                ('gateway', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sms_set', to='twilio.TwilioSMSGateway')),
27
            ],
28
            options={
29
                'verbose_name': 'Twilio SMS',
30
                'db_table': 'sms_twilio_sms',
31
            },
32
        ),
33
    ]
passerelle/apps/twilio/models.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16
import requests
17 17
from requests.auth import HTTPBasicAuth
18 18

  
19 19
from django.db import models
20 20
from django.utils.translation import ugettext_lazy as _
21 21

  
22 22
from passerelle.utils.jsonresponse import APIError
23
from passerelle.base.models import SMSResource
23
from passerelle.base.models import SMSResource, SMS
24 24

  
25 25

  
26 26
class TwilioSMSGateway(SMSResource):
27 27
    account_sid = models.CharField(verbose_name=_('Account Sid'), max_length=64)
28 28
    auth_token = models.CharField(verbose_name=_('Auth Token'), max_length=64)
29 29

  
30 30
    manager_view_template_name = 'passerelle/manage/messages_service_view.html'
31 31

  
32 32
    class Meta:
33
        verbose_name = 'Twilio'
33
        verbose_name = _('Twilio')
34 34
        db_table = 'sms_twilio'
35 35

  
36 36
    TEST_DEFAULTS = {
37 37
        'create_kwargs': {
38 38
            'account_sid': 'ACxxx',
39 39
            'auth_token': 'yyy',
40 40
        },
41 41
        'test_vectors': [
......
83 83
                    results.append('Twilio error: %s' % resp.text)
84 84
                else:
85 85
                    results.append(0)
86 86
        if any(results):
87 87
            raise APIError(
88 88
                'Twilio error: some destinations failed',
89 89
                data=list(zip(destinations, results)))
90 90
        return None
91

  
92

  
93
class TwilioSMS(SMS):
94
    gateway = models.ForeignKey(TwilioSMSGateway, related_name='sms_set')
95

  
96
    class Meta:
97
        verbose_name = _('Twilio SMS')
98
        db_table = 'sms_twilio_sms'
passerelle/base/models.py
965 965
        result = {'data': self.send_msg(data['message'], data['from'], data['to'], stop=stop)}
966 966
        SMSLog.objects.create(appname=self.get_connector_slug(), slug=self.slug)
967 967
        return result
968 968

  
969 969
    class Meta:
970 970
        abstract = True
971 971

  
972 972

  
973
class SMS(models.Model):
974
    STATUS_PENDING = 'pending'
975
    STATUS_PUSHED = 'pushed'
976
    STATUS_ERROR = 'error'
977

  
978
    STATUSES = [
979
        (STATUS_PENDING, _('pending')),
980
        (STATUS_PUSHED, _('pushed')),
981
        (STATUS_ERROR, _('error')),
982
    ]
983

  
984
    text = models.CharField(max_length=256, blank=True)
985
    sender = models.CharField(max_length=128, blank=True)
986
    destination = models.CharField(max_length=256, blank=True)
987
    stop = models.BooleanField(default=False)
988
    status = models.CharField(max_length=32, null=True, choices=STATUSES, default=STATUS_PENDING)
989
    status_details = models.CharField(max_length=256, blank=True)
990

  
991
    class Meta:
992
        abstract = True
993

  
994

  
973 995
@six.python_2_unicode_compatible
974 996
class SMSLog(models.Model):
975 997
    timestamp = models.DateTimeField(auto_now_add=True)
976 998
    appname = models.CharField(max_length=128, verbose_name='appname', null=True)
977 999
    slug = models.CharField(max_length=128, verbose_name='slug', null=True)
978 1000

  
979 1001
    def __str__(self):
980 1002
        return '%s %s %s' % (self.timestamp, self.appname, self.slug)
981
-