[search] Add scrobble searching
This commit is contained in:
@ -968,6 +968,123 @@ class EmbeddableTopArtistsWidget(TemplateView):
|
||||
return context
|
||||
|
||||
|
||||
class ScrobbleSearchView(LoginRequiredMixin, TemplateView):
|
||||
template_name = "scrobbles/scrobble_search.html"
|
||||
|
||||
MEDIA_FIELDS = {
|
||||
"Video": ("video__title", "video__overview"),
|
||||
"Track": ("track__title", None),
|
||||
"PodcastEpisode": ("podcast_episode__title", None),
|
||||
"Book": ("book__title", "book__description"),
|
||||
"Paper": ("paper__title", None),
|
||||
"VideoGame": ("video_game__title", "video_game__description"),
|
||||
"BoardGame": ("board_game__title", "board_game__description"),
|
||||
"Beer": ("beer__name", "beer__style"),
|
||||
"Food": ("food__name", "food__description"),
|
||||
"Puzzle": ("puzzle__name", "puzzle__description"),
|
||||
"Trail": ("trail__name", "trail__location"),
|
||||
"GeoLocation": ("geo_location__name", "geo_location__description"),
|
||||
"Task": ("task__title", "task__description"),
|
||||
"WebPage": ("web_page__title", None),
|
||||
"LifeEvent": ("life_event__title", "life_event__description"),
|
||||
"Mood": ("mood__title", "mood__description"),
|
||||
"BrickSet": ("brick_set__title", None),
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not request.GET.get("q") and not request.GET.get("media_type"):
|
||||
return super().get(request, *args, **kwargs)
|
||||
return self.search(request)
|
||||
|
||||
def search(self, request):
|
||||
query = request.GET.get("q", "").strip()
|
||||
media_type = request.GET.get("media_type", "")
|
||||
user = request.user
|
||||
|
||||
scrobbles = Scrobble.objects.filter(user=user)
|
||||
|
||||
if media_type:
|
||||
scrobbles = scrobbles.filter(media_type=media_type)
|
||||
|
||||
if query:
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from taggit.models import TaggedItem
|
||||
|
||||
scrobble_ct = ContentType.objects.get_for_model(Scrobble)
|
||||
|
||||
tag_match_ids = list(
|
||||
TaggedItem.objects.filter(
|
||||
content_type=scrobble_ct,
|
||||
tag__name__icontains=query,
|
||||
).values_list("object_id", flat=True)
|
||||
)
|
||||
|
||||
q = Q()
|
||||
q |= Q(log__notes__icontains=query)
|
||||
q |= Q(log__title__icontains=query)
|
||||
q |= Q(log__description__icontains=query)
|
||||
q |= Q(source__icontains=query)
|
||||
|
||||
if media_type and media_type in self.MEDIA_FIELDS:
|
||||
title_field, desc_field = self.MEDIA_FIELDS[media_type]
|
||||
if title_field:
|
||||
q |= Q(**{f"{title_field}__icontains": query})
|
||||
if desc_field:
|
||||
q |= Q(**{f"{desc_field}__icontains": query})
|
||||
|
||||
scrobbles = scrobbles.filter(q).distinct()
|
||||
else:
|
||||
all_matching_ids = set()
|
||||
|
||||
base_matches = scrobbles.filter(q).values_list("id", flat=True)
|
||||
all_matching_ids.update(base_matches)
|
||||
|
||||
for mt, (title_field, desc_field) in self.MEDIA_FIELDS.items():
|
||||
mt_queries = []
|
||||
if title_field:
|
||||
mt_queries.append(Q(**{f"{title_field}__icontains": query}))
|
||||
if desc_field:
|
||||
mt_queries.append(Q(**{f"{desc_field}__icontains": query}))
|
||||
|
||||
if mt_queries:
|
||||
mt_q = mt_queries[0]
|
||||
for mq in mt_queries[1:]:
|
||||
mt_q |= mq
|
||||
try:
|
||||
mt_matches = scrobbles.filter(mt_q).values_list(
|
||||
"id", flat=True
|
||||
)
|
||||
all_matching_ids.update(mt_matches)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
all_matching_ids.update(tag_match_ids)
|
||||
|
||||
scrobbles = Scrobble.objects.filter(id__in=all_matching_ids, user=user)
|
||||
|
||||
scrobbles = scrobbles.order_by("-timestamp")[:100]
|
||||
|
||||
context = self.get_context_data(
|
||||
scrobbles=scrobbles,
|
||||
query=query,
|
||||
media_type=media_type,
|
||||
media_types=Scrobble.MediaType.choices,
|
||||
)
|
||||
return self.render_to_response(context)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if "scrobbles" not in ctx:
|
||||
ctx["scrobbles"] = []
|
||||
if "query" not in ctx:
|
||||
ctx["query"] = ""
|
||||
if "media_type" not in ctx:
|
||||
ctx["media_type"] = ""
|
||||
if "media_types" not in ctx:
|
||||
ctx["media_types"] = Scrobble.MediaType.choices
|
||||
return ctx
|
||||
|
||||
|
||||
class EmbeddableTopBoardGamesWidget(BaseEmbeddableWidget):
|
||||
media_type = "Board Games"
|
||||
count_label = "plays"
|
||||
|
||||
Reference in New Issue
Block a user