219 lines
6.4 KiB
Python
219 lines
6.4 KiB
Python
from datetime import datetime
|
|
|
|
import pytz
|
|
from django.contrib.auth import get_user_model
|
|
from django.utils import timezone
|
|
from music.models import Artist, Track
|
|
from scrobbles.models import Scrobble
|
|
|
|
from vrobbler.apps.scrobbles.utils import (
|
|
analyze_scrobble_sentiment,
|
|
deduplicate_scrobbles,
|
|
timestamp_user_tz_to_utc,
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
def test_timestamp_user_tz_to_utc():
|
|
timestamp = timestamp_user_tz_to_utc(1685561082, pytz.timezone("US/Eastern"))
|
|
assert timestamp == datetime(2023, 5, 31, 23, 24, 42, tzinfo=pytz.utc)
|
|
|
|
|
|
def _make_track():
|
|
artist = Artist.objects.create(name="Carly Rae Jepsen")
|
|
return Track.objects.create(
|
|
title="Emotion",
|
|
artist_fk=artist,
|
|
base_run_time_seconds=60,
|
|
)
|
|
|
|
|
|
def test_deduplicate_scrobbles_removes_exact_duplicates(db):
|
|
user = User.objects.create(email="dup@example.com")
|
|
track = _make_track()
|
|
timestamp = timezone.now().replace(microsecond=0)
|
|
stop_timestamp = timestamp + timezone.timedelta(seconds=60)
|
|
for _ in range(3):
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
|
|
count = deduplicate_scrobbles(commit=True)
|
|
|
|
assert count == 2
|
|
assert Scrobble.objects.filter(user=user, track=track).count() == 1
|
|
|
|
|
|
def test_deduplicate_scrobbles_keeps_different_media(db):
|
|
user = User.objects.create(email="media@example.com")
|
|
track = _make_track()
|
|
other_track = Track.objects.create(
|
|
title="Other",
|
|
artist_fk=Artist.objects.create(name="Someone Else"),
|
|
base_run_time_seconds=60,
|
|
)
|
|
timestamp = timezone.now().replace(microsecond=0)
|
|
stop_timestamp = timestamp + timezone.timedelta(seconds=60)
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=other_track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
|
|
count = deduplicate_scrobbles(commit=True)
|
|
|
|
assert count == 0
|
|
assert Scrobble.objects.count() == 2
|
|
|
|
|
|
def test_deduplicate_scrobbles_keeps_different_timestamps(db):
|
|
user = User.objects.create(email="time@example.com")
|
|
track = _make_track()
|
|
timestamp = timezone.now().replace(microsecond=0)
|
|
stop_timestamp = timestamp + timezone.timedelta(seconds=60)
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp + timezone.timedelta(hours=1),
|
|
stop_timestamp=stop_timestamp + timezone.timedelta(hours=1),
|
|
)
|
|
|
|
count = deduplicate_scrobbles(commit=True)
|
|
|
|
assert count == 0
|
|
assert Scrobble.objects.count() == 2
|
|
|
|
|
|
def test_deduplicate_scrobbles_dry_run_does_not_delete(db):
|
|
user = User.objects.create(email="dry@example.com")
|
|
track = _make_track()
|
|
timestamp = timezone.now().replace(microsecond=0)
|
|
stop_timestamp = timestamp + timezone.timedelta(seconds=60)
|
|
for _ in range(2):
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
|
|
count = deduplicate_scrobbles(commit=False)
|
|
|
|
assert count == 1
|
|
assert Scrobble.objects.filter(user=user, track=track).count() == 2
|
|
|
|
|
|
def test_deduplicate_scrobbles_filters_by_media_type(db):
|
|
user = User.objects.create(email="filter@example.com")
|
|
track = _make_track()
|
|
timestamp = timezone.now().replace(microsecond=0)
|
|
stop_timestamp = timestamp + timezone.timedelta(seconds=60)
|
|
for _ in range(2):
|
|
Scrobble.objects.create(
|
|
user=user,
|
|
track=track,
|
|
media_type="Track",
|
|
timestamp=timestamp,
|
|
stop_timestamp=stop_timestamp,
|
|
)
|
|
|
|
count = deduplicate_scrobbles(commit=True, media_type="Video")
|
|
|
|
assert count == 0
|
|
assert Scrobble.objects.filter(user=user, track=track).count() == 2
|
|
|
|
|
|
def _make_boardgame_scrobble_with_notes(notes):
|
|
from boardgames.models import BoardGame
|
|
|
|
user = User.objects.create(email="notes@example.com")
|
|
board_game = BoardGame.objects.create(title="Test Board Game")
|
|
return Scrobble.objects.create(
|
|
user=user,
|
|
board_game=board_game,
|
|
media_type="BoardGame",
|
|
log={"notes": notes},
|
|
)
|
|
|
|
|
|
def test_analyze_scrobble_sentiment_positive(db):
|
|
scrobble = _make_boardgame_scrobble_with_notes(
|
|
{"1774476716": "This was amazing and delightful, I loved every minute."}
|
|
)
|
|
|
|
analyzed = analyze_scrobble_sentiment(scrobble)
|
|
|
|
assert analyzed is True
|
|
sentiment = scrobble.log["sentiment"]
|
|
assert sentiment["compound"] > 0
|
|
assert set(sentiment) == {"neg", "neu", "pos", "compound"}
|
|
|
|
|
|
def test_analyze_scrobble_sentiment_negative(db):
|
|
scrobble = _make_boardgame_scrobble_with_notes(
|
|
{"1774476716": "This was terrible, I hated every minute of it."}
|
|
)
|
|
|
|
analyzed = analyze_scrobble_sentiment(scrobble)
|
|
|
|
assert analyzed is True
|
|
assert scrobble.log["sentiment"]["compound"] < 0
|
|
|
|
|
|
def test_analyze_scrobble_sentiment_no_notes_skips(db):
|
|
scrobble = _make_boardgame_scrobble_with_notes({})
|
|
|
|
analyzed = analyze_scrobble_sentiment(scrobble)
|
|
|
|
assert analyzed is False
|
|
assert scrobble.log.get("sentiment") is None
|
|
|
|
|
|
def test_analyze_scrobble_sentiment_skips_when_already_done(db):
|
|
scrobble = _make_boardgame_scrobble_with_notes(
|
|
{"1774476716": "This was amazing and delightful."}
|
|
)
|
|
scrobble.log["sentiment"] = {"neg": 0, "neu": 1, "pos": 0, "compound": 0.0}
|
|
scrobble.save()
|
|
|
|
analyzed = analyze_scrobble_sentiment(scrobble)
|
|
|
|
assert analyzed is False
|
|
assert scrobble.log["sentiment"]["compound"] == 0.0
|
|
|
|
|
|
def test_analyze_scrobble_sentiment_overwrite(db):
|
|
scrobble = _make_boardgame_scrobble_with_notes(
|
|
{"1774476716": "This was amazing and delightful."}
|
|
)
|
|
scrobble.log["sentiment"] = {"neg": 0, "neu": 1, "pos": 0, "compound": 0.0}
|
|
scrobble.save()
|
|
|
|
analyzed = analyze_scrobble_sentiment(scrobble, overwrite=True)
|
|
|
|
assert analyzed is True
|
|
assert scrobble.log["sentiment"]["compound"] > 0
|