##// END OF EJS Templates
Fixed flac mimetype for viewing
neko259 -
r1867:68469e1a default
parent child Browse files
Show More
@@ -1,239 +1,239 b''
1 1 import re
2 2
3 3 from PIL import Image
4 4
5 5 from django.contrib.staticfiles import finders
6 6 from django.contrib.staticfiles.templatetags.staticfiles import static
7 7 from django.core.files.images import get_image_dimensions
8 8 from django.template.defaultfilters import filesizeformat
9 9 from django.core.urlresolvers import reverse
10 10 from django.utils.translation import ugettext_lazy as _, ungettext_lazy
11 11
12 12 from boards.utils import get_domain, cached_result
13 13 from boards import settings
14 14
15 15
16 16 FILE_STUB_IMAGE = 'images/file.png'
17 17 FILE_STUB_URL = 'url'
18 18 FILE_FILEFORMAT = 'images/fileformats/{}.png'
19 19
20 20
21 21 FILE_TYPES_VIDEO = (
22 22 'video/webm',
23 23 'video/mp4',
24 24 'video/mpeg',
25 25 'video/ogv',
26 26 )
27 27 FILE_TYPE_SVG = 'image/svg'
28 28 FILE_TYPES_AUDIO = (
29 29 'audio/ogg',
30 30 'audio/mp3',
31 31 'audio/opus',
32 'audio/flac',
32 'audio/x-flac',
33 33 )
34 34 FILE_TYPES_IMAGE = (
35 35 'image/jpeg',
36 36 'image/jpg',
37 37 'image/png',
38 38 'image/bmp',
39 39 'image/gif',
40 40 )
41 41
42 42 PLAIN_FILE_FORMATS = {
43 43 'application/zip': 'archive',
44 44 'application/x-tar': 'archive',
45 45 'gz': 'archive',
46 46 'audio/midi' : 'midi',
47 47 }
48 48
49 49 URL_PROTOCOLS = {
50 50 'magnet': 'magnet',
51 51 }
52 52
53 53 CSS_CLASS_IMAGE = 'image'
54 54 CSS_CLASS_THUMB = 'thumb'
55 55
56 56 ABSTRACT_VIEW = '<div class="image">'\
57 57 '{}'\
58 58 '<div class="image-metadata"><a href="{}" download >{}, {}</a>'\
59 59 ' <a class="file-menu" href="#" data-type="{}" data-search-url="{}" data-filename="{}">πŸ” </a></div>'\
60 60 '</div>'
61 61 URL_VIEW = '<div class="image">' \
62 62 '{}' \
63 63 '<div class="image-metadata">{}</div>' \
64 64 '</div>'
65 65 ABSTRACT_FORMAT_VIEW = '<a href="{}">'\
66 66 '<img class="url-image" src="{}" width="{}" height="{}"/>'\
67 67 '</a>'
68 68 VIDEO_FORMAT_VIEW = '<video width="200" height="150" controls src="{}"></video>'
69 69 AUDIO_FORMAT_VIEW = '<audio controls src="{}"></audio>'
70 70 IMAGE_FORMAT_VIEW = '<a class="{}" href="{full}">' \
71 71 '<img class="post-image-preview"' \
72 72 ' src="{}"' \
73 73 ' alt="{}"' \
74 74 ' width="{}"' \
75 75 ' height="{}"' \
76 76 ' data-width="{}"' \
77 77 ' data-height="{}" />' \
78 78 '</a>'
79 79 SVG_FORMAT_VIEW = '<a class="thumb" href="{}">'\
80 80 '<img class="post-image-preview" width="200" height="150" src="{}" />'\
81 81 '</a>'
82 82 URL_FORMAT_VIEW = '<a href="{}">' \
83 83 '<img class="url-image" src="{}" width="{}" height="{}"/>' \
84 84 '</a>'
85 85
86 86
87 87 def get_viewers():
88 88 return AbstractViewer.__subclasses__()
89 89
90 90
91 91 def get_static_dimensions(filename):
92 92 file_path = finders.find(filename)
93 93 return get_image_dimensions(file_path)
94 94
95 95
96 96 # TODO Move this to utils
97 97 def file_exists(filename):
98 98 return finders.find(filename) is not None
99 99
100 100
101 101 class AbstractViewer:
102 102 def __init__(self, file, file_type, hash, url):
103 103 self.file = file
104 104 self.file_type = file_type
105 105 self.hash = hash
106 106 self.url = url
107 107
108 108 @staticmethod
109 109 def supports(file_type):
110 110 return True
111 111
112 112 def get_view(self):
113 113 search_host = settings.get('External', 'ImageSearchHost')
114 114 if search_host:
115 115 if search_host.endswith('/'):
116 116 search_host = search_host[:-1]
117 117 search_url = search_host + self.file.url
118 118 else:
119 119 search_url = ''
120 120
121 121 return ABSTRACT_VIEW.format(self.get_format_view(), self.file.url,
122 122 self.file_type, filesizeformat(self.file.size),
123 123 self.file_type, search_url, self.file.name)
124 124
125 125 def get_format_view(self):
126 126 image_name = PLAIN_FILE_FORMATS.get(self.file_type, self.file_type)
127 127 file_name = FILE_FILEFORMAT.format(image_name)
128 128
129 129 if file_exists(file_name):
130 130 image = file_name
131 131 else:
132 132 image = FILE_STUB_IMAGE
133 133
134 134 w, h = get_static_dimensions(image)
135 135
136 136 return ABSTRACT_FORMAT_VIEW.format(self.file.url, static(image), w, h)
137 137
138 138
139 139 class VideoViewer(AbstractViewer):
140 140 @staticmethod
141 141 def supports(file_type):
142 142 return file_type in FILE_TYPES_VIDEO
143 143
144 144 def get_format_view(self):
145 145 return VIDEO_FORMAT_VIEW.format(self.file.url)
146 146
147 147
148 148 class AudioViewer(AbstractViewer):
149 149 @staticmethod
150 150 def supports(file_type):
151 151 return file_type in FILE_TYPES_AUDIO
152 152
153 153 def get_format_view(self):
154 154 return AUDIO_FORMAT_VIEW.format(self.file.url)
155 155
156 156
157 157 class SvgViewer(AbstractViewer):
158 158 @staticmethod
159 159 def supports(file_type):
160 160 return file_type == FILE_TYPE_SVG
161 161
162 162 def get_format_view(self):
163 163 return SVG_FORMAT_VIEW.format(self.file.url, self.file.url)
164 164
165 165
166 166 class ImageViewer(AbstractViewer):
167 167 @staticmethod
168 168 def supports(file_type):
169 169 return file_type in FILE_TYPES_IMAGE
170 170
171 171 def get_format_view(self):
172 172 metadata = '{}, {}'.format(self.file.name.split('.')[-1],
173 173 filesizeformat(self.file.size))
174 174
175 175 try:
176 176 width, height = get_image_dimensions(self.file.path)
177 177 except Exception:
178 178 # If the image is a decompression bomb, treat it as just a regular
179 179 # file
180 180 return super().get_format_view()
181 181
182 182 preview_path = self.file.path.replace('.', '.200x150.')
183 183 pre_width, pre_height = get_image_dimensions(preview_path)
184 184
185 185 split = self.file.url.rsplit('.', 1)
186 186 w, h = 200, 150
187 187 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
188 188
189 189 return IMAGE_FORMAT_VIEW.format(CSS_CLASS_THUMB,
190 190 thumb_url,
191 191 self.hash,
192 192 str(pre_width),
193 193 str(pre_height), str(width), str(height),
194 194 full=self.file.url, image_meta=metadata)
195 195
196 196
197 197 class UrlViewer(AbstractViewer):
198 198 @staticmethod
199 199 def supports(file_type):
200 200 return file_type is None
201 201
202 202 def get_view(self):
203 203 return URL_VIEW.format(self.get_format_view(), get_domain(self.url))
204 204
205 205 def get_format_view(self):
206 206 protocol = self.url.split(':')[0]
207 207
208 208 domain = get_domain(self.url)
209 209
210 210 if protocol in URL_PROTOCOLS:
211 211 url_image_name = URL_PROTOCOLS.get(protocol)
212 212 elif domain:
213 213 url_image_name = self._find_image_for_domains(domain) or FILE_STUB_URL
214 214 else:
215 215 url_image_name = FILE_STUB_URL
216 216
217 217 image_path = 'images/{}.png'.format(url_image_name)
218 218 image = static(image_path)
219 219 w, h = get_static_dimensions(image_path)
220 220
221 221 return URL_FORMAT_VIEW.format(self.url, image, w, h)
222 222
223 223 @cached_result()
224 224 def _find_image_for_domains(self, domain):
225 225 """
226 226 Searches for the domain image for every domain level except top.
227 227 E.g. for l3.example.co.uk it will search for l3.example.co.uk, then
228 228 example.co.uk, then co.uk
229 229 """
230 230 levels = domain.split('.')
231 231 while len(levels) > 1:
232 232 domain = '.'.join(levels)
233 233
234 234 filename = 'images/domains/{}.png'.format(domain)
235 235 if file_exists(filename):
236 236 return 'domains/' + domain
237 237 else:
238 238 del levels[0]
239 239
General Comments 0
You need to be logged in to leave comments. Login now