polyphonic/interface/models.py
2021-09-04 10:29:22 +10:00

183 lines
6.0 KiB
Python

from django.db import models
from django.utils.text import slugify
from django.utils import timezone
from django.conf import settings
from django.shortcuts import resolve_url
import random
import boto3
from datetime import datetime
from urllib.parse import urlparse
import os.path
s3client = boto3.client('s3', **getattr(settings, 'S3_CREDENTIALS', {}))
BUCKET = settings.AWS_BUCKET
MEDIA_TYPES = [
('audio', "Audio"),
('video', "Video"),
('general', "General"),
]
def rough_date(d):
days = (self.event_date - timezone.now().date()).days
in_past = days < 0
if in_past:
days = abs(days)
if days ==0:
return "today!"
if days >= 7:
return in_past, "{0:d} weeks, {1:d} days".format(days / 7, days % 7)
return in_past, f"{days} days"
def generate_code(length=9):
return "".join([ random.choice('0123456789') for _ in range(length) ])
class Ensemble(models.Model):
name = models.CharField(max_length=100)
code = models.CharField(max_length=9, default=generate_code)
passphrase = models.CharField(max_length=100)
admins = models.ManyToManyField('auth.User', related_name='ensembles')
slug = models.SlugField(max_length=100, editable=False)
details = models.TextField(blank=True)
storage = models.ForeignKey('byostorage.UserStorage', null=True, on_delete=models.SET_NULL)
def active_projects(self):
return self.projects.filter(active=True)
def ensemble_code(self):
code = str(self.code)
return "{}-{}-{}".format(code[:3], code[3:6], code[6:])
def save(self, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super(Ensemble, self).save(**kwargs)
def __str__(self):
return self.name
class Project(models.Model):
name = models.CharField(max_length=100)
ensemble = models.ForeignKey(Ensemble, related_name='projects', on_delete=models.CASCADE, null=True)
description = models.TextField(blank=True)
active = models.BooleanField(default=True)
event_date =models.DateField(null=True, blank=True)
owner = models.CharField(max_length=255, blank=True)
slug = models.SlugField(max_length=100, editable=False)
enable_library = models.BooleanField(default=True, help_text="Enable items to be added from the library")
enable_submissions = models.BooleanField(default=False, help_text="Allow media submissions from participants")
@property
def submissions(self):
return self.all_submissions.filter(complete=True).order_by('-pk')
def presigned_post(self, object_name, fields=None, conditions=None, expires=3600):
key = os.path.join(self.slug, object_name)
return s3client.generate_presigned_post(BUCKET, key, Fields=fields or {}, Conditions=conditions or [], ExpiresIn=expires)
@property
def days(self):
return (self.event_date - timezone.now().date()).days
@property
def has_happened(self):
return self.event_date < timezone.now().date()
def save(self):
if not self.slug:
self.slug = slugify(self.name)
super(Project, self).save()
def __str__(self):
return self.name
class Resource(models.Model):
project = models.ForeignKey(Project, related_name='resources', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
key = models.CharField(max_length=255, blank=True)
media_type = models.CharField(max_length=10, choices=MEDIA_TYPES, default='*')
visible = models.BooleanField(default=True)
def key_template(self):
return "{}/${{filename}}".format(slugify(self.name))
def accept(self):
if self.media_type == 'general':
return ".*"
return f"{self.media_type}/*"
def presigned_url(self):
if not self.key:
return ""
params = {'Bucket': BUCKET, 'Key': self.key}
return s3client.generate_presigned_url('get_object', Params=params, ExpiresIn=3600*24)
def __str__(self):
return self.name
class WikiPage(models.Model):
project = models.ForeignKey(Project, related_name='wiki_pages', on_delete=models.CASCADE)
title = models.CharField(max_length=255)
markdown = models.TextField()
def get_absolute_url(self):
return resolve_url('wiki', project=self.project_id, pk=self.pk)
def __str__(self):
return self.title
class Submission(models.Model):
project = models.ForeignKey(Project, related_name='all_submissions', on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True, )
name = models.CharField(max_length=255)
instrument = models.CharField(max_length=100, verbose_name="Instrument / Voice")
notes = models.TextField(blank=True)
complete = models.BooleanField(default=False)
url = models.CharField(max_length=512, blank=True)
private = models.BooleanField(default=False)
@property
def download_url(self):
if not self.complete:
raise RuntimeError("Submission not complete")
if self.private:
return self.url
params = {'Bucket': BUCKET, 'Key': self.url}
return s3client.generate_presigned_url('get_object', Params=params, ExpiresIn=3600)
@property
def download_name(self):
uri = urlparse(self.download_url)
_, name = os.path.split(uri.path)
return name or "<Unknown>"
def key_template(self):
return "submissions/{}_{}_{}_${{filename}}".format(
timezone.localtime(self.date).isoformat(timespec='seconds').replace(':', '')[:17],
slugify(self.name),
slugify(self.instrument)
)
@property
def short_name(self):
_, ext = os.path.splitext(self.download_name)
return "{}_{}_{}{}".format(
#timezone.localtime(self.date).strftime("%Y%m%d%H%M%S"),
slugify(self.name),
slugify(self.instrument),
self.pk,
ext
)
def __str__(self):
return f"{self.name}: {self.date}"