##// END OF EJS Templates
Support audio viewer
neko259 -
r1279:03b66329 default
parent child Browse files
Show More
@@ -1,75 +1,76 b''
1 import hashlib
1 import hashlib
2 import os
2 import os
3 import time
3 import time
4
4
5 from random import random
5 from random import random
6
6
7 from django.db import models
7 from django.db import models
8
8
9 from boards.models.attachment.viewers import AbstractViewer, WebmViewer
9 from boards.models.attachment.viewers import AbstractViewer, WebmViewer, \
10
10 AudioViewer
11
11
12 FILES_DIRECTORY = 'files/'
12 FILES_DIRECTORY = 'files/'
13 FILE_EXTENSION_DELIMITER = '.'
13 FILE_EXTENSION_DELIMITER = '.'
14
14
15 VIEWERS = (
15 VIEWERS = (
16 WebmViewer,
16 WebmViewer,
17 AudioViewer,
17 )
18 )
18
19
19
20
20 class AttachmentManager(models.Manager):
21 class AttachmentManager(models.Manager):
21 def create_with_hash(self, file):
22 def create_with_hash(self, file):
22 file_hash = self.get_hash(file)
23 file_hash = self.get_hash(file)
23 existing = self.filter(hash=file_hash)
24 existing = self.filter(hash=file_hash)
24 if len(existing) > 0:
25 if len(existing) > 0:
25 attachment = existing[0]
26 attachment = existing[0]
26 else:
27 else:
27 file_type = file.name.split(FILE_EXTENSION_DELIMITER)[-1].lower()
28 file_type = file.name.split(FILE_EXTENSION_DELIMITER)[-1].lower()
28 attachment = Attachment.objects.create(file=file,
29 attachment = Attachment.objects.create(file=file,
29 mimetype=file_type, hash=file_hash)
30 mimetype=file_type, hash=file_hash)
30
31
31 return attachment
32 return attachment
32
33
33 def get_hash(self, file):
34 def get_hash(self, file):
34 """
35 """
35 Gets hash of an file.
36 Gets hash of an file.
36 """
37 """
37 md5 = hashlib.md5()
38 md5 = hashlib.md5()
38 for chunk in file.chunks():
39 for chunk in file.chunks():
39 md5.update(chunk)
40 md5.update(chunk)
40 return md5.hexdigest()
41 return md5.hexdigest()
41
42
42
43
43 class Attachment(models.Model):
44 class Attachment(models.Model):
44 objects = AttachmentManager()
45 objects = AttachmentManager()
45
46
46 # TODO Dedup the method
47 # TODO Dedup the method
47 def _update_filename(self, filename):
48 def _update_filename(self, filename):
48 """
49 """
49 Gets unique filename
50 Gets unique filename
50 """
51 """
51
52
52 # TODO Use something other than random number in file name
53 # TODO Use something other than random number in file name
53 new_name = '{}{}.{}'.format(
54 new_name = '{}{}.{}'.format(
54 str(int(time.mktime(time.gmtime()))),
55 str(int(time.mktime(time.gmtime()))),
55 str(int(random() * 1000)),
56 str(int(random() * 1000)),
56 filename.split(FILE_EXTENSION_DELIMITER)[-1:][0])
57 filename.split(FILE_EXTENSION_DELIMITER)[-1:][0])
57
58
58 return os.path.join(FILES_DIRECTORY, new_name)
59 return os.path.join(FILES_DIRECTORY, new_name)
59
60
60 file = models.FileField(upload_to=_update_filename)
61 file = models.FileField(upload_to=_update_filename)
61 mimetype = models.CharField(max_length=50)
62 mimetype = models.CharField(max_length=50)
62 hash = models.CharField(max_length=36)
63 hash = models.CharField(max_length=36)
63
64
64 def get_view(self):
65 def get_view(self):
65 file_viewer = None
66 file_viewer = None
66 for viewer in VIEWERS:
67 for viewer in VIEWERS:
67 if viewer.supports(self.mimetype):
68 if viewer.supports(self.mimetype):
68 file_viewer = viewer(self.file, self.mimetype)
69 file_viewer = viewer(self.file, self.mimetype)
69 break
70 break
70 if file_viewer is None:
71 if file_viewer is None:
71 file_viewer = AbstractViewer(self.file, self.mimetype)
72 file_viewer = AbstractViewer(self.file, self.mimetype)
72
73
73 return file_viewer.get_view()
74 return file_viewer.get_view()
74
75
75
76
@@ -1,40 +1,50 b''
1 from django.template.defaultfilters import filesizeformat
1 from django.template.defaultfilters import filesizeformat
2 from django.templatetags.static import static
2 from django.templatetags.static import static
3
3
4 FILE_STUB_IMAGE = 'images/file.png'
5
6 FILE_TYPE_WEBM = 'webm'
7 FILE_TYPES_AUDIO = (
8 'ogg',
9 'mp3',
10 )
11
4
12
5 class AbstractViewer:
13 class AbstractViewer:
6 def __init__(self, file, file_type):
14 def __init__(self, file, file_type):
7 self.file = file
15 self.file = file
8 self.file_type = file_type
16 self.file_type = file_type
9
17
10 @staticmethod
18 @staticmethod
11 def get_viewer(file_type, file):
12 for viewer in VIEWERS:
13 if viewer.supports(file_type):
14 return viewer(file)
15 return AbstractViewer(file)
16
17 @staticmethod
18 def supports(file_type):
19 def supports(file_type):
19 return true
20 return True
20
21
21 def get_view(self):
22 def get_view(self):
22 return '<div class="image"><a href="{}">'\
23 return '<div class="image"><a href="{}">'\
23 '<img src="{}" width="200" height="150"/>'\
24 '<img src="{}" width="200" height="150"/>'\
24 '</a>'\
25 '</a>'\
25 '<div class="image-metadata">{}, {}</div>'\
26 '<div class="image-metadata">{}, {}</div>'\
26 '</div>'.format(self.file.url, static('images/file.png'), self.file_type,
27 '</div>'.format(self.file.url, static(FILE_STUB_IMAGE),
27 filesizeformat(self.file.size))
28 self.file_type, filesizeformat(self.file.size))
28
29
29
30
30 class WebmViewer(AbstractViewer):
31 class WebmViewer(AbstractViewer):
31 @staticmethod
32 @staticmethod
32 def supports(file_type):
33 def supports(file_type):
33 return file_type == 'webm'
34 return file_type == FILE_TYPE_WEBM
34
35
35 def get_view(self):
36 def get_view(self):
36 return '<div class="image">'\
37 return '<div class="image">'\
37 '<video width="200" height="150" controls/>'\
38 '<video width="200" height="150" controls src="{}"/>'\
38 '<source src="{}">'\
39 '</div>'.format(self.file.url)
39 '</div>'.format(self.file.url)
40
40
41
42 class AudioViewer(AbstractViewer):
43 @staticmethod
44 def supports(file_type):
45 return file_type in FILE_TYPES_AUDIO
46
47 def get_view(self):
48 return '<div class="image">' \
49 '<audio controls src="{}"/>' \
50 '</div>'.format(self.file.url)
General Comments 0
You need to be logged in to leave comments. Login now