Add scrobble log option and CLI tool
This commit is contained in:
@ -62,9 +62,7 @@ combine_as_imports = true
|
||||
exclude_dirs = ["*/tests/*", "*/migrations/*"]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
server = 'scripts:server'
|
||||
migrate = 'scripts:migrate'
|
||||
shell = 'scripts:shell'
|
||||
vrobbler = "vrobbler.cli:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
||||
18
scrobbles/migrations/0004_scrobble_scrobble_log.py
Normal file
18
scrobbles/migrations/0004_scrobble_scrobble_log.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.1.5 on 2023-01-05 17:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('scrobbles', '0003_remove_scrobble_counted_scrobble_in_progress'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='scrobble',
|
||||
name='scrobble_log',
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@ -21,6 +21,7 @@ class Scrobble(TimeStampedModel):
|
||||
source = models.CharField(max_length=255, **BNULL)
|
||||
source_id = models.TextField(**BNULL)
|
||||
in_progress = models.BooleanField(default=True)
|
||||
scrobble_log = models.TextField(**BNULL)
|
||||
|
||||
@property
|
||||
def percent_played(self) -> int:
|
||||
|
||||
@ -34,7 +34,9 @@ class RecentScrobbleList(ListView):
|
||||
model = Scrobble
|
||||
|
||||
def get_queryset(self):
|
||||
return Scrobble.objects.filter(in_progress=False)
|
||||
return Scrobble.objects.filter(in_progress=False).order_by(
|
||||
'-timestamp'
|
||||
)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@ -93,8 +95,16 @@ def jellyfin_websocket(request):
|
||||
.order_by('-modified')
|
||||
.first()
|
||||
)
|
||||
existing_in_progress_scrobble = (
|
||||
Scrobble.objects.filter(
|
||||
video=video, user_id=request.user.id, in_progress=True
|
||||
)
|
||||
.order_by('-modified')
|
||||
.first()
|
||||
)
|
||||
|
||||
minutes_from_now = timezone.now() + timedelta(minutes=15)
|
||||
a_day_from_now = timezone.now() + timedelta(days=1)
|
||||
|
||||
if (
|
||||
existing_finished_scrobble
|
||||
@ -105,14 +115,28 @@ def jellyfin_websocket(request):
|
||||
)
|
||||
return Response(video_dict, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
scrobble, scrobble_created = Scrobble.objects.get_or_create(
|
||||
**scrobble_dict
|
||||
)
|
||||
# Check if found in progress scrobble is more than a day old
|
||||
if not (
|
||||
existing_in_progress_scrobble
|
||||
and existing_in_progress_scrobble.modified < a_day_from_now
|
||||
):
|
||||
logger.info(
|
||||
'Found a scrobble for this video more than a day old, creating a new scrobble'
|
||||
)
|
||||
scrobble = existing_in_progress_scrobble
|
||||
scrobble_created = False
|
||||
else:
|
||||
if getattr(settings, "DELETE_STALE_SCROBBLES", True):
|
||||
existing_in_progress_scrobble.delete()
|
||||
scrobble, scrobble_created = Scrobble.objects.get_or_create(
|
||||
**scrobble_dict
|
||||
)
|
||||
|
||||
if scrobble_created:
|
||||
# If we newly created this, capture the client we're watching from
|
||||
scrobble.source = data_dict['ClientName']
|
||||
scrobble.source_id = data_dict['MediaSourceId']
|
||||
scrobble.scrobble_log = ""
|
||||
else:
|
||||
last_tick = scrobble.playback_position_ticks
|
||||
|
||||
@ -121,7 +145,14 @@ def jellyfin_websocket(request):
|
||||
scrobble.playback_position = data_dict["PlaybackPosition"]
|
||||
scrobble.timestamp = parse(data_dict["UtcTimestamp"])
|
||||
scrobble.is_paused = data_dict["IsPaused"] in TRUTHY_VALUES
|
||||
scrobble.save()
|
||||
scrobble.save(
|
||||
update_fields=[
|
||||
'playback_position_ticks',
|
||||
'playback_position',
|
||||
'timestamp',
|
||||
'is_paused',
|
||||
]
|
||||
)
|
||||
|
||||
# If we hit our completion threshold, save it and get ready
|
||||
# to scrobble again if we re-watch this.
|
||||
@ -133,6 +164,9 @@ def jellyfin_websocket(request):
|
||||
scrobble.save()
|
||||
|
||||
if scrobble.percent_played % 5 == 0:
|
||||
logger.info(f"You are {scrobble.percent_played}% through {video}")
|
||||
if getattr(settings, "KEEP_DETAILED_SCROBBLE_LOGS", False):
|
||||
scrobble.scrobble_log += f"\n{str(scrobble.timestamp)} - {scrobble.playback_position} - {str(scrobble.playback_position_ticks)} - {str(scrobble.percent_played)}%"
|
||||
scrobble.save(update_fields=['scrobble_log'])
|
||||
logger.debug(f"You are {scrobble.percent_played}% through {video}")
|
||||
|
||||
return Response(video_dict, status=status.HTTP_201_CREATED)
|
||||
|
||||
34
vrobbler/cli.py
Normal file
34
vrobbler/cli.py
Normal file
@ -0,0 +1,34 @@
|
||||
# cli.py
|
||||
import logging
|
||||
import sys
|
||||
from os import environ as env
|
||||
|
||||
|
||||
if not 'DJANGO_SETTINGS_MODULE' in env:
|
||||
from vrobbler import settings
|
||||
env.setdefault('DJANGO_SETTINGS_MODULE', settings.__name__)
|
||||
|
||||
|
||||
import django
|
||||
django.setup()
|
||||
|
||||
# this line must be after django.setup() for logging configure
|
||||
logger = logging.getLogger('vrobbler')
|
||||
|
||||
def main():
|
||||
# to get configured settings
|
||||
from django.conf import settings
|
||||
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -32,6 +32,12 @@ DEBUG = os.getenv("VROBBLER_DEBUG", False)
|
||||
|
||||
TESTING = len(sys.argv) > 1 and sys.argv[1] == "test"
|
||||
|
||||
KEEP_DETAILED_SCROBBLE_LOGS = os.getenv(
|
||||
"VROBBLER_KEEP_DETAILED_SCROBBLE_LOGS", False
|
||||
)
|
||||
|
||||
DELETE_STALE_SCROBBLES = os.getenv("VROBBLER_DELETE_STALE_SCROBBLES", True)
|
||||
|
||||
TMDB_API_KEY = os.getenv("VROBBLER_TMDB_API_KEY", "")
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
@ -61,7 +67,6 @@ INSTALLED_APPS = [
|
||||
"django_filters",
|
||||
"django_extensions",
|
||||
'rest_framework.authtoken',
|
||||
"vrobbler",
|
||||
"scrobbles",
|
||||
"videos",
|
||||
"rest_framework",
|
||||
|
||||
Reference in New Issue
Block a user