Completed
Push — master ( ee6984...d48528 )
by Fox
36s
created

ServicesMgr.send_digest_event()   A

Complexity

Conditions 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 18
rs 9.4285
1
# coding: utf-8
2
# Using OAuth1Session
3
from requests_oauthlib import OAuth1Session, OAuth2Session
4
5
# django stuff
6
from django.core.cache import caches
7
from django.core.urlresolvers import reverse
8
from django.conf import settings
9
10
try:
11
    from django.apps import apps
12
    get_model = apps.get_model
13
except ImportError:
14
    from django.db.models.loading import get_model
15
16
# django_th stuff
17
from django_th import signals
18
from django_th.models import UserService, ServicesActivated, TriggerService
19
from django_th.publishing_limit import PublishingLimit
20
from django_th.html_entities import HtmlEntities
21
22
23
class ServicesMgr(object):
24
    """
25
        Main Service Class
26
    """
27
    name = ''
28
    title = ''
29
    body = ''
30
    data = {}
31
32
    class __ServicesMgr:
33
34
        def __init__(self, arg):
35
            self.val = arg
36
37
        def __str__(self):
38
            return repr(self) + self.val
39
40
    instance = None
41
42
    def __init__(self, arg, **kwargs):
43
        base = 'https://www.urltotheserviceapi.com'
44
        self.AUTH_URL = '{}/api/rest/v1/oauth/authorize/'.format(base)
45
        self.REQ_TOKEN = '{}/api/rest/v1/oauth/request_token/'.format(base)
46
        self.ACC_TOKEN = '{}/api/rest/v1/oauth/access_token/'.format(base)
47
        self.oauth = 'oauth1'
48
        self.token = ''
49
        self.service = ''
50
        self.scope = ''
51
        if not ServicesMgr.instance:
52
            ServicesMgr.instance = ServicesMgr.__ServicesMgr(arg)
53
        else:
54
            ServicesMgr.instance.val = arg
55
56
    def __getattr__(self, name):
57
        return getattr(self.instance, name)
58
59
    def __str__(self):
60
        return self.name
61
62
    @staticmethod
63
    def _get_content(data, which_content):
64
        """
65
            get the content that could be hidden
66
            in the middle of "content" or "summary detail"
67
            from the data of the provider
68
        """
69
        content = ''
70
        if data.get(which_content):
71
            if type(data.get(which_content)) is list or\
72
               type(data.get(which_content)) is tuple or\
73
               type(data.get(which_content)) is dict:
74
                if 'value' in data.get(which_content)[0]:
75
                    content = data.get(which_content)[0].value
76
            else:
77
                if type(data.get(which_content)) is str:
78
                    content = data.get(which_content)
79
                else:
80
                    # if not str or list or tuple
81
                    # or dict it could be feedparser.FeedParserDict
82
                    # so get the item value
83
                    content = data.get(which_content)['value']
84
        return content
85
86
    @staticmethod
87
    def set_title(data):
88
        """
89
            handle the title from the data
90
            :param data: contains the data from the provider
91
            :type data: dict
92
            :rtype: string
93
        """
94
        title = (data.get('title') if data.get('title') else data.get('link'))
95
96
        return title
97
98
    def set_content(self, data):
99
        """
100
            handle the content from the data
101
            :param data: contains the data from the provider
102
            :type data: dict
103
            :rtype: string
104
        """
105
        content = self._get_content(data, 'content')
106
107
        if content == '':
108
            content = self._get_content(data, 'summary_detail')
109
110
        if content == '':
111
            if data.get('description'):
112
                content = data.get('description')
113
114
        return content
115
116
    def read_data(self, **kwargs):
117
        """
118
            get the data from the service
119
120
            :param kwargs: contain keyword args : trigger_id and model name
121
            :type kwargs: dict
122
            :rtype: model
123
        """
124
        model = get_model('django_th', kwargs['model_name'])
125
126
        return model.objects.get(trigger_id=kwargs['trigger_id'])
127
128
    def process_data(self, **kwargs):
129
        """
130
             get the data from the cache
131
            :param kwargs: contain keyword args : trigger_id at least
132
            :type kwargs: dict
133
        """
134
        cache = caches[kwargs.get('cache_stack')]
135
        cache_data = cache.get(kwargs.get('cache_stack') + '_' +
136
                               kwargs.get('trigger_id'))
137
        return PublishingLimit.get_data(kwargs.get('cache_stack'),
138
                                        cache_data, kwargs.get('trigger_id'))
139
140
    def save_data(self, trigger_id, **data):
141
        """
142
            used to save data to the service
143
            but first of all
144
            make some work about the data to find
145
            and the data to convert
146
            :param trigger_id: trigger ID from which to save data
147
            :param data: the data to check to be used and save
148
            :type trigger_id: int
149
            :type data:  dict
150
            :return: the status of the save statement
151
            :rtype: boolean
152
        """
153
        title = self.set_title(data)
154
        title = HtmlEntities(title).html_entity_decode
155
        content = self.set_content(data)
156
        content = HtmlEntities(content).html_entity_decode
157
        if data.get('output_format'):
158
            # pandoc to convert tools
159
            import pypandoc
160
            content = pypandoc.convert(content,
161
                                       data.get('output_format'),
162
                                       format='html')
163
        return title, content
164
165
    def auth(self, request):
166
        """
167
            get the auth of the services
168
            :param request: contains the current session
169
            :type request: dict
170
            :rtype: dict
171
        """
172
        request_token = self.get_request_token(request)
