Project

General

Profile

Download (8.13 KB) Statistics
| Branch: | Tag: | Revision:

root / corbo / transports.py @ b51a06ed

1
import logging
2
import smtplib
3
import re
4
try:
5
    import simplejson as json
6
except:
7
    import json
8

    
9
import requests
10

    
11

    
12
from django.utils.importlib import import_module
13
from django.core.mail import EmailMessage
14
from django.template.loader import select_template
15
from django.template import Context
16
from django.utils.translation import ugettext_lazy as _
17

    
18

    
19
import app_settings
20
import models
21

    
22
logger = logging.getLogger()
23

    
24

    
25
def get_transport_choices(include=[], exclude=[]):
26
    for transport in get_transports():
27
        if include and transport.identifier not in include:
28
            continue
29
        if exclude and transport.identifier in exclude:
30
            continue
31
        for identifier, display_name in transport.get_choices():
32
            yield (identifier, display_name)
33

    
34

    
35
def get_transport(identifier):
36
    transports = get_transports()
37
    for transport in transports:
38
        if identifier == transport.identifier:
39
            return transport
40
    return None
41

    
42

    
43
__TRANSPORTS = None
44

    
45

    
46
def get_transports():
47
    global __TRANSPORTS
48

    
49
    if __TRANSPORTS is None:
50
        transports = []
51
        for class_path in app_settings.transport_modes:
52
            if not isinstance(class_path, basestring):
53
                class_path, kwargs = class_path
54
            else:
55
                kwargs = {}
56
            module_path, class_name = class_path.rsplit('.', 1)
57
            try:
58
                module = import_module(module_path)
59
                transports.append(getattr(module, class_name)(**kwargs))
60
            except (ImportError, AttributeError), e:
61
                raise ImportError('Unable to load transport class %s' % class_path, e)
62
        __TRANSPORTS = transports
63
    return __TRANSPORTS
64

    
65

    
66
def get_template_list(template_list, **kwargs):
67
    '''Customize a template list given an announce category'''
68
    for template in template_list:
69
        yield template.format(**kwargs)
70

    
71

    
72
def get_template(template_list, **kwargs):
73
    template_list = get_template_list(template_list, **kwargs)
74
    return select_template(template_list)
75

    
76

    
77
class HomepageTransport(object):
78
    identifier = 'homepage'
79

    
80
    def get_choices(self):
81
        return (('homepage', _('Homepage')),)
82

    
83
    def get_identifier_from_subscription(self, subscription):
84
        return u'homepage'
85

    
86

    
87
class SMSTransport(object):
88
    body_template_list = [
89
        'portail_citoyen_announces/{identifier}/body_{category}.txt',
90
        'portail_citoyen_announces/{identifier}/body.txt',
91
        'portail_citoyen_announces/body_{category}.txt',
92
        'portail_citoyen_announces/body.txt',
93
    ]
94
    mobile_re = re.compile('^0[67][0-9]{8}$')
95

    
96
    def __init__(self, url, from_mobile, login=None, password=None, identifier='sms', name=_('SMS')):
97
        self.url = url
98
        self.from_mobile = from_mobile
99
        self.login = login
100
        self.password = password
101
        self.identifier = identifier
102
        self.name = name
103

    
104
    def get_choices(self):
105
        return ((self.identifier, self.name),)
106

    
107
    def get_subscriptions(self, category):
108
        return models.Subscription.objects.filter(category=category,
109
                transport=self.identifier)
110

    
111
    def get_sms(self, category):
112
        qs = self.get_subscriptions(category)
113
        for subscription in qs:
114
            sms = ''
115
            if subscription.identifier:
116
                sms = subscription.identifier
117
            elif subscription.user:
118
                sms = subscription.user.mobile
119
            if self.mobile_re.match(sms):
120
                yield sms
121

    
122
    def send(self, announce):
123
        category = announce.category
124
        site = category.site
125
        body_template = get_template(self.body_template_list,
126
                category=category.identifier, identifier=self.identifier)
127
        ctx = Context({ 'announce': announce, 'site': site, 'category': category })
128
        body = body_template.render(ctx)
129
        sms = list(self.get_sms(category))
