gnm_deliverables/views/views.py (574 lines of code) (raw):

# coding: utf-8 import functools # for reduce() import logging import re import urllib.parse import urllib.parse import os from rabbitmq.time_funcs import get_current_time from django.conf import settings from django.views.generic import TemplateView from gnmvidispine.vidispine_api import VSNotFound, VSException, VSApi from rest_framework import mixins, status from rest_framework.authentication import BasicAuthentication from rest_framework.generics import RetrieveAPIView, \ ListAPIView, CreateAPIView from rest_framework.parsers import JSONParser from rest_framework.permissions import AllowAny from rest_framework.permissions import IsAuthenticated from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.views import APIView import gnm_deliverables.launch_detector from jsonschema import ValidationError from gnm_deliverables.models import * from gnm_deliverables.choices import DELIVERABLE_ASSET_TYPES, \ DELIVERABLE_ASSET_STATUS_NOT_INGESTED, \ DELIVERABLE_ASSET_STATUS_INGESTED, \ DELIVERABLE_ASSET_STATUS_INGEST_FAILED, DELIVERABLE_ASSET_STATUS_INGESTING, \ DELIVERABLE_ASSET_STATUS_TRANSCODED, \ DELIVERABLE_ASSET_STATUS_TRANSCODE_FAILED, DELIVERABLE_ASSET_STATUS_TRANSCODING from gnm_deliverables.exceptions import NoShapeError from gnm_deliverables.files import create_folder_for_deliverable from gnm_deliverables.jwt_auth_backend import JwtRestAuth from gnm_deliverables.hmac_auth_backend import HmacRestAuth from gnm_deliverables.models import Deliverable, DeliverableAsset, YouTubeCategories, YouTubeChannels from gnm_deliverables.serializers import DeliverableAssetSerializer, DeliverableSerializer, DeliverableSerializerExtended, DenormalisedAssetSerializer, SearchRequestSerializer from gnm_deliverables.vs_notification import VSNotification from datetime import datetime, timedelta from django.db.models import Count import copy logger = logging.getLogger(__name__) def inform_sentry_exception(err): pass class NewDeliverableUI(TemplateView): template_name = "gnm_deliverables/new_ui.html" def get_context_data(self, **kwargs): full_url = settings.__getattr__("DEPLOYMENT_ROOT") parts = urllib.parse.urlparse(full_url) cbVersion = "DEV" try: from gnm_deliverables.version import version_branch, version_commit cbVersion = version_commit except Exception as e: logger.exception("Could not get version from source: ") return { "deployment_root": parts.path, "cbVersion": cbVersion, "vidispine_client_uri": settings.VIDISPINE_CLIENT_URI, "media_atom_uri": settings.MEDIA_ATOM_TOOL_URI, "archive_hunter_url": settings.ARCHIVE_HUNTER_URL } class NewDeliverablesAPIList(ListAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) serializer_class = DeliverableSerializer def get_queryset(self): try: if "pageSize" in self.request.GET: page_size = int(self.request.GET["pageSize"]) else: page_size = 50 if "p" in self.request.GET: start_at = int(self.request.GET["p"]) * page_size #page 1 is at index 0 else: start_at = 0 sort_by = 'created' if "sortBy" in self.request.GET: sort_by = self.request.GET["sortBy"] sort_order = '-' if "sortOrder" in self.request.GET: if self.request.GET["sortOrder"] == 'asc': sort_order = '' return Deliverable.objects.all().order_by('{0}{1}'.format(sort_order, sort_by))[start_at:start_at+page_size] except ValueError: return Response({"status":"error","detail":"either pageSize or page was incorrectly formatted"}, status=400) except Exception as e: logger.exception("could not load bundle data: ", e) return Response({"status":"error","detail":str(e)},status=500) class NewDeliverabesApiBundleGet(RetrieveAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) queryset = Deliverable.objects serializer_class = DeliverableSerializer lookup_url_kwarg = "bundleId" class NewDeliverablesApiGet(RetrieveAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) queryset = Deliverable.objects serializer_class = DeliverableSerializer lookup_url_kwarg = "projectId" lookup_field = "pluto_core_project_id" class NewDeliverablesAPICreate(CreateAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) serializer_class = DeliverableSerializer def attempt_create_bundle(self, bundle, auto_name, attempt_number, request): """ Function to attempt to create a bundle. :param bundle: DeliverableSerializer object. :param auto_name: Boolean indicating if auto naming should be attempted if there is a problem with the name. :param attempt_number: Number of attempts. :param request: request object. :return: a Response object indicating the outcome of the attempt. """ if attempt_number > 200: return Response({"status": "conflict", "field": "name", "detail": "This field must be a unique value. Two hundred attempts where made at automatically setting a unique value for it."}, status=409) if not bundle.is_valid(): for field, error_details in bundle.errors.items(): uniqueness_errors = list(filter(lambda entry: entry.code == 'unique', error_details)) if (len(uniqueness_errors) > 0) and (field == "name") and auto_name: data_to_set = copy.copy(request.data) new_name = "{0}{1}".format(request.data["name"], attempt_number) data_to_set["name"] = new_name logger.debug('About to attempt to create a bundle with the name: {0}'.format(new_name)) new_bundle = DeliverableSerializer(data=data_to_set) return self.attempt_create_bundle(new_bundle, auto_name, attempt_number + 1, request) if len(uniqueness_errors) > 0: return Response({"status": "conflict", "field": field, "detail": "This field must be a unique value"}, status=409) return Response({"status": "error", "detail": str(bundle.errors)}, status=400) # If we get here then the request is definitely valid so proceed. name = bundle.validated_data['name'] try: path, created = create_folder_for_deliverable(name) if created and path: logger.info('Created folder for deliverable at: %s', path) bundle.save() return Response({"status": "ok", "data": bundle.data}, status=200) elif not created and path: logger.error('The folder already exists for deliverable at: %s', path) bundle.save() return Response({"status": "ok", "data": bundle.data}, status=200) else: logger.error('Failed to create folder for deliverable at: %s', path) return Response({"status": "error", "data": bundle.data}, status=409) except OSError as e: logger.error('Failed to create folder for {name}: {e}'.format(name=name, e=e.strerror)) return Response({"status": "error", "data": e.strerror}, status=500) def post(self, request, *args, **kwargs): bundle = DeliverableSerializer(data=request.data) auto_name = self.request.GET.get("autoname", "false").lower() in ["true", "t", "yes", "1"] return self.attempt_create_bundle(bundle, auto_name, 1, request) class NewDeliverableAssetAPIList(ListAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) serializer_class = DeliverableAssetSerializer def get_queryset(self): sort_by = 'filename' if "sortBy" in self.request.GET: sort_by = self.request.GET["sortBy"] sort_order = '-' if "sortOrder" in self.request.GET: if self.request.GET["sortOrder"] == 'asc': sort_order = '' bundle_id = self.request.GET["project_id"] parent_bundle = Deliverable.objects.get(pluto_core_project_id=bundle_id) return DeliverableAsset.objects.filter(deliverable=parent_bundle).order_by('{0}{1}'.format(sort_order, sort_by)) def get(self, *args, **kwargs): try: return super(NewDeliverableAssetAPIList, self).get(*args, **kwargs) except Deliverable.DoesNotExist: return Response({"status": "error", "detail": "Project not known"}, status=404) except KeyError: return Response( {"status": "error", "detail": "you must specify a project_id= query param"}, status=400) class DeliverableAPIView(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def delete(self, *args, **kwargs): bundle_id = self.request.GET["project_id"] parent_bundle = Deliverable.objects.get(pluto_core_project_id=bundle_id) deliverables = DeliverableAsset.objects.filter(deliverable=parent_bundle, pk__in=self.request.data) for asset in deliverables: try: if os.path.exists(str(asset.absolute_path)): asset.remove_file() #asset.purge(user=self.request.user.get_username()) asset.purge() asset.delete() except Exception as e: logger.error("Could not delete existing path or asset for asset {0}: {1}".format(str(asset), str(e))) return Response(status=status.HTTP_204_NO_CONTENT) class CountDeliverablesView(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def get(self, *args, **kwargs): bundle_id = self.kwargs["project_id"] try: parent_bundle = Deliverable.objects.get(pluto_core_project_id=bundle_id) deliverables_count = DeliverableAsset.objects.filter(deliverable=parent_bundle, ).count() not_started = DeliverableAsset.objects.filter(deliverable=parent_bundle, status=DELIVERABLE_ASSET_STATUS_NOT_INGESTED).count() ingest_failed = DeliverableAsset.objects.filter(deliverable=parent_bundle, status=DELIVERABLE_ASSET_STATUS_INGEST_FAILED).count() transcode_failed = DeliverableAsset.objects.filter(deliverable=parent_bundle, status=DELIVERABLE_ASSET_STATUS_TRANSCODE_FAILED).count() unimported_count = not_started + ingest_failed + transcode_failed result = {'total_asset_count': deliverables_count, 'unimported_asset_count': unimported_count} return Response(result, status=200) except Deliverable.DoesNotExist: return Response({"status":"notfound","detail":"Deliverable bundle does not exist"}, status=404) class NewDeliverableAPIScan(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) def post(self, request): try: bundle = Deliverable.objects.get(pluto_core_project_id=request.GET["project_id"]) results = bundle.sync_assets_from_file_system() return Response({"status": "ok", "detail": "resync performed", **results}, status=200) except Deliverable.DoesNotExist: return Response({"status": "error", "detail": "Project not known"}, status=404) except Exception as e: return Response({"status": "error", "detail": str(e)}, status=500) class DeliverablesTypeListAPI(APIView): """ returns a json object of the available categories. this is in the format of: { "section": [ [id,name], [id,name], ... ], "section": [ [id,name], [id,name], ... ], } """ authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) def get(self, request): result = functools.reduce(lambda acc, cat: {**acc, **{cat[0]: cat[1]}}, DeliverableAsset.type.field.choices, {}) return Response(result, status=200) class AdoptExistingVidispineItemView(APIView): """ tries to adopt the given vidispine item into the bundle list. """ authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) vs_validator = re.compile(r'^\w{2}-\d+$') def post(self, request): project_id = request.GET.get("project_id") vs_id = request.GET.get("vs_id") if project_id is None or vs_id is None: return Response({"status": "error", "detail": "missing either project_id or vs_id"}, status=400) if not self.vs_validator.match(vs_id): return Response({"status": "error", "detail": "vidispine id is invalid"}, status=400) try: # FIXME: once bearer token auth is integrated, then the user= field must be set in create_asset_from_vs_item bundle = Deliverable.objects.get(pluto_core_project_id=project_id) asset, created = bundle.create_asset_from_vs_item(vs_id, user="admin") if created: return Response({"status": "ok", "detail": "item attached"}, status=200) else: return Response( {"status": "conflict", "detail": "item is already attached to this bundle!"}, status=409) except Deliverable.DoesNotExist: return Response({"status": "notfound", "detail": "that deliverable does not exist"}, status=404) except NoShapeError: return Response({"status": "error", "detail": "the given item has no media"}, status=400) except VSNotFound: return Response( {"status": "notfound", "detail": "that item does not exist in Vidispine"}, status=404) except VSException as e: logger.exception( "Could not communicate with VS adopting item {0}: {1}".format(vs_id, str(e))) return Response({"status": "server_error", "detail": str(e)}) except Exception as e: logger.exception("Unexpected error adopting VS item {0}: ".format(vs_id)) return Response({"status": "server_error", "detail": str(e)}) class SetTypeView(APIView): """ set the deliverable type of the item and possibly trigger ingest """ authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def put(self, request, bundleId, assetId): try: item = DeliverableAsset.objects.get(id=assetId) except DeliverableAsset.DoesNotExist: return Response({"status": "notfound", "detail": "No such item exists"}, status=404) if item.deliverable.pluto_core_project_id != bundleId: return Response({"status": "notfound", "detail": "No such item exists"}, status=404) if "type" not in request.data: return Response({"status": "error", "detail": "No type field in body"}, status=400) if not isinstance(request.data["type"], int): return Response({"status": "error", "detail": "Type must be an integer identifier"}, status=400) try: item.type = request.data["type"] if item.online_item_id is None: logger.info("user object is {0}".format(request.user.__dict__)) logger.info("username is {0}".format(request.user.get_username())) item.start_file_import(user=request.user.get_username()) else: item.save() return Response(status=201) except Exception as e: logger.exception("Could not update item type: ", exc_info=e) return Response({"status": "server_error", "detail": str(e)}, status=500) class TestCreateProxyView(APIView): authentication_classes = (JwtRestAuth, BasicAuthentication,) permission_classes = (IsAuthenticated,) def post(self, request, bundleId, assetId): try: item = DeliverableAsset.objects.get(id=assetId) except DeliverableAsset.DoesNotExist: return Response({"status": "notfound", "detail": "No such item exists"}, status=404) try: job_id = item.create_proxy() if job_id is None: return Response({"status": "not_needed", "detail": "A proxy already exists"}, status=409) else: return Response({"status": "ok", "job_id": job_id}, status=200) except Exception as e: logger.exception("Could not create proxy for asset id {0}: ".format(assetId), exc_info=e) return Response({"status": "error", "detail": str(e)}, status=500) class GetAssetView(RetrieveAPIView): authentication_classes = (JwtRestAuth, ) permission_classes = (IsAuthenticated, ) renderer_classes = (JSONRenderer, ) queryset = DeliverableAsset.objects.all() serializer_class = DenormalisedAssetSerializer class DeliverableAPIStarted(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def get(self, *args, **kwargs): project_id = self.request.GET["project_id"] try: parent_bundle = Deliverable.objects.get(pluto_core_project_id=project_id) if parent_bundle.assets.filter(status=DELIVERABLE_ASSET_STATUS_NOT_INGESTED).exists(): result = {'ingests_started': False} else: result = {'ingests_started': True} return Response(result, status=200) except Deliverable.DoesNotExist: return Response({"status": "error", "detail": "Bundle not known"}, status=404) except KeyError: return Response({"status": "error", "detail": "You must specify a bundleId= query parameter"}, status=400) class LaunchDetectorUpdateView(APIView): authentication_classes = (HmacRestAuth, ) permission_classes = (IsAuthenticated, ) parser_classes = (JSONParser, ) renderer_classes = (JSONRenderer, ) def post(self, request, atom_id=None): from time import sleep logger.info("Received update from launch detector: {0}".format(request.data)) try: msg = gnm_deliverables.launch_detector.LaunchDetectorUpdate(request.data) except ValidationError as e: logger.error("External update didn't validate: {0}".format(str(e))) logger.error("Offending content was: {0}".format(request.data)) return Response({"status":"invalid_data"}, status=400) if msg.atom_id=="": logger.error("Received empty body") return Response({"status":"invalid_data"},status=400) attempt = 1 while True: try: return self.try_update(request, msg) except DeliverableAsset.DoesNotExist: logger.error("Could not find a deliverable asset matching the atom id {0}".format(msg.atom_id)) if attempt>=5: return Response({"status":"not_found","atom_id":msg.atom_id}, status=404) else: attempt+=1 #asynchronous retries would be a LOT better. But would be a lot more work too. We'll #re-visit if this causes problems. Max delay is 15s. logger.warning("Retrying for attempt {} after 3s...".format(attempt)) sleep(3) except Exception as e: logger.exception("Could not process incoming update for {0}: ".format(atom_id), exc_info=e) return Response({"status":"server_error", "detail": str(e)}, status=500) def try_update(self, request, msg): asset = gnm_deliverables.launch_detector.find_asset_for(msg) logger.info("Found asset ID {} for {}".format(asset.pk, asset.atom_id)) gnm_deliverables.launch_detector.update_gnmwebsite(msg, asset) gnm_deliverables.launch_detector.update_dailymotion(msg, asset) gnm_deliverables.launch_detector.update_mainstream(msg, asset) gnm_deliverables.launch_detector.update_youtube(msg, asset) asset.save() return Response({"status":"ok", "detail":"updated","atom_id":msg.atom_id}, status=200) class SearchForDeliverableAPIView(RetrieveAPIView): """ see if we have any deliverable assets with the given file name. This is used for tagging during the backup process. """ renderer_classes = (JSONRenderer, ) authentication_classes = (JwtRestAuth, HmacRestAuth, BasicAuthentication) permission_classes = (IsAuthenticated, ) serializer_class = DenormalisedAssetSerializer def get_object(self, queryset=None): fileName = self.request.GET["filename"] return DeliverableAsset.objects.filter(filename=fileName)[0] def get(self, request, *args, **kwargs): try: return super(SearchForDeliverableAPIView, self).get(request,*args,**kwargs) except KeyError: return Response({"status":"badrequest","detail":"You must include ?filename in the url"},status=400) except IndexError: return Response({"status":"notfound","detail":"No deliverables found with the filename {0}".format(self.request.GET["filename"])}, status=404) except Exception as e: logger.exception("Could not look up deliverables for filename {0}:".format(self.request.GET["filename"]), e) return Response({"status":"error","detail":str(e)}, status=500) class GenericAssetSearchAPI(ListAPIView): renderer_classes = (JSONRenderer, ) parser_classes = (JSONParser, ) authentication_classes = (JwtRestAuth, HmacRestAuth, BasicAuthentication) permission_classes = (IsAuthenticated, ) serializer_class = DeliverableAssetSerializer def __init__(self, *args, **kwargs): super(GenericAssetSearchAPI, self).__init__(*args, **kwargs) self._search_request:SearchRequestSerializer = None def get_queryset(self): from django.db.models import Q if self._search_request is None: raise Exception("no search request saved") queryset = DeliverableAsset.objects.all() if self._search_request.validated_data["title"] and self._search_request.validated_data["title"]!="": queryset = queryset.filter(Q(filename__icontains=self._search_request.validated_data["title"]) | \ Q(gnm_website_master__website_title__icontains=self._search_request.validated_data["title"]) | \ Q(mainstream_master__mainstream_title__icontains=self._search_request.validated_data["title"]) | \ Q(DailyMotion_master__daily_motion_title__icontains=self._search_request.validated_data["title"]) | \ Q(youtube_master__youtube_title__icontains=self._search_request.validated_data["title"])) if self._search_request.validated_data["atom_id"] and self._search_request.validated_data["atom_id"]!="": queryset = queryset.filter(atom_id=self._search_request.validated_data["atom_id"]) if self._search_request.validated_data["commission_id"] and self._search_request.validated_data["commission_id"]!=0: queryset = queryset.filter(deliverable__commission_id=self._search_request.validated_data["commission_id"]) if self._search_request.validated_data["order_by"]: queryset = queryset.order_by(self._search_request.validated_data["order_by"]) else: queryset = queryset.order_by("-modified_dt") if ("startAt" in self.request.GET) or ("limit" in self.request.GET): start_at = 0 limit = 25 if "startAt" in self.request.GET: start_at = int(self.request.GET["startAt"]) if "limit" in self.request.GET: limit = int(self.request.GET["limit"]) queryset = queryset[start_at:limit] return queryset def get(self, request, *args, **kwargs): return Response({"status":"error","detail":"GET not supported on this endpoint"}, status=405) def post(self, request, *args, **kwargs): rq = SearchRequestSerializer(data=request.data) if not rq.is_valid(raise_exception=False): return Response({"status":"bad_request", "missing_fields": [str(x) for x in rq.errors]}, status=400) self._search_request = rq try: return super(GenericAssetSearchAPI, self).get(request, *args, **kwargs) except Exception as e: logger.exception("could not perform asset search: ", exc_info=e) return Response({"status":"error", "detail": str(e)}, status=500) class BundlesForCommission(ListAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) serializer_class = DeliverableSerializerExtended def get_queryset(self): return Deliverable.objects.filter(commission_id=self.kwargs['commissionId']) class RetryJobForAsset(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) def put(self, request, job_id, asset_id): try: vs_api = VSApi(url=settings.VIDISPINE_URL, user=settings.VIDISPINE_USER, passwd=settings.VIDISPINE_PASSWORD) vs_job_data = vs_api.request("/job/{0}/re-run".format(job_id), method="POST") asset = DeliverableAsset.objects.get(id=asset_id) asset.job_id = vs_job_data.find("{http://xml.vidispine.com/schema/vidispine}jobId").text asset.status = DELIVERABLE_ASSET_STATUS_INGESTING asset.save() return Response({"status": "ok", "detail": "New job created with id.: {0}".format(asset.job_id)}, status=200) except VSNotFound: logger.error("The job did not exist when attempting to retry job {0} for asset {1}: {2}".format(job_id , asset_id, str(e))) return Response({"status": "notfound", "detail": "That job does not exist in Vidispine"}, status=404) except Exception as e: logger.error("An error occurred when attempting to retry job {0} for asset {1}: {2}".format(job_id , asset_id, str(e))) return Response({"status": "error", "detail": str(e)}, status=500) class InvalidAPIList(ListAPIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) serializer_class = DeliverableAssetSerializer def get_queryset(self): data_limit = 128 if 'limit' in self.request.GET: data_limit = int(self.request.GET["limit"]) if 'date' in self.request.GET: return DeliverableAsset.objects.filter(access_dt__icontains=self.request.GET["date"]).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTING).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODING)[0:data_limit] elif 'type' in self.request.GET: return DeliverableAsset.objects.filter(type=self.request.GET["type"]).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTING).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODING)[0:data_limit] elif 'status' in self.request.GET: return DeliverableAsset.objects.filter(status=self.request.GET["status"])[0:data_limit] else: return DeliverableAsset.objects.exclude(status=DELIVERABLE_ASSET_STATUS_INGESTING).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODING)[0:data_limit] def get(self, *args, **kwargs): try: return super(InvalidAPIList, self).get(*args, **kwargs) except Exception as e: logger.exception("Could not load invalid deliverable assets: {0}".format(str(e))) return Response({"status":"error","detail":"Could not load invalid deliverable assets: {0}".format(str(e))}, status=500) class CountInvalid(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def get(self, *args, **kwargs): try: result = [ DeliverableAsset.objects.filter(access_dt__icontains=datetime.strftime((datetime.now() - timedelta(i)), '%Y-%m-%d')).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTING).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODING).count() for i in range(11, -1, -1)] return Response(result, status=200) except Exception: return Response({"status":"error","detail":"Could not process invalid count."}, status=500) class CountInvalidByType(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def get(self, *args, **kwargs): try: result = [ DeliverableAsset.objects.filter(type=i).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTING).exclude(status=DELIVERABLE_ASSET_STATUS_INGESTED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODED).exclude(status=DELIVERABLE_ASSET_STATUS_TRANSCODING).count() for i in range(1, 16, 1)] return Response(result, status=200) except Exception: return Response({"status":"error","detail":"Could not process invalid count."}, status=500) class CountInvalidByStatus(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) parser_classes = (JSONParser,) def get(self, *args, **kwargs): try: result = DeliverableAsset.objects.values("status").annotate(Count("id")) return Response(result, status=200) except Exception as e: logger.exception("Could not process invalid count: {0}".format(str(e))) return Response({"status":"error","detail":"Could not process invalid count: {0}".format(str(e))}, status=500) class TestAndFixDropfolder(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated, ) renderer_classes = (JSONRenderer, ) def get(self, *args, **kwargs): project_id = kwargs.get("project_id") if project_id is None: #the router should prevent this from happening but there's no harm in handling the case here return Response({"status": "error", "detail": "bad request"}, status=400) try: bundle = Deliverable.objects.get(pluto_core_project_id=project_id) bundle.create_folder_for_deliverable() return Response({"status": "ok", "clientpath": bundle.local_path}) except Deliverable.DoesNotExist: return Response({"status": "notfound", "detail": "Invalid deliverable bundle"}, status=404) except Exception as e: logger.exception("TestAndFixDropfolder got an unexpected error: {0}".format(str(e))) return Response({"status": "error", "detail": str(e)}, status=500) class GetYouTubeCategory(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) def get(self, request, category_id): try: category = YouTubeCategories.objects.get(identity=category_id) return Response({"title": category.title}, status=200) except YouTubeCategories.DoesNotExist: return Response({"status": "error", "detail": "Category not known."}, status=404) except KeyError: return Response({"status": "error", "detail": "You must specify a category identity."}, status=400) class GetYouTubeChannel(APIView): authentication_classes = (JwtRestAuth, HmacRestAuth) permission_classes = (IsAuthenticated,) renderer_classes = (JSONRenderer,) def get(self, request, channel_id): try: channel = YouTubeChannels.objects.get(identity=channel_id) return Response({"title": channel.title}, status=200) except YouTubeChannels.DoesNotExist: return Response({"status": "error", "detail": "Channel not known."}, status=404) except KeyError: return Response({"status": "error", "detail": "You must specify a channel identity."}, status=400)