Passed
Push — develop ( 4455b2...d40843 )
by Dean
03:05
created

DismissMessages()   A

Complexity

Conditions 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 20
rs 9.4285
1
from core.helpers import pad_title, try_convert, redirect
0 ignored issues
show
Bug introduced by
The name helpers does not seem to exist in module core.
Loading history...
Configuration introduced by
The import core.helpers could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
2
3
from plugin.core.constants import PLUGIN_PREFIX
0 ignored issues
show
Configuration introduced by
The import plugin.core.constants could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
4
from plugin.core.environment import translate as _
0 ignored issues
show
Configuration introduced by
The import plugin.core.environment could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
5
from plugin.managers.exception import ExceptionManager, MessageManager, VERSION_BASE, VERSION_BRANCH
0 ignored issues
show
Configuration introduced by
The import plugin.managers.exception could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
Unused Code introduced by
Unused VERSION_BRANCH imported from plugin.managers.exception
Loading history...
6
from plugin.models import Exception, Message
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in Exception.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
Configuration introduced by
The import plugin.models could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7
8
from ago import human
0 ignored issues
show
Configuration introduced by
The import ago could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
9
from datetime import datetime, timedelta
10
import logging
11
12
log = logging.getLogger(__name__)
13
14
ERROR_TYPES = [
15
    Message.Type.Exception,
16
17
    Message.Type.Warning,
18
    Message.Type.Error,
19
    Message.Type.Critical
20
]
21
22
23
@route(PLUGIN_PREFIX + '/messages/list')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
24
def ListMessages(days=14, version='latest', viewed=False):
25
    # Cast `viewed` to boolean
26
    if type(viewed) is str:
27
        if viewed == 'None':
28
            viewed = None
29
        else:
30
            viewed = viewed == 'True'
31
32
    # Retrieve messages
33
    messages = list(List(
34
        days=try_convert(days, int),
35
        version=version,
36
        viewed=viewed
37
    ).order_by(
38
        Message.last_logged_at.desc()
39
    ).limit(50))
40
41
    total_messages = List(
42
        days=try_convert(days, int),
43
        version=version,
44
    ).count()
45
46
    # Construct container
47
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
48
        title2=_("Messages")
49
    )
50
51
    if viewed is False and len(messages) > 1:
52
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
53
            key=Callback(DismissMessages),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
54
            title=pad_title(_("Dismiss all"))
55
        ))
56
57
    for m in messages:
58
        if m.type is None or\
59
           m.summary is None:
60
            continue
61
62
        thumb = None
63
64
        if m.type == Message.Type.Exception:
65
            thumb = R("icon-exception-viewed.png") if m.viewed else R("icon-exception.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
66
        elif m.type == Message.Type.Info:
67
            thumb = R("icon-notification-viewed.png") if m.viewed else R("icon-notification.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
68
        elif m.type in ERROR_TYPES:
69
            thumb = R("icon-error-viewed.png") if m.viewed else R("icon-error.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
70
71
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
72
            key=Callback(ViewMessage, error_id=m.id),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
73
            title=pad_title('[%s] %s' % (Message.Type.title(m.type), m.summary)),
74
            thumb=thumb
75
        ))
76
77
    # Append "View All" button
78
    if len(messages) != 50 and len(messages) < total_messages:
79
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
80
            key=Callback(ListMessages, days=None, viewed=None),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
81
            title=pad_title(_("View All"))
82
        ))
83
84
    return oc
85
86
@route(PLUGIN_PREFIX + '/messages/view')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
87
def ViewMessage(error_id):
88
    # Retrieve message from database
89
    message = MessageManager.get.by_id(error_id)
90
91
    # Update `last_viewed_at` field
92
    message.last_viewed_at = datetime.utcnow()
93
    message.save()
94
95
    # Parse request headers
96
    web_client = Request.Headers.get('X-Plex-Product', '').lower() == 'plex web'
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Request'
Loading history...
97
98
    # Build objects
99
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
100
        title2='[%s] %s' % (Message.Type.title(message.type), Trim(message.summary))
101
    )
102
103
    if message.type == Message.Type.Exception:
104
        # Display exception samples
