2021-01-07 14:33:02 +01:00
from datetime import datetime , timedelta
2021-05-26 17:35:21 +02:00
from celery . task . control import revoke
2020-12-15 22:33:43 +01:00
from django . conf import settings
from django . contrib import messages
2021-05-26 17:35:21 +02:00
from django . contrib . auth . decorators import login_required
2020-12-15 22:33:43 +01:00
from django . contrib . postgres . search import SearchQuery
2021-05-26 17:35:21 +02:00
from django . core . mail import EmailMessage
from django . db . models import Q
from django . http import HttpResponseRedirect
from django . shortcuts import get_object_or_404 , render
from django . template . defaultfilters import slugify
2021-05-29 15:34:36 +02:00
from drf_yasg import openapi as openapi
from drf_yasg . utils import swagger_auto_schema
2021-05-26 17:35:21 +02:00
from rest_framework import permissions , status
2020-12-15 22:33:43 +01:00
from rest_framework . exceptions import PermissionDenied
from rest_framework . parsers import (
FileUploadParser ,
FormParser ,
2021-05-26 17:35:21 +02:00
JSONParser ,
MultiPartParser ,
2020-12-15 22:33:43 +01:00
)
2021-05-26 17:35:21 +02:00
from rest_framework . response import Response
from rest_framework . settings import api_settings
from rest_framework . views import APIView
2020-12-15 22:33:43 +01:00
2021-05-26 17:35:21 +02:00
from actions . models import USER_MEDIA_ACTIONS , MediaAction
2020-12-15 22:33:43 +01:00
from cms . custom_pagination import FastPaginationWithoutCount
2021-05-26 17:35:21 +02:00
from cms . permissions import IsAuthorizedToAdd , IsUserOrEditor , user_allowed_to_upload
2020-12-15 22:33:43 +01:00
from users . models import User
2021-05-26 17:35:21 +02:00
from . forms import ContactForm , MediaForm , SubtitleForm
from . helpers import clean_query , produce_ffmpeg_commands
from . methods import (
2022-06-01 13:23:21 +02:00
check_comment_for_mention ,
2021-05-26 17:35:21 +02:00
get_user_or_session ,
is_mediacms_editor ,
is_mediacms_manager ,
list_tasks ,
notify_user_on_comment ,
show_recommended_media ,
show_related_media ,
update_user_ratings ,
)
2020-12-15 22:33:43 +01:00
from . models import (
2021-05-26 17:35:21 +02:00
Category ,
Comment ,
2020-12-15 22:33:43 +01:00
EncodeProfile ,
Encoding ,
2021-05-26 17:35:21 +02:00
Media ,
2020-12-15 22:33:43 +01:00
Playlist ,
PlaylistMedia ,
Tag ,
)
from . serializers import (
CategorySerializer ,
2021-05-26 17:35:21 +02:00
CommentSerializer ,
2020-12-15 22:33:43 +01:00
EncodeProfileSerializer ,
MediaSearchSerializer ,
2021-05-26 17:35:21 +02:00
MediaSerializer ,
2020-12-15 22:33:43 +01:00
PlaylistDetailSerializer ,
2021-05-26 17:35:21 +02:00
PlaylistSerializer ,
SingleMediaSerializer ,
TagSerializer ,
2020-12-15 22:33:43 +01:00
)
from . stop_words import STOP_WORDS
2021-05-26 17:35:21 +02:00
from . tasks import save_user_action
2020-12-15 22:33:43 +01:00
VALID_USER_ACTIONS = [ action for action , name in USER_MEDIA_ACTIONS ]
def about ( request ) :
""" About view """
context = { }
return render ( request , " cms/about.html " , context )
@login_required
def add_subtitle ( request ) :
""" Add subtitle view """
friendly_token = request . GET . get ( " m " , " " ) . strip ( )
if not friendly_token :
return HttpResponseRedirect ( " / " )
media = Media . objects . filter ( friendly_token = friendly_token ) . first ( )
if not media :
return HttpResponseRedirect ( " / " )
2021-05-26 17:35:21 +02:00
if not ( request . user == media . user or is_mediacms_editor ( request . user ) or is_mediacms_manager ( request . user ) ) :
2020-12-15 22:33:43 +01:00
return HttpResponseRedirect ( " / " )
if request . method == " POST " :
form = SubtitleForm ( media , request . POST , request . FILES )
if form . is_valid ( ) :
subtitle = form . save ( )
messages . add_message ( request , messages . INFO , " Subtitle was added! " )
return HttpResponseRedirect ( subtitle . media . get_absolute_url ( ) )
else :
form = SubtitleForm ( media_item = media )
return render ( request , " cms/add_subtitle.html " , { " form " : form } )
def categories ( request ) :
""" List categories view """
context = { }
return render ( request , " cms/categories.html " , context )
def contact ( request ) :
""" Contact view """
context = { }
if request . method == " GET " :
form = ContactForm ( request . user )
context [ " form " ] = form
else :
form = ContactForm ( request . user , request . POST )
if form . is_valid ( ) :
if request . user . is_authenticated :
from_email = request . user . email
name = request . user . name
else :
from_email = request . POST . get ( " from_email " )
name = request . POST . get ( " name " )
message = request . POST . get ( " message " )
title = " [ {} ] - Contact form message received " . format ( settings . PORTAL_NAME )
msg = """
You have received a message through the contact form \n
Sender name : % s
Sender email : % s \n
\n % s
""" % (
name ,
from_email ,
message ,
)
email = EmailMessage (
title ,
msg ,
settings . DEFAULT_FROM_EMAIL ,
settings . ADMIN_EMAIL_LIST ,
reply_to = [ from_email ] ,
)
email . send ( fail_silently = True )
success_msg = " Message was sent! Thanks for contacting "
context [ " success_msg " ] = success_msg
return render ( request , " cms/contact.html " , context )
def history ( request ) :
""" Show personal history view """
context = { }
return render ( request , " cms/history.html " , context )
@login_required
def edit_media ( request ) :
""" Edit a media view """
friendly_token = request . GET . get ( " m " , " " ) . strip ( )
if not friendly_token :
return HttpResponseRedirect ( " / " )
media = Media . objects . filter ( friendly_token = friendly_token ) . first ( )
if not media :
return HttpResponseRedirect ( " / " )
2021-05-26 17:35:21 +02:00
if not ( request . user == media . user or is_mediacms_editor ( request . user ) or is_mediacms_manager ( request . user ) ) :
2020-12-15 22:33:43 +01:00
return HttpResponseRedirect ( " / " )
if request . method == " POST " :
form = MediaForm ( request . user , request . POST , request . FILES , instance = media )
if form . is_valid ( ) :
media = form . save ( )
for tag in media . tags . all ( ) :
media . tags . remove ( tag )
if form . cleaned_data . get ( " new_tags " ) :
for tag in form . cleaned_data . get ( " new_tags " ) . split ( " , " ) :
tag = slugify ( tag )
if tag :
try :
tag = Tag . objects . get ( title = tag )
except Tag . DoesNotExist :
tag = Tag . objects . create ( title = tag , user = request . user )
if tag not in media . tags . all ( ) :
media . tags . add ( tag )
messages . add_message ( request , messages . INFO , " Media was edited! " )
return HttpResponseRedirect ( media . get_absolute_url ( ) )
else :
form = MediaForm ( request . user , instance = media )
return render (
request ,
" cms/edit_media.html " ,
{ " form " : form , " add_subtitle_url " : media . add_subtitle_url } ,
)
def embed_media ( request ) :
""" Embed media view """
friendly_token = request . GET . get ( " m " , " " ) . strip ( )
if not friendly_token :
return HttpResponseRedirect ( " / " )
media = Media . objects . values ( " title " ) . filter ( friendly_token = friendly_token ) . first ( )
if not media :
return HttpResponseRedirect ( " / " )
context = { }
context [ " media " ] = friendly_token
return render ( request , " cms/embed.html " , context )
def featured_media ( request ) :
""" List featured media view """
context = { }
return render ( request , " cms/featured-media.html " , context )
def index ( request ) :
""" Index view """
context = { }
return render ( request , " cms/index.html " , context )
def latest_media ( request ) :
""" List latest media view """
context = { }
return render ( request , " cms/latest-media.html " , context )
def liked_media ( request ) :
""" List user ' s liked media view """
context = { }
return render ( request , " cms/liked_media.html " , context )
@login_required
def manage_users ( request ) :
""" List users management view """
context = { }
return render ( request , " cms/manage_users.html " , context )
@login_required
def manage_media ( request ) :
""" List media management view """
context = { }
return render ( request , " cms/manage_media.html " , context )
@login_required
def manage_comments ( request ) :
""" List comments management view """
context = { }
return render ( request , " cms/manage_comments.html " , context )
def members ( request ) :
""" List members view """
context = { }
return render ( request , " cms/members.html " , context )
def recommended_media ( request ) :
""" List recommended media view """
context = { }
return render ( request , " cms/recommended-media.html " , context )
def search ( request ) :
""" Search view """
context = { }
2020-12-24 23:49:38 +01:00
RSS_URL = f " /rss { request . environ [ ' REQUEST_URI ' ] } "
context [ " RSS_URL " ] = RSS_URL
2020-12-15 22:33:43 +01:00
return render ( request , " cms/search.html " , context )
def tags ( request ) :
""" List tags view """
context = { }
return render ( request , " cms/tags.html " , context )
def tos ( request ) :
""" Terms of service view """
context = { }
return render ( request , " cms/tos.html " , context )
def upload_media ( request ) :
""" Upload media view """
from allauth . account . forms import LoginForm
form = LoginForm ( )
context = { }
context [ " form " ] = form
context [ " can_add " ] = user_allowed_to_upload ( request )
can_upload_exp = settings . CANNOT_ADD_MEDIA_MESSAGE
context [ " can_upload_exp " ] = can_upload_exp
return render ( request , " cms/add-media.html " , context )
def view_media ( request ) :
""" View media view """
friendly_token = request . GET . get ( " m " , " " ) . strip ( )
context = { }
media = Media . objects . filter ( friendly_token = friendly_token ) . first ( )
if not media :
context [ " media " ] = None
return render ( request , " cms/media.html " , context )
user_or_session = get_user_or_session ( request )
2021-05-26 17:35:21 +02:00
save_user_action . delay ( user_or_session , friendly_token = friendly_token , action = " watch " )
2020-12-15 22:33:43 +01:00
context = { }
context [ " media " ] = friendly_token
context [ " media_object " ] = media
context [ " CAN_DELETE_MEDIA " ] = False
context [ " CAN_EDIT_MEDIA " ] = False
context [ " CAN_DELETE_COMMENTS " ] = False
if request . user . is_authenticated :
2021-05-26 17:35:21 +02:00
if ( media . user . id == request . user . id ) or is_mediacms_editor ( request . user ) or is_mediacms_manager ( request . user ) :
2020-12-15 22:33:43 +01:00
context [ " CAN_DELETE_MEDIA " ] = True
context [ " CAN_EDIT_MEDIA " ] = True
context [ " CAN_DELETE_COMMENTS " ] = True
return render ( request , " cms/media.html " , context )
def view_playlist ( request , friendly_token ) :
""" View playlist view """
try :
playlist = Playlist . objects . get ( friendly_token = friendly_token )
except BaseException :
playlist = None
context = { }
context [ " playlist " ] = playlist
return render ( request , " cms/playlist.html " , context )
class MediaList ( APIView ) :
""" Media listings views """
permission_classes = ( IsAuthorizedToAdd , )
2021-05-31 21:24:05 +02:00
parser_classes = ( MultiPartParser , FormParser , FileUploadParser )
2020-12-15 22:33:43 +01:00
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = ' page ' , type = openapi . TYPE_INTEGER , in_ = openapi . IN_QUERY , description = ' Page number ' ) ,
openapi . Parameter ( name = ' author ' , type = openapi . TYPE_STRING , in_ = openapi . IN_QUERY , description = ' username ' ) ,
openapi . Parameter ( name = ' show ' , type = openapi . TYPE_STRING , in_ = openapi . IN_QUERY , description = ' show ' , enum = [ ' recommended ' , ' featured ' , ' latest ' ] ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' List Media ' ,
operation_description = ' Lists all media ' ,
responses = { 200 : MediaSerializer ( many = True ) } ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
# Show media
params = self . request . query_params
show_param = params . get ( " show " , " " )
author_param = params . get ( " author " , " " ) . strip ( )
if author_param :
user_queryset = User . objects . all ( )
user = get_object_or_404 ( user_queryset , username = author_param )
if show_param == " recommended " :
pagination_class = FastPaginationWithoutCount
media = show_recommended_media ( request , limit = 50 )
else :
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
if author_param :
# in case request.user is the user here, show
# all media independant of state
if self . request . user == user :
basic_query = Q ( user = user )
else :
basic_query = Q ( listable = True , user = user )
else :
# base listings should show safe content
basic_query = Q ( listable = True )
if show_param == " featured " :
media = Media . objects . filter ( basic_query , featured = True )
else :
media = Media . objects . filter ( basic_query ) . order_by ( " -add_date " )
paginator = pagination_class ( )
if show_param != " recommended " :
media = media . prefetch_related ( " user " )
page = paginator . paginate_queryset ( media , request )
serializer = MediaSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = " media_file " , in_ = openapi . IN_FORM , type = openapi . TYPE_FILE , required = True , description = " media_file " ) ,
openapi . Parameter ( name = " description " , in_ = openapi . IN_FORM , type = openapi . TYPE_STRING , required = False , description = " description " ) ,
openapi . Parameter ( name = " title " , in_ = openapi . IN_FORM , type = openapi . TYPE_STRING , required = False , description = " title " ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' Add new Media ' ,
operation_description = ' Adds a new media, for authenticated users ' ,
responses = { 201 : openapi . Response ( ' response description ' , MediaSerializer ) , 401 : ' bad request ' } ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def post ( self , request , format = None ) :
# Add new media
serializer = MediaSerializer ( data = request . data , context = { " request " : request } )
if serializer . is_valid ( ) :
media_file = request . data [ " media_file " ]
serializer . save ( user = request . user , media_file = media_file )
return Response ( serializer . data , status = status . HTTP_201_CREATED )
return Response ( serializer . errors , status = status . HTTP_400_BAD_REQUEST )
class MediaDetail ( APIView ) :
"""
Retrieve , update or delete a media instance .
"""
permission_classes = ( permissions . IsAuthenticatedOrReadOnly , IsUserOrEditor )
2021-05-31 21:24:05 +02:00
parser_classes = ( MultiPartParser , FormParser , FileUploadParser )
2020-12-15 22:33:43 +01:00
def get_object ( self , friendly_token , password = None ) :
try :
2021-05-26 17:35:21 +02:00
media = Media . objects . select_related ( " user " ) . prefetch_related ( " encodings__profile " ) . get ( friendly_token = friendly_token )
2020-12-15 22:33:43 +01:00
# this need be explicitly called, and will call
# has_object_permission() after has_permission has succeeded
self . check_object_permissions ( self . request , media )
2021-05-26 17:35:21 +02:00
if media . state == " private " and not ( self . request . user == media . user or is_mediacms_editor ( self . request . user ) ) :
if ( not password ) or ( not media . password ) or ( password != media . password ) :
2020-12-15 22:33:43 +01:00
return Response (
{ " detail " : " media is private " } ,
status = status . HTTP_401_UNAUTHORIZED ,
)
return media
except PermissionDenied :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " bad permissions " } , status = status . HTTP_401_UNAUTHORIZED )
2020-12-15 22:33:43 +01:00
except BaseException :
return Response (
{ " detail " : " media file does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = ' friendly_token ' , type = openapi . TYPE_STRING , in_ = openapi . IN_PATH , description = ' unique identifier ' , required = True ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' Get information for Media ' ,
operation_description = ' Get information for a media ' ,
responses = { 200 : SingleMediaSerializer ( ) , 400 : ' bad request ' } ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , friendly_token , format = None ) :
# Get media details
password = request . GET . get ( " password " )
media = self . get_object ( friendly_token , password = password )
if isinstance ( media , Response ) :
return media
serializer = SingleMediaSerializer ( media , context = { " request " : request } )
if media . state == " private " :
related_media = [ ]
else :
related_media = show_related_media ( media , request = request , limit = 100 )
2021-05-26 17:35:21 +02:00
related_media_serializer = MediaSerializer ( related_media , many = True , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
related_media = related_media_serializer . data
ret = serializer . data
# update rattings info with user specific ratings
# eg user has already rated for this media
# this only affects user rating and only if enabled
2021-05-26 17:35:21 +02:00
if settings . ALLOW_RATINGS and ret . get ( " ratings_info " ) and not request . user . is_anonymous :
ret [ " ratings_info " ] = update_user_ratings ( request . user , media , ret . get ( " ratings_info " ) )
2020-12-15 22:33:43 +01:00
ret [ " related_media " ] = related_media
return Response ( ret )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = ' friendly_token ' , type = openapi . TYPE_STRING , in_ = openapi . IN_PATH , description = ' unique identifier ' , required = True ) ,
openapi . Parameter ( name = ' type ' , type = openapi . TYPE_STRING , in_ = openapi . IN_FORM , description = ' action to perform ' , enum = [ ' encode ' , ' review ' ] ) ,
openapi . Parameter (
name = ' encoding_profiles ' ,
type = openapi . TYPE_ARRAY ,
items = openapi . Items ( type = openapi . TYPE_STRING ) ,
in_ = openapi . IN_FORM ,
description = ' if action to perform is encode, need to specify list of ids of encoding profiles ' ,
) ,
openapi . Parameter ( name = ' result ' , type = openapi . TYPE_BOOLEAN , in_ = openapi . IN_FORM , description = ' if action is review, this is the result (True for reviewed, False for not reviewed) ' ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' Run action on Media ' ,
operation_description = ' Actions for a media, for MediaCMS editors and managers ' ,
responses = { 201 : ' action created ' , 400 : ' bad request ' } ,
operation_id = ' media_manager_actions ' ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def post ( self , request , friendly_token , format = None ) :
""" superuser actions
Available only to MediaCMS editors and managers
Action is a POST variable , review and encode are implemented
"""
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
if not ( is_mediacms_editor ( request . user ) or is_mediacms_manager ( request . user ) ) :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " not allowed " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
action = request . data . get ( " type " )
profiles_list = request . data . get ( " encoding_profiles " )
result = request . data . get ( " result " , True )
if action == " encode " :
# Create encoding tasks for specific profiles
valid_profiles = [ ]
if profiles_list :
if isinstance ( profiles_list , list ) :
for p in profiles_list :
p = EncodeProfile . objects . filter ( id = p ) . first ( )
if p :
valid_profiles . append ( p )
elif isinstance ( profiles_list , str ) :
try :
p = EncodeProfile . objects . filter ( id = int ( profiles_list ) ) . first ( )
valid_profiles . append ( p )
except ValueError :
return Response (
2021-05-26 17:35:21 +02:00
{ " detail " : " encoding_profiles must be int or list of ints of valid encode profiles " } ,
2020-12-15 22:33:43 +01:00
status = status . HTTP_400_BAD_REQUEST ,
)
media . encode ( profiles = valid_profiles )
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " media will be encoded " } , status = status . HTTP_201_CREATED )
2020-12-15 22:33:43 +01:00
elif action == " review " :
if result :
media . is_reviewed = True
2021-05-26 17:35:21 +02:00
elif result is False :
2020-12-15 22:33:43 +01:00
media . is_reviewed = False
media . save ( update_fields = [ " is_reviewed " ] )
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " media reviewed set " } , status = status . HTTP_201_CREATED )
2020-12-15 22:33:43 +01:00
return Response (
{ " detail " : " not valid action or no action specified " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = " description " , in_ = openapi . IN_FORM , type = openapi . TYPE_STRING , required = False , description = " description " ) ,
openapi . Parameter ( name = " title " , in_ = openapi . IN_FORM , type = openapi . TYPE_STRING , required = False , description = " title " ) ,
openapi . Parameter ( name = " media_file " , in_ = openapi . IN_FORM , type = openapi . TYPE_FILE , required = False , description = " media_file " ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' Update Media ' ,
operation_description = ' Update a Media, for Media uploader ' ,
responses = { 201 : openapi . Response ( ' response description ' , MediaSerializer ) , 401 : ' bad request ' } ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def put ( self , request , friendly_token , format = None ) :
# Update a media object
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
2021-05-26 17:35:21 +02:00
serializer = MediaSerializer ( media , data = request . data , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
if serializer . is_valid ( ) :
2021-05-31 21:24:05 +02:00
if request . data . get ( ' media_file ' ) :
media_file = request . data [ " media_file " ]
serializer . save ( user = request . user , media_file = media_file )
else :
serializer . save ( user = request . user )
2020-12-15 22:33:43 +01:00
return Response ( serializer . data , status = status . HTTP_201_CREATED )
return Response ( serializer . errors , status = status . HTTP_400_BAD_REQUEST )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
2021-05-31 21:24:05 +02:00
manual_parameters = [
openapi . Parameter ( name = ' friendly_token ' , type = openapi . TYPE_STRING , in_ = openapi . IN_PATH , description = ' unique identifier ' , required = True ) ,
] ,
2021-05-29 15:34:36 +02:00
tags = [ ' Media ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' Delete Media ' ,
operation_description = ' Delete a Media, for MediaCMS editors and managers ' ,
responses = {
204 : ' no content ' ,
} ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def delete ( self , request , friendly_token , format = None ) :
# Delete a media object
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
media . delete ( )
return Response ( status = status . HTTP_204_NO_CONTENT )
class MediaActions ( APIView ) :
"""
Retrieve , update or delete a media action instance .
"""
permission_classes = ( permissions . AllowAny , )
parser_classes = ( JSONParser , )
def get_object ( self , friendly_token ) :
try :
2021-05-26 17:35:21 +02:00
media = Media . objects . select_related ( " user " ) . prefetch_related ( " encodings__profile " ) . get ( friendly_token = friendly_token )
2020-12-15 22:33:43 +01:00
if media . state == " private " and self . request . user != media . user :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " media is private " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
return media
except PermissionDenied :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " bad permissions " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
except BaseException :
return Response (
{ " detail " : " media file does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def get ( self , request , friendly_token , format = None ) :
# show date and reason for each time media was reported
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
ret = { }
reported = MediaAction . objects . filter ( media = media , action = " report " )
ret [ " reported " ] = [ ]
for rep in reported :
item = { " reported_date " : rep . action_date , " reason " : rep . extra_info }
ret [ " reported " ] . append ( item )
return Response ( ret , status = status . HTTP_200_OK )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def post ( self , request , friendly_token , format = None ) :
# perform like/dislike/report actions
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
action = request . data . get ( " type " )
extra = request . data . get ( " extra_info " )
if request . user . is_anonymous :
# there is a list of allowed actions for
# anonymous users, specified in settings
if action not in settings . ALLOW_ANONYMOUS_ACTIONS :
return Response (
{ " detail " : " action allowed on logged in users only " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
if action :
user_or_session = get_user_or_session ( request )
save_user_action . delay (
user_or_session ,
friendly_token = media . friendly_token ,
action = action ,
extra_info = extra ,
)
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " action received " } , status = status . HTTP_201_CREATED )
2020-12-15 22:33:43 +01:00
else :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " no action specified " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def delete ( self , request , friendly_token , format = None ) :
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
if not request . user . is_superuser :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " not allowed " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
action = request . data . get ( " type " )
if action :
if action == " report " : # delete reported actions
MediaAction . objects . filter ( media = media , action = " report " ) . delete ( )
media . reported_times = 0
media . save ( update_fields = [ " reported_times " ] )
return Response (
{ " detail " : " reset reported times counter " } ,
status = status . HTTP_201_CREATED ,
)
else :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " no action specified " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
class MediaSearch ( APIView ) :
"""
Retrieve results for searc
Only GET is implemented here
"""
parser_classes = ( JSONParser , )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Search ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
params = self . request . query_params
query = params . get ( " q " , " " ) . strip ( ) . lower ( )
category = params . get ( " c " , " " ) . strip ( )
tag = params . get ( " t " , " " ) . strip ( )
ordering = params . get ( " ordering " , " " ) . strip ( )
sort_by = params . get ( " sort_by " , " " ) . strip ( )
media_type = params . get ( " media_type " , " " ) . strip ( )
author = params . get ( " author " , " " ) . strip ( )
2021-01-07 14:33:02 +01:00
upload_date = params . get ( ' upload_date ' , ' ' ) . strip ( )
2020-12-15 22:33:43 +01:00
sort_by_options = [ " title " , " add_date " , " edit_date " , " views " , " likes " ]
if sort_by not in sort_by_options :
sort_by = " add_date "
if ordering == " asc " :
ordering = " "
else :
ordering = " - "
if media_type not in [ " video " , " image " , " audio " , " pdf " ] :
media_type = None
if not ( query or category or tag ) :
ret = { }
return Response ( ret , status = status . HTTP_200_OK )
media = Media . objects . filter ( state = " public " , is_reviewed = True )
if query :
2020-12-25 14:07:50 +01:00
# move this processing to a prepare_query function
2020-12-15 22:33:43 +01:00
query = clean_query ( query )
2021-05-26 17:35:21 +02:00
q_parts = [ q_part . rstrip ( " y " ) for q_part in query . split ( ) if q_part not in STOP_WORDS ]
2020-12-15 22:33:43 +01:00
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 )
if tag :
media = media . filter ( tags__title = tag )
if category :
media = media . filter ( category__title__contains = category )
if media_type :
media = media . filter ( media_type = media_type )
if author :
media = media . filter ( user__username = author )
2021-01-07 14:33:02 +01:00
if upload_date :
2021-06-03 17:26:53 +02:00
gte = None
2021-01-07 14:33:02 +01:00
if upload_date == ' today ' :
gte = datetime . now ( ) . date ( )
if upload_date == ' this_week ' :
gte = datetime . now ( ) - timedelta ( days = 7 )
if upload_date == ' this_month ' :
year = datetime . now ( ) . date ( ) . year
month = datetime . now ( ) . date ( ) . month
2021-05-26 17:35:21 +02:00
gte = datetime ( year , month , 1 )
2021-01-07 14:33:02 +01:00
if upload_date == ' this_year ' :
year = datetime . now ( ) . date ( ) . year
2021-05-26 17:35:21 +02:00
gte = datetime ( year , 1 , 1 )
2021-01-07 14:33:02 +01:00
if gte :
media = media . filter ( add_date__gte = gte )
2020-12-15 22:33:43 +01:00
media = media . order_by ( f " { ordering } { sort_by } " )
if self . request . query_params . get ( " show " , " " ) . strip ( ) == " titles " :
media = media . values ( " title " ) [ : 40 ]
return Response ( media , status = status . HTTP_200_OK )
else :
media = media . prefetch_related ( " user " )
if category or tag :
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
else :
# pagination_class = FastPaginationWithoutCount
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
page = paginator . paginate_queryset ( media , request )
2021-05-26 17:35:21 +02:00
serializer = MediaSearchSerializer ( page , many = True , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
return paginator . get_paginated_response ( serializer . data )
class PlaylistList ( APIView ) :
""" Playlists listings and creation views """
permission_classes = ( permissions . IsAuthenticatedOrReadOnly , IsAuthorizedToAdd )
parser_classes = ( JSONParser , MultiPartParser , FormParser , FileUploadParser )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
2021-05-31 21:24:05 +02:00
responses = {
200 : openapi . Response ( ' response description ' , PlaylistSerializer ( many = True ) ) ,
} ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
playlists = Playlist . objects . filter ( ) . prefetch_related ( " user " )
if " author " in self . request . query_params :
author = self . request . query_params [ " author " ] . strip ( )
playlists = playlists . filter ( user__username = author )
page = paginator . paginate_queryset ( playlists , request )
serializer = PlaylistSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def post ( self , request , format = None ) :
serializer = PlaylistSerializer ( data = request . data , context = { " request " : request } )
if serializer . is_valid ( ) :
serializer . save ( user = request . user )
return Response ( serializer . data , status = status . HTTP_201_CREATED )
return Response ( serializer . errors , status = status . HTTP_400_BAD_REQUEST )
class PlaylistDetail ( APIView ) :
""" Playlist related views """
permission_classes = ( permissions . IsAuthenticatedOrReadOnly , IsUserOrEditor )
parser_classes = ( JSONParser , MultiPartParser , FormParser , FileUploadParser )
def get_playlist ( self , friendly_token ) :
try :
playlist = Playlist . objects . get ( friendly_token = friendly_token )
self . check_object_permissions ( self . request , playlist )
return playlist
except PermissionDenied :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " not enough permissions " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
except BaseException :
return Response (
{ " detail " : " Playlist does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def get ( self , request , friendly_token , format = None ) :
playlist = self . get_playlist ( friendly_token )
if isinstance ( playlist , Response ) :
return playlist
serializer = PlaylistDetailSerializer ( playlist , context = { " request " : request } )
2021-05-26 17:35:21 +02:00
playlist_media = PlaylistMedia . objects . filter ( playlist = playlist ) . prefetch_related ( " media__user " )
2020-12-15 22:33:43 +01:00
playlist_media = [ c . media for c in playlist_media ]
2021-05-26 17:35:21 +02:00
playlist_media_serializer = MediaSerializer ( playlist_media , many = True , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
ret = serializer . data
ret [ " playlist_media " ] = playlist_media_serializer . data
return Response ( ret )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def post ( self , request , friendly_token , format = None ) :
playlist = self . get_playlist ( friendly_token )
if isinstance ( playlist , Response ) :
return playlist
2021-05-26 17:35:21 +02:00
serializer = PlaylistDetailSerializer ( playlist , data = request . data , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
if serializer . is_valid ( ) :
serializer . save ( user = request . user )
return Response ( serializer . data , status = status . HTTP_201_CREATED )
return Response ( serializer . errors , status = status . HTTP_400_BAD_REQUEST )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def put ( self , request , friendly_token , format = None ) :
playlist = self . get_playlist ( friendly_token )
if isinstance ( playlist , Response ) :
return playlist
action = request . data . get ( " type " )
media_friendly_token = request . data . get ( " media_friendly_token " )
ordering = 0
if request . data . get ( " ordering " ) :
try :
ordering = int ( request . data . get ( " ordering " ) )
except ValueError :
pass
if action in [ " add " , " remove " , " ordering " ] :
2021-05-26 17:35:21 +02:00
media = Media . objects . filter ( friendly_token = media_friendly_token ) . first ( )
2020-12-15 22:33:43 +01:00
if media :
if action == " add " :
2021-05-26 17:35:21 +02:00
media_in_playlist = PlaylistMedia . objects . filter ( playlist = playlist ) . count ( )
2020-12-15 22:33:43 +01:00
if media_in_playlist > = settings . MAX_MEDIA_PER_PLAYLIST :
return Response (
{ " detail " : " max number of media for a Playlist reached " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
else :
obj , created = PlaylistMedia . objects . get_or_create (
playlist = playlist ,
media = media ,
ordering = media_in_playlist + 1 ,
)
obj . save ( )
return Response (
{ " detail " : " media added to Playlist " } ,
status = status . HTTP_201_CREATED ,
)
elif action == " remove " :
2021-05-26 17:35:21 +02:00
PlaylistMedia . objects . filter ( playlist = playlist , media = media ) . delete ( )
2020-12-15 22:33:43 +01:00
return Response (
{ " detail " : " media removed from Playlist " } ,
status = status . HTTP_201_CREATED ,
)
elif action == " ordering " :
if ordering :
playlist . set_ordering ( media , ordering )
return Response (
{ " detail " : " new ordering set " } ,
status = status . HTTP_201_CREATED ,
)
else :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " media is not valid " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
return Response (
{ " detail " : " invalid or not specified action " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Playlists ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def delete ( self , request , friendly_token , format = None ) :
playlist = self . get_playlist ( friendly_token )
if isinstance ( playlist , Response ) :
return playlist
playlist . delete ( )
return Response ( status = status . HTTP_204_NO_CONTENT )
class EncodingDetail ( APIView ) :
""" Experimental. This View is used by remote workers
Needs heavy testing and documentation .
"""
permission_classes = ( permissions . IsAdminUser , )
parser_classes = ( JSONParser , MultiPartParser , FormParser , FileUploadParser )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema ( auto_schema = None )
2020-12-15 22:33:43 +01:00
def post ( self , request , encoding_id ) :
ret = { }
force = request . data . get ( " force " , False )
task_id = request . data . get ( " task_id " , False )
action = request . data . get ( " action " , " " )
chunk = request . data . get ( " chunk " , False )
chunk_file_path = request . data . get ( " chunk_file_path " , " " )
encoding_status = request . data . get ( " status " , " " )
progress = request . data . get ( " progress " , " " )
commands = request . data . get ( " commands " , " " )
logs = request . data . get ( " logs " , " " )
retries = request . data . get ( " retries " , " " )
worker = request . data . get ( " worker " , " " )
temp_file = request . data . get ( " temp_file " , " " )
total_run_time = request . data . get ( " total_run_time " , " " )
if action == " start " :
try :
encoding = Encoding . objects . get ( id = encoding_id )
media = encoding . media
profile = encoding . profile
except BaseException :
Encoding . objects . filter ( id = encoding_id ) . delete ( )
return Response ( { " status " : " fail " } , status = status . HTTP_400_BAD_REQUEST )
# TODO: break chunk True/False logic here
if (
Encoding . objects . filter (
media = media ,
profile = profile ,
chunk = chunk ,
chunk_file_path = chunk_file_path ,
) . count ( )
2021-06-03 17:26:53 +02:00
> 1 # noqa
and force is False # noqa
2020-12-15 22:33:43 +01:00
) :
Encoding . objects . filter ( id = encoding_id ) . delete ( )
return Response ( { " status " : " fail " } , status = status . HTTP_400_BAD_REQUEST )
else :
Encoding . objects . filter (
media = media ,
profile = profile ,
chunk = chunk ,
chunk_file_path = chunk_file_path ,
) . exclude ( id = encoding . id ) . delete ( )
encoding . status = " running "
if task_id :
encoding . task_id = task_id
encoding . save ( )
if chunk :
original_media_path = chunk_file_path
original_media_md5sum = encoding . md5sum
2021-05-26 17:35:21 +02:00
original_media_url = settings . SSL_FRONTEND_HOST + encoding . media_chunk_url
2020-12-15 22:33:43 +01:00
else :
original_media_path = media . media_file . path
original_media_md5sum = media . md5sum
2021-05-26 17:35:21 +02:00
original_media_url = settings . SSL_FRONTEND_HOST + media . original_media_url
2020-12-15 22:33:43 +01:00
ret [ " original_media_url " ] = original_media_url
ret [ " original_media_path " ] = original_media_path
ret [ " original_media_md5sum " ] = original_media_md5sum
# generating the commands here, and will replace these with temporary
# files created on the remote server
tf = " TEMP_FILE_REPLACE "
tfpass = " TEMP_FPASS_FILE_REPLACE "
ffmpeg_commands = produce_ffmpeg_commands (
original_media_path ,
media . media_info ,
resolution = profile . resolution ,
codec = profile . codec ,
output_filename = tf ,
pass_file = tfpass ,
chunk = chunk ,
)
if not ffmpeg_commands :
encoding . delete ( )
return Response ( { " status " : " fail " } , status = status . HTTP_400_BAD_REQUEST )
ret [ " duration " ] = media . duration
ret [ " ffmpeg_commands " ] = ffmpeg_commands
ret [ " profile_extension " ] = profile . extension
return Response ( ret , status = status . HTTP_201_CREATED )
elif action == " update_fields " :
try :
encoding = Encoding . objects . get ( id = encoding_id )
except BaseException :
return Response ( { " status " : " fail " } , status = status . HTTP_400_BAD_REQUEST )
to_update = [ " size " , " update_date " ]
if encoding_status :
encoding . status = encoding_status
to_update . append ( " status " )
if progress :
encoding . progress = progress
to_update . append ( " progress " )
if logs :
encoding . logs = logs
to_update . append ( " logs " )
if commands :
encoding . commands = commands
to_update . append ( " commands " )
if task_id :
encoding . task_id = task_id
to_update . append ( " task_id " )
if total_run_time :
encoding . total_run_time = total_run_time
to_update . append ( " total_run_time " )
if worker :
encoding . worker = worker
to_update . append ( " worker " )
if temp_file :
encoding . temp_file = temp_file
to_update . append ( " temp_file " )
if retries :
encoding . retries = retries
to_update . append ( " retries " )
try :
encoding . save ( update_fields = to_update )
except BaseException :
return Response ( { " status " : " fail " } , status = status . HTTP_400_BAD_REQUEST )
return Response ( { " status " : " success " } , status = status . HTTP_201_CREATED )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema ( auto_schema = None )
2020-12-15 22:33:43 +01:00
def put ( self , request , encoding_id , format = None ) :
encoding_file = request . data [ " file " ]
encoding = Encoding . objects . filter ( id = encoding_id ) . first ( )
if not encoding :
return Response (
{ " detail " : " encoding does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
encoding . media_file = encoding_file
encoding . save ( )
return Response ( { " detail " : " ok " } , status = status . HTTP_201_CREATED )
class CommentList ( APIView ) :
permission_classes = ( permissions . IsAuthenticatedOrReadOnly , IsAuthorizedToAdd )
parser_classes = ( JSONParser , MultiPartParser , FormParser , FileUploadParser )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [
openapi . Parameter ( name = ' page ' , type = openapi . TYPE_INTEGER , in_ = openapi . IN_QUERY , description = ' Page number ' ) ,
openapi . Parameter ( name = ' author ' , type = openapi . TYPE_STRING , in_ = openapi . IN_QUERY , description = ' username ' ) ,
] ,
tags = [ ' Comments ' ] ,
operation_summary = ' Lists Comments ' ,
operation_description = ' Paginated listing of all comments ' ,
2021-05-31 21:24:05 +02:00
responses = {
200 : openapi . Response ( ' response description ' , CommentSerializer ( many = True ) ) ,
} ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
comments = Comment . objects . filter ( )
comments = comments . prefetch_related ( " user " )
comments = comments . prefetch_related ( " media " )
params = self . request . query_params
if " author " in params :
author_param = params [ " author " ] . strip ( )
user_queryset = User . objects . all ( )
user = get_object_or_404 ( user_queryset , username = author_param )
comments = comments . filter ( user = user )
page = paginator . paginate_queryset ( comments , request )
serializer = CommentSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
class CommentDetail ( APIView ) :
""" Comments related views
Listings of comments for a media ( GET )
Create comment ( POST )
Delete comment ( DELETE )
"""
2020-12-25 15:58:53 +01:00
permission_classes = ( IsAuthorizedToAdd , )
2020-12-15 22:33:43 +01:00
parser_classes = ( JSONParser , MultiPartParser , FormParser , FileUploadParser )
def get_object ( self , friendly_token ) :
try :
2021-05-26 17:35:21 +02:00
media = Media . objects . select_related ( " user " ) . get ( friendly_token = friendly_token )
2020-12-15 22:33:43 +01:00
self . check_object_permissions ( self . request , media )
if media . state == " private " and self . request . user != media . user :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " media is private " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
return media
except PermissionDenied :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " bad permissions " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
except BaseException :
return Response (
{ " detail " : " media file does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def get ( self , request , friendly_token ) :
# list comments for a media
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
comments = media . comments . filter ( ) . prefetch_related ( " user " )
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
page = paginator . paginate_queryset ( comments , request )
serializer = CommentSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def delete ( self , request , friendly_token , uid = None ) :
""" Delete a comment
Administrators , MediaCMS editors and managers ,
media owner , and comment owners , can delete a comment
"""
if uid :
try :
comment = Comment . objects . get ( uid = uid )
except BaseException :
return Response (
{ " detail " : " comment does not exist " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
2021-05-26 17:35:21 +02:00
if ( comment . user == self . request . user ) or comment . media . user == self . request . user or is_mediacms_editor ( self . request . user ) :
2020-12-15 22:33:43 +01:00
comment . delete ( )
else :
2021-05-26 17:35:21 +02:00
return Response ( { " detail " : " bad permissions " } , status = status . HTTP_400_BAD_REQUEST )
2020-12-15 22:33:43 +01:00
return Response ( status = status . HTTP_204_NO_CONTENT )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Media ' ] ,
operation_summary = ' to_be_written ' ,
operation_description = ' to_be_written ' ,
)
2020-12-15 22:33:43 +01:00
def post ( self , request , friendly_token ) :
""" Create a comment """
media = self . get_object ( friendly_token )
if isinstance ( media , Response ) :
return media
if not media . enable_comments :
return Response (
{ " detail " : " comments not allowed here " } ,
status = status . HTTP_400_BAD_REQUEST ,
)
serializer = CommentSerializer ( data = request . data , context = { " request " : request } )
if serializer . is_valid ( ) :
serializer . save ( user = request . user , media = media )
if request . user != media . user :
notify_user_on_comment ( friendly_token = media . friendly_token )
2022-06-01 13:23:21 +02:00
# here forward the comment to check if a user was mentioned
if settings . ALLOW_MENTION_IN_COMMENTS :
check_comment_for_mention ( friendly_token = media . friendly_token , comment_text = serializer . data [ ' text ' ] )
2020-12-15 22:33:43 +01:00
return Response ( serializer . data , status = status . HTTP_201_CREATED )
return Response ( serializer . errors , status = status . HTTP_400_BAD_REQUEST )
class UserActions ( APIView ) :
parser_classes = ( JSONParser , )
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [
openapi . Parameter ( name = ' action ' , type = openapi . TYPE_STRING , in_ = openapi . IN_PATH , description = ' action ' , required = True , enum = VALID_USER_ACTIONS ) ,
] ,
tags = [ ' Users ' ] ,
operation_summary = ' List user actions ' ,
operation_description = ' Lists user actions ' ,
)
2020-12-15 22:33:43 +01:00
def get ( self , request , action ) :
media = [ ]
if action in VALID_USER_ACTIONS :
if request . user . is_authenticated :
2021-05-26 17:35:21 +02:00
media = Media . objects . select_related ( " user " ) . filter ( mediaactions__user = request . user , mediaactions__action = action ) . order_by ( " -mediaactions__action_date " )
2020-12-15 22:33:43 +01:00
elif request . session . session_key :
media = (
Media . objects . select_related ( " user " )
. filter (
mediaactions__session_key = request . session . session_key ,
mediaactions__action = action ,
)
. order_by ( " -mediaactions__action_date " )
)
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
page = paginator . paginate_queryset ( media , request )
serializer = MediaSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
class CategoryList ( APIView ) :
""" List categories """
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Categories ' ] ,
operation_summary = ' Lists Categories ' ,
operation_description = ' Lists all categories ' ,
2021-05-31 21:24:05 +02:00
responses = {
200 : openapi . Response ( ' response description ' , CategorySerializer ) ,
} ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
categories = Category . objects . filter ( ) . order_by ( " title " )
2021-05-26 17:35:21 +02:00
serializer = CategorySerializer ( categories , many = True , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
ret = serializer . data
return Response ( ret )
class TagList ( APIView ) :
""" List tags """
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [
openapi . Parameter ( name = ' page ' , type = openapi . TYPE_INTEGER , in_ = openapi . IN_QUERY , description = ' Page number ' ) ,
] ,
tags = [ ' Tags ' ] ,
operation_summary = ' Lists Tags ' ,
operation_description = ' Paginated listing of all tags ' ,
2021-05-31 21:24:05 +02:00
responses = {
200 : openapi . Response ( ' response description ' , TagSerializer ) ,
} ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
tags = Tag . objects . filter ( ) . order_by ( " -media_count " )
pagination_class = api_settings . DEFAULT_PAGINATION_CLASS
paginator = pagination_class ( )
page = paginator . paginate_queryset ( tags , request )
serializer = TagSerializer ( page , many = True , context = { " request " : request } )
return paginator . get_paginated_response ( serializer . data )
class EncodeProfileList ( APIView ) :
""" List encode profiles """
2021-05-29 15:34:36 +02:00
@swagger_auto_schema (
manual_parameters = [ ] ,
tags = [ ' Encoding Profiles ' ] ,
2021-05-31 21:24:05 +02:00
operation_summary = ' List Encoding Profiles ' ,
operation_description = ' Lists all encoding profiles for videos ' ,
responses = { 200 : EncodeProfileSerializer ( many = True ) } ,
2021-05-29 15:34:36 +02:00
)
2020-12-15 22:33:43 +01:00
def get ( self , request , format = None ) :
profiles = EncodeProfile . objects . all ( )
2021-05-26 17:35:21 +02:00
serializer = EncodeProfileSerializer ( profiles , many = True , context = { " request " : request } )
2020-12-15 22:33:43 +01:00
return Response ( serializer . data )
class TasksList ( APIView ) :
""" List tasks """
2021-05-29 15:34:36 +02:00
swagger_schema = None
2020-12-15 22:33:43 +01:00
permission_classes = ( permissions . IsAdminUser , )
def get ( self , request , format = None ) :
ret = list_tasks ( )
return Response ( ret )
class TaskDetail ( APIView ) :
""" Cancel a task """
2021-05-29 15:34:36 +02:00
swagger_schema = None
2020-12-15 22:33:43 +01:00
permission_classes = ( permissions . IsAdminUser , )
def delete ( self , request , uid , format = None ) :
revoke ( uid , terminate = True )
return Response ( status = status . HTTP_204_NO_CONTENT )