130
        logger.info(u'sending announce %(announce)s through %(mode)s to %(count)s emails',
131
                dict(announce=announce, mode=self.identifier, count=len(sms)))
132
        try:
133
            payload = {
134
                    'message': body,
135
                    'from': self.from_mobile,
136
                    'to': list(sms),
137
            }
138
            response = requests.post(self.url, data=json.dumps(payload))
139
            json_response = response.json()
140
            if json_response['err'] != 0:
141
                msg = u'unable to send announce "%s" on site "%s": %s' % (announce,
142
                    site, json_response)
143
                logger.error(msg)
144
            else:
145
                logger.info('announce %(announce)s sent succesfully',
146
                        dict(announce=announce))
147
                msg = u'ok'
148
        except smtplib.SMTPException, e:
149
            msg = u'unable to send announce "%s" on site "%s": %s' % (announce,
150
                site, e)
151
            logger.error(msg)
152
        except Exception, e:
153
            msg = u'unable to send announce "%s" on site "%s": %s' % (announce,
154
                site, e)
155
            logger.exception(msg)
156
        models.Sent.objects.create(
157
            announce=announce,
158
            transport=self.identifier,
159
            result=msg)
160

    
161
    def get_identifier_from_subscription(self, subscription):
162
        if subscription.user:
163
            return subscription.user.mobile
164
        return subscription.identifier
165

    
166
class EmailTransport(object):
167
    identifier = 'email'
168

    
169
    subject_template_list = [
170
        'portail_citoyen_announces/email/subject_{category}.txt',
171
        'portail_citoyen_announces/email/subject.txt',
172
        'portail_citoyen_announces/subject_{category}.txt',
173
        'portail_citoyen_announces/subject.txt',
174
    ]
175

    
176
    body_template_list = [
177
        'portail_citoyen_announces/email/body_{category}.txt',
178
        'portail_citoyen_announces/email/body.txt',
179
        'portail_citoyen_announces/body_{category}.txt',
180
        'portail_citoyen_announces/body.txt',
181
    ]
182

    
183
    def get_choices(self):
184
        return (('email', _('Email')),)
185

    
186
    def get_subscriptions(self, category):
187
        return models.Subscription.objects.filter(category=category,
188
                transport=self.identifier)
189

    
190
    def get_emails(self, category):
191
        qs = self.get_subscriptions(category)
192
        for subscription in qs:
193
            email = ''
194
            if subscription.identifier:
195
                email = subscription.identifier
196
            elif subscription.user:
197
                email = subscription.user.email
198
            yield email
199

    
200
    def send(self, announce):
201
        category = announce.category
202
        site = category.site
203
        subject_template = get_template(self.subject_template_list,
204
                category=category.identifier, identifier=self.identifier)
205
        body_template = get_template(self.body_template_list,
206
                category=category.identifier, identifier=self.identifier)
207
        ctx = Context({ 'announce': announce, 'site': site, 'category': category })
208
        subject = subject_template.render(ctx).replace('\r', '').replace('\n', '')
209
        body = body_template.render(ctx)
210
        emails = list(self.get_emails(category))
211
        logger.info(u'sending announce %(announce)s through %(mode)s to %(count)s emails',
212
                dict(announce=announce, mode=self.identifier, count=len(emails)))
213
        try:
214
            message = EmailMessage(subject=subject, 
215
                    body=body, 
216
                    from_email=app_settings.default_from,
217
                    bcc=emails)
218
            message.send()
219
        except smtplib.SMTPException, e:
220
            msg = u'unable to send announce "%s" on site "%s": %s' % (announce,
221
                site, e)
222
            logger.error(msg)
223
        except Exception, e:
224
            msg = u'unable to send announce "%s" on site "%s": %s' % (announce,
225
                site, e)
226
            logger.exception(msg)
227
        else:
228
            logger.info('announce %(announce)s sent succesfully',
229
                    dict(announce=announce))
230
            msg = u'ok'
231
        models.Sent.objects.create(
232
            announce=announce,
233
            transport=self.identifier,
234
            result=msg)
235

    
236
    def get_identifier_from_subscription(self, subscription):
237
        if subscription.user:
238
            return subscription.user.email
239
        return subscription.identifier
(7-7/11)