105
        for e in message.exceptions.order_by(Exception.timestamp.desc()).limit(50):
106
            since = datetime.utcnow() - e.timestamp
107
108
            callback = Callback(ViewMessage, error_id=error_id)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
109
110
            if web_client:
111
                # Display exception traceback in Plex/Web
112
                callback = Callback(ViewException, exception_id=e.id)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
113
114
            oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
115
                key=callback,
116
                title=pad_title('[%s] %s: %s' % (human(since, precision=1), e.type, e.message)),
117
                thumb=R("icon-exception.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
118
            ))
119
    elif message.type in [Message.Type.Info, Message.Type.Warning, Message.Type.Error, Message.Type.Critical]:
120
        # Display message code
121
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
122
            key='',
123
            title=pad_title(_('Code: %s') % hex(message.code))
124
        ))
125
126
        # Display message description
127
        if message.description:
128
            oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
129
                key='',
130
                title=pad_title(_('Description: %s') % message.description)
131
            ))
132
133
    return oc
134
135
@route(PLUGIN_PREFIX + '/exceptions/view')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
136
def ViewException(exception_id):
137
    # Retrieve exception from database
138
    exception = ExceptionManager.get.by_id(exception_id)
139
140
    # Split traceback into lines
141
    traceback = exception.traceback
142
143
    if traceback:
144
        traceback = traceback.split('\n')
145
146
    # Build exception view
147
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
148
        title2='%s: %s' % (exception.type, Trim(exception.message))
149
    )
150
151
    if not traceback:
152
        return oc
153
154
    for line in traceback:
155
        if not line:
156
            continue
157
158
        length = len(line)
159
160
        line = line.lstrip()
161
        spaces = length - len(line)
162
163
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
164
            key=Callback(ViewException, exception_id=exception_id),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
165
            title=pad_title(('&nbsp;' * spaces) + line)
166
        ))
167
168
    return oc
169
170
171
@route(PLUGIN_PREFIX + '/messages/dismissAll')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
172
def DismissMessages(days=14, version='latest'):
173
    # Retrieve messages that match the specified criteria
174
    messages = List(
175
        days=days,
176
        version=version,
177
        viewed=False
178
    )
179
180
    # Mark all messages as viewed
181
    for message in messages:
182
        # Update `last_viewed_at` field
183
        message.last_viewed_at = datetime.utcnow()
184
        message.save()
185
186
    # Redirect back to the messages view
187
    return redirect(
188
        '/messages/list',
189
        days=days,
190
        version=version
191
    )
192
193
194
def Status(viewed=None):
195
    """Get the number and type of messages logged in the last week"""
196
    messages = List(
197
        days=14,
198
        version='latest',
199
        viewed=viewed
200
    )
201
202
    count = 0
203
    type = 'notification'
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in type.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
204
205
    for message in messages:
206
        if message.type in ERROR_TYPES:
207
            type = 'error'
208
209
        count += 1
210
211
    return count, type
212
213
214
def List(days=None, version=None, viewed=None):
215
    """Get messages logged in the last week"""
216
    log.debug('List(%r, %r, %r)', days, version, viewed)
217
    where = []
218
219
    # Days
220
    if days is not None:
221
        where.append(
222
            Message.last_logged_at > datetime.utcnow() - timedelta(days=days)
223
        )
224
225
    # Version
226
    if version == 'latest':
227
        where.append(
228
            Message.version_base == VERSION_BASE
229
        )
230
    elif version is not None:
231
        log.warn('Unknown version specified: %r', version)
232
233
    # Viewed state
234
    if viewed is True:
235
        where.append(
236
            ~(Message.last_viewed_at >> None),
237
            Message.last_viewed_at > Message.last_logged_at
238
        )
239
    elif viewed is False:
240
        where.append(
241
            (Message.last_viewed_at >> None) | (Message.last_viewed_at < Message.last_logged_at)
242
        )
243
244
    # Build query
245
    if where:
246
        return MessageManager.get.where(*where)
247
248
    return MessageManager.get.all()
249
250
251
def Trim(value, length=45):
252
    if value and len(value) > length:
253
        return value[:length - 3] + "..."
254
255
    return value
256