diff --git a/files/context_processors.py b/files/context_processors.py index 0fd883f..d11aa1d 100644 --- a/files/context_processors.py +++ b/files/context_processors.py @@ -37,4 +37,5 @@ def stuff(request): ret[ "VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE" ] = settings.VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE + ret["RSS_URL"] = "/rss" return ret diff --git a/files/feeds.py b/files/feeds.py index 46aedb5..6c3c7eb 100644 --- a/files/feeds.py +++ b/files/feeds.py @@ -1,20 +1,72 @@ from django.contrib.syndication.views import Feed +from django.utils.feedgenerator import Rss201rev2Feed from django.urls import reverse from django.db.models import Q +from django.conf import settings +from django.contrib.postgres.search import SearchQuery -from .models import Media +from .models import Media, Category +from . import helpers +from .stop_words import STOP_WORDS -class RssMediaFeed(Feed): +class MediaRSSFeed(Rss201rev2Feed): + def rss_attributes(self): + attrs = super(MediaRSSFeed, self).rss_attributes() + attrs["xmlns:media"] = "http://search.yahoo.com/mrss/" + attrs["xmlns:atom"] = "http://www.w3.org/2005/Atom" + return attrs + + def add_item_elements(self, handler, item): + """Callback to add elements to each item (item/entry) element.""" + super(MediaRSSFeed, self).add_item_elements(handler, item) + + if "media:title" in item: + handler.addQuickElement("media:title", item["title"]) + if "media:description" in item: + handler.addQuickElement("media:description", item["description"]) + + if "content_url" in item: + content = dict(url=item["content_url"]) + if "content_width" in item: + content["width"] = str(item["content_width"]) + if "content_height" in item: + content["height"] = str(item["content_height"]) + handler.addQuickElement("media:content", "", content) + + if "thumbnail_url" in item: + thumbnail = dict(url=item["thumbnail_url"]) + if "thumbnail_width" in item: + thumbnail["width"] = str(item["thumbnail_width"]) + if "thumbnail_height" in item: + thumbnail["height"] = str(item["thumbnail_height"]) + handler.addQuickElement("media:thumbnail", "", thumbnail) + + if "keywords" in item: + handler.addQuickElement("media:keywords", item["keywords"]) + + def add_root_elements(self, handler): + super().add_root_elements(handler) + if self.feed["author_name"] is not None: + handler.startElement("author", {}) + handler.addQuickElement("name", self.feed["author_name"]) + handler.endElement("author") + if self.feed.get("published") is not None: + handler.startElement("published", {}) + handler.addQuickElement("name", self.feed["published"]) + handler.endElement("published") + + +class IndexRSSFeed(Feed): + feed_type = MediaRSSFeed title = "Latest Media" - link = "/media" + link = "/rss" description = "Latest Media RSS feed" def items(self): - basic_query = Q(listable=True) - media = Media.objects.filter(basic_query).order_by("-add_date") + media = Media.objects.filter(listable=True).order_by("-add_date") media = media.prefetch_related("user") - return media[:40] + return media[:20] def item_title(self, item): return item.title @@ -22,5 +74,97 @@ class RssMediaFeed(Feed): def item_description(self, item): return item.description + def item_author_name(self, item): + return item.user.username + + def item_pubdate(self, item): + return item.add_date + + def item_updateddate(self, item): + return item.edit_date + def item_link(self, item): return reverse("get_media") + "?m={0}".format(item.friendly_token) + + def item_extra_kwargs(self, item): + item = { + "media:title": item.title, + "media:description": item.description, + "content_width": 720, + "thumbnail_url": f"{settings.SSL_FRONTEND_HOST}/{item.poster_url}", + "content_url": f"{settings.SSL_FRONTEND_HOST}/{item.get_absolute_url()}", + "thumbnail_width": 720, + } + return item + + +class SearchRSSFeed(Feed): + feed_type = MediaRSSFeed + description = "Latest Media RSS feed" + + def link(self, obj): + return f"/rss/search" + + def get_object(self, request): + category = request.GET.get("c", "") + tag = request.GET.get("t", "") + query = request.GET.get("q", "") + + media = Media.objects.filter(listable=True) + + if category: + media = media.filter(category__title=category) + elif tag: + media = media.filter(tags__title=tag) + elif query: + # same as on files.views.MediaSearch: move this processing to a prepare_query function + query = helpers.clean_query(query) + q_parts = [ + q_part.rstrip("y") + for q_part in query.split() + if q_part not in STOP_WORDS + ] + if q_parts: + query = SearchQuery(q_parts[0] + ":*", search_type="raw") + for part in q_parts[1:]: + query &= SearchQuery(part + ":*", search_type="raw") + else: + query = None + if query: + media = media.filter(search=query) + + media = media.order_by("-add_date").prefetch_related("user") + + return media + + def items(self, objects): + return objects[:20] + + def item_title(self, item): + return item.title + + def item_description(self, item): + return item.description + + def item_author_name(self, item): + return item.user.username + + def item_pubdate(self, item): + return item.add_date + + def item_updateddate(self, item): + return item.edit_date + + def item_link(self, item): + return reverse("get_media") + "?m={0}".format(item.friendly_token) + + def item_extra_kwargs(self, item): + item = { + "media:title": item.title, + "media:description": item.description, + "content_width": 720, + "thumbnail_url": f"{settings.SSL_FRONTEND_HOST}/{item.poster_url}", + "content_url": f"{settings.SSL_FRONTEND_HOST}/{item.get_absolute_url()}", + "thumbnail_width": 720, + } + return item diff --git a/files/management_views.py b/files/management_views.py index 4cc36dd..e2dae07 100644 --- a/files/management_views.py +++ b/files/management_views.py @@ -137,11 +137,10 @@ class CommentList(APIView): serializer = CommentSerializer(page, many=True, context={"request": request}) return paginator.get_paginated_response(serializer.data) - def delete(self, request, format=None): - comment_ids = request.GET.get('comment_ids') + comment_ids = request.GET.get("comment_ids") if comment_ids: - comments = comment_ids.split(',') + comments = comment_ids.split(",") Comment.objects.filter(uid__in=comments).delete() return Response(status=status.HTTP_204_NO_CONTENT) @@ -161,6 +160,7 @@ class UserList(APIView): params = self.request.query_params ordering = params.get("ordering", "").strip() sort_by = params.get("sort_by", "").strip() + role = params.get("role", "all").strip() sort_by_options = ["date_added", "name"] if sort_by not in sort_by_options: @@ -173,11 +173,16 @@ class UserList(APIView): pagination_class = api_settings.DEFAULT_PAGINATION_CLASS qs = User.objects.filter() - media = qs.order_by(f"{ordering}{sort_by}") + if role == "manager": + qs = qs.filter(is_manager=True) + elif role == "editor": + qs = qs.filter(is_editor=True) + + users = qs.order_by(f"{ordering}{sort_by}") paginator = pagination_class() - page = paginator.paginate_queryset(media, request) + page = paginator.paginate_queryset(users, request) serializer = UserSerializer(page, many=True, context={"request": request}) return paginator.get_paginated_response(serializer.data) diff --git a/files/urls.py b/files/urls.py index 561242c..4470c31 100644 --- a/files/urls.py +++ b/files/urls.py @@ -5,7 +5,7 @@ from django.urls import path from . import views from . import management_views -from .feeds import RssMediaFeed +from .feeds import IndexRSSFeed, SearchRSSFeed urlpatterns = [ url(r"^$", views.index), @@ -33,7 +33,8 @@ urlpatterns = [ ), url(r"^popular$", views.recommended_media), url(r"^recommended$", views.recommended_media), - path("rss/", RssMediaFeed()), + path("rss/", IndexRSSFeed()), + url("^rss/search", SearchRSSFeed()), url(r"^search", views.search, name="search"), url(r"^scpublisher", views.upload_media, name="upload_media"), url(r"^tags", views.tags, name="tags"), diff --git a/files/views.py b/files/views.py index 3905ddf..6f7e7df 100644 --- a/files/views.py +++ b/files/views.py @@ -296,6 +296,8 @@ def search(request): """Search view""" context = {} + RSS_URL = f"/rss{request.environ['REQUEST_URI']}" + context["RSS_URL"] = RSS_URL return render(request, "cms/search.html", context) @@ -730,8 +732,13 @@ class MediaSearch(APIView): media = Media.objects.filter(state="public", is_reviewed=True) if query: + # move this processing to a prepare_query function query = clean_query(query) - q_parts = [q_part for q_part in query.split() if q_part not in STOP_WORDS] + q_parts = [ + q_part.rstrip("y") + for q_part in query.split() + if q_part not in STOP_WORDS + ] if q_parts: query = SearchQuery(q_parts[0] + ":*", search_type="raw") for part in q_parts[1:]: diff --git a/templates/common/head-links.html b/templates/common/head-links.html index 2f23cb3..37e37fe 100644 --- a/templates/common/head-links.html +++ b/templates/common/head-links.html @@ -5,6 +5,7 @@ +