diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..25975d3 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,10 @@ +before_script: + - apt-get -qq update + - apt-get -qq install -y python3 python3-venv python3-pip + - python3 -m venv venv + - source venv/bin/activate + - pip install -r requirements.txt pylint + +pylint: + script: + - pylint marietje/marietje marietje/metrics marietje/playerapi marietje/queues marietje/songs marietje/stats diff --git a/marietje/api/views.py b/marietje/api/views.py index 7a21351..5dc453e 100644 --- a/marietje/api/views.py +++ b/marietje/api/views.py @@ -111,7 +111,7 @@ def songs(request): except EmptyPage: songs = paginator.page(paginator.num_pages) - songs_dict = [song_to_dict(song, user=True) for song in songs.object_list] + songs_dict = [song_to_dict(song, include_user=True) for song in songs.object_list] return JsonResponse({ 'per_page': pagesize, 'current_page': page, diff --git a/marietje/marietje/forms.py b/marietje/marietje/forms.py index c04b1c1..41e741a 100644 --- a/marietje/marietje/forms.py +++ b/marietje/marietje/forms.py @@ -5,9 +5,6 @@ from django.utils.translation import ugettext_lazy as _ class AuthenticationForm(BaseAuthenticationForm): - def __init__(self, request=None, *args, **kwargs): - super(AuthenticationForm, self).__init__(request, *args, **kwargs) - def confirm_login_allowed(self, user): if user.activation_token: raise forms.ValidationError( diff --git a/marietje/marietje/models.py b/marietje/marietje/models.py index b89c502..6421c5d 100644 --- a/marietje/marietje/models.py +++ b/marietje/marietje/models.py @@ -1,14 +1,14 @@ -from django.db import models -from queues.models import Queue from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager from django.contrib.auth.hashers import make_password from django.contrib.auth.models import PermissionsMixin from django.contrib.auth.validators import ASCIIUsernameValidator, UnicodeUsernameValidator +from django.core.mail import send_mail +from django.db import models from django.utils import six, timezone from django.utils.translation import ugettext_lazy as _ -from django.core.mail import send_mail from marietje.utils import get_first_queue +from queues.models import Queue class UserManager(BaseUserManager): diff --git a/marietje/marietje/settings.py b/marietje/marietje/settings.py index 5d83da5..6a7e99f 100644 --- a/marietje/marietje/settings.py +++ b/marietje/marietje/settings.py @@ -62,7 +62,7 @@ DATABASES = { 'PASSWORD': 'v8TzZwdAdSi7Tk5I', 'HOST': 'localhost', 'PORT': '3306', - 'OPTIONS': { 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" }, + 'OPTIONS': {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"}, } } @@ -95,12 +95,17 @@ CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/MarietjeDjango_cache/default', - 'OPTIONS': { 'MAX_ENTRIES': 1000 }, + 'OPTIONS': {'MAX_ENTRIES': 1000}, }, 'song_search': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/MarietjeDjango_cache/song_search', - 'OPTIONS': { 'MAX_ENTRIES': 1000 }, + 'OPTIONS': {'MAX_ENTRIES': 1000}, + }, + 'userstats': { + 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', + 'LOCATION': '/var/tmp/MarietjeDjango_cache/default', + 'OPTIONS': {'MAX_ENTRIES': 1500}, }, 'userstats': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', @@ -144,8 +149,8 @@ CONTACT_EMAIL = 'marietje@science.ru.nl' STATS_TOP_COUNT = 50 STATS_REQUEST_IGNORE_USER_IDS = [] -ISSUES_URL = 'https://gitlab.science.ru.nl/Marietje/MarietjeDjango/issues' -MERGE_REQUESTS_URL = 'https://gitlab.science.ru.nl/Marietje/MarietjeDjango/merge_requests' +ISSUES_URL = 'https://gitlab.science.ru.nl/dsprenkels/MarietjeDjango/issues' +MERGE_REQUESTS_URL = 'https://gitlab.science.ru.nl/dsprenkels/MarietjeDjango/merge_requests' TRUSTED_IP_RANGES = [ '131.174.0.0/16', # RU wired '145.116.136.0/22', # eduroam diff --git a/marietje/marietje/static/css/custom.css b/marietje/marietje/static/css/custom.css index d727cd5..c9e8d79 100644 --- a/marietje/marietje/static/css/custom.css +++ b/marietje/marietje/static/css/custom.css @@ -23,10 +23,9 @@ footer { } .marietjequeue { - color: #777777;" + color: #777777; } -.marietjequeuestart { +.marietjequeue-start { border-top: 4px double #777777; - color: #777777;" } \ No newline at end of file diff --git a/marietje/marietje/static/js/queue.js b/marietje/marietje/static/js/queue.js index a0eaefa..7fc0758 100644 --- a/marietje/marietje/static/js/queue.js +++ b/marietje/marietje/static/js/queue.js @@ -52,6 +52,9 @@ $(function () { createAlert('danger', 'Please enter a message.'); return false } + if (message == null) { + return false + } $.post('/api/report', {id: songId, msg: message, csrfmiddlewaretoken: csrf_token}, function (result) { if (result.success) { createAlert('success', 'Thanks for your song report!'); @@ -198,14 +201,15 @@ function renderQueue(playNextAt, now) var requestedBy = song.requested_by; var reqMarietje = requestedBy != 'Marietje'; var startMarietje = false - - //checks if id is the last item and returns false if the next song is Marietje, while the current song is not. + + //checks if id is the last item and returns false if the next song is Marietje, while the current song is not. if(id === queue.length-1){ var requestNext = false } else { var requestNext = !((queue[id+1].requested_by === 'Marietje') && (requestedBy !== 'Marietje')) } - //checks if id is the first item and returns false if the previous song is not Marietje, while the current song is. + + //checks if id is the first item and returns false if the previous song is not Marietje, while the current song is. if(id === 0){ var requestPrev = false } else { @@ -226,7 +230,7 @@ function renderQueue(playNextAt, now) var artist = song.song.artist.trim() === '' ? '?' : song.song.artist; var title = song.song.title.trim() === '' ? '?' : song.song.title; var marietjeclass = reqMarietje ? '' : ' class="marietjequeue"'; - var marietjestartclass = startMarietje ? ' class="marietjequeuestart"' : ''; + var marietjestartclass = startMarietje ? ' class="marietjequeue marietjequeue-start"' : ''; showTime = showTimeToPlay ? (timeToPlay < 0 ? '' : timeToPlay.secondsToMMSS()) : (playNextAt < now ? '' : playNextAt.timestampToHHMMSS()) diff --git a/marietje/marietje/utils.py b/marietje/marietje/utils.py index 8c6f03b..ae32c35 100644 --- a/marietje/marietje/utils.py +++ b/marietje/marietje/utils.py @@ -1,10 +1,13 @@ -import socket, struct, binascii +import binascii +import socket +import struct + from django.conf import settings -from queues.models import Queue, Playlist from django.http import StreamingHttpResponse +from queues.models import Queue, Playlist -def song_to_dict(song, hash=False, user=False, replaygain=False): +def song_to_dict(song, include_hash=False, include_user=False, include_replaygain=False, **options): data = { 'id': song.id, 'artist': song.artist, @@ -12,13 +15,13 @@ def song_to_dict(song, hash=False, user=False, replaygain=False): 'duration': song.duration, } - if hash: + if include_hash: data['hash'] = song.hash - if user is not None and song.user is not None and song.user.name: + if include_user is not None and song.user is not None and song.user.name: data['uploader_name'] = song.user.name - if replaygain: + if include_replaygain: data['rg_gain'] = song.rg_gain data['rg_peak'] = song.rg_peak @@ -44,9 +47,9 @@ def send_to_bertha(file): for chunk in file.chunks(): sock.sendall(chunk) sock.shutdown(socket.SHUT_WR) - hash = binascii.hexlify(sock.recv(64)) + song_hash = binascii.hexlify(sock.recv(64)) sock.close() - return hash + return song_hash def get_first_queue(): @@ -61,10 +64,10 @@ def get_first_queue(): return queue -def bertha_stream(hash): +def bertha_stream(song_hash): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(settings.BERTHA_HOST) - sock.sendall(struct.pack("?$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma, + dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata, + blah, + bla + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +#class-attribute-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=50 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + x, y, z, + _ + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +#variable-rgx= + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled). +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled). +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement. +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=cls + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception". +overgeneral-exceptions=Exception