173
174
        return request_token
175
176
    def callback_url(self, request):
177
        """
178
            the url to go back after the external service call
179
            :param request: contains the current session
180
            :type request: dict
181
            :rtype: string
182
        """
183
        service = self.service.split('Service')[1].lower()
184
        return_to = '{service}_callback'.format(service=service)
185
        return '%s://%s%s' % (request.scheme, request.get_host(),
186
                              reverse(return_to))
187
188
    def callback(self, request, **kwargs):
189
        """
190
            Called from the Service when the user accept to activate it
191
            the url to go back after the external service call
192
            :param request: contains the current session
193
            :param kwargs: keyword args
194
            :type request: dict
195
            :type kwargs: dict
196
            :rtype: string
197
        """
198
        if self.oauth == 'oauth1':
199
            token = self.callback_oauth1(request, **kwargs)
200
        else:
201
            token = self.callback_oauth2(request)
202
203
        service_name = ServicesActivated.objects.get(name=self.service)
204
205
        UserService.objects.filter(user=request.user,
206
                                   name=service_name
207
                                   ).update(token=token)
208
        back = self.service.split('Service')[1].lower()
209
        back_to = '{back_to}/callback.html'.format(back_to=back)
210
        return back_to
211
212
    def callback_oauth1(self, request, **kwargs):
213
        """
214
            Process for oAuth 1
215
            :param request: contains the current session
216
            :param kwargs: keyword args
217
            :type request: dict
218
            :type kwargs: dict
219
            :rtype: string
220
        """
221
        if kwargs.get('access_token') == '' \
222
           or kwargs.get('access_token') is None:
223
            access_token = self.get_access_token(
224
                request.session['oauth_token'],
225
                request.session['oauth_token_secret'],
226
                request.GET.get('oauth_verifier', '')
227
            )
228
            print(request.session)
229
        else:
230
            access_token = kwargs.get('access_token')
231
232
        if type(access_token) == str:
233
            token = access_token
234
        else:
235
            token = '#TH#'.join((access_token.get('oauth_token'),
236
                                 access_token.get('oauth_token_secret')))
237
        return token
238
239
    def callback_oauth2(self, request):
240
        """
241
            Process for oAuth 2
242
            :param request: contains the current session
243
            :return:
244
        """
245
        callback_url = self.callback_url(request)
246
247
        oauth = OAuth2Session(client_id=self.consumer_key,
248
                              redirect_uri=callback_url,
249
                              scope=self.scope)
250
        request_token = oauth.fetch_token(self.REQ_TOKEN,
251
                                          code=request.GET.get('code', ''),
252
                                          authorization_response=callback_url,
253
                                          client_secret=self.consumer_secret,
254
                                          scope=self.scope,
255
                                          verify=False)
256
        return request_token.get('access_token')
257
258
    def get_request_token(self, request):
259
        """
260
           request the token to the external service
261
        """
262
        if self.oauth == 'oauth1':
263
            oauth = OAuth1Session(self.consumer_key,
264
                                  client_secret=self.consumer_secret)
265
            request_token = oauth.fetch_request_token(self.REQ_TOKEN)
266
            # Save the request token information for later
267
            request.session['oauth_token'] = request_token['oauth_token']
268
            request.session['oauth_token_secret'] = request_token[
269
                'oauth_token_secret']
270
            print(request.session)
271
            return request_token
272
        else:
273
            callback_url = self.callback_url(request)
274
            oauth = OAuth2Session(client_id=self.consumer_key,
275
                                  redirect_uri=callback_url,
276
                                  scope=self.scope)
277
            authorization_url, state = oauth.authorization_url(self.AUTH_URL)
278
            return authorization_url
279
280
    def get_access_token(self, oauth_token, oauth_token_secret,
281
                         oauth_verifier):
282
        """
283
           get the access token
284
            the url to go back after the external service call
285
            :param oauth_token: oauth token
286
            :param oauth_token_secret: oauth secret token
287
            :param oauth_verifier: oauth verifier
288
            :type oauth_token: string
289
            :type oauth_token_secret: string
290
            :type oauth_verifier: string
291
            :rtype: dict
292
        """
293
        # Using OAuth1Session
294
        oauth = OAuth1Session(self.consumer_key,
295
                              client_secret=self.consumer_secret,
296
                              resource_owner_key=oauth_token,
297
                              resource_owner_secret=oauth_token_secret,
298
                              verifier=oauth_verifier)
299
        oauth_tokens = oauth.fetch_access_token(self.ACC_TOKEN)
300
301
        return oauth_tokens
302
303
    def reset_failed(self, pk):
304
        """
305
            reset failed counter
306
        :param pk:
307
        :return:
308
        """
309
        TriggerService.objects.filter(consumer__name__id=pk).update(
310
            consumer_failed=0, provider_failed=0)
311
        TriggerService.objects.filter(provider__name__id=pk).update(
312
            consumer_failed=0, provider_failed=0)
313
314
    def send_digest_event(self, trigger_id, title, link=''):
315
        """
316
        handling of the signal of digest
317
        :param trigger_id:
318
        :param title:
319
        :param link:
320
        :return:
321
        """
322
        if settings.DJANGO_TH.get('digest_event'):
323
324
            t = TriggerService.objects.get(id=trigger_id)
325
326
            if t.provider.duration != 'n':
327
328
                kwargs = {'user': t.user, 'title': title,
329
                          'link': link, 'duration': t.provider.duration}
330
331
                signals.digest_event.send(sender=t.provider.name, **kwargs)
332