import re from django.contrib.staticfiles import finders from django.contrib.staticfiles.templatetags.staticfiles import static from django.core.files.images import get_image_dimensions from django.template.defaultfilters import filesizeformat REGEX_DOMAIN = re.compile(r'(\w+\.)*(\w+\.\w+)') FILE_STUB_IMAGE = 'images/file.png' FILE_STUB_URL = 'url' FILE_TYPES_VIDEO = ( 'webm', 'mp4', 'mpeg', 'ogv', ) FILE_TYPE_SVG = 'svg' FILE_TYPES_AUDIO = ( 'ogg', 'mp3', 'opus', ) FILE_TYPES_IMAGE = ( 'jpeg', 'jpg', 'png', 'bmp', 'gif', ) PLAIN_FILE_FORMATS = { 'pdf': 'pdf', 'djvu': 'djvu', 'txt': 'txt', 'tex': 'tex', 'xcf': 'xcf', 'zip': 'archive', 'tar': 'archive', 'gz': 'archive', } URL_PROTOCOLS = { 'magnet': 'magnet', } CSS_CLASS_IMAGE = 'image' CSS_CLASS_THUMB = 'thumb' def get_viewers(): return AbstractViewer.__subclasses__() def get_static_dimensions(filename): file_path = finders.find(filename) return get_image_dimensions(file_path) # TODO Move this to utils def file_exists(filename): return finders.find(filename) is not None class AbstractViewer: def __init__(self, file, file_type, hash, url): self.file = file self.file_type = file_type self.hash = hash self.url = url @staticmethod def supports(file_type): return True def get_view(self): return '
'\ '{}'\ '
{}, {}
'\ '
'.format(self.get_format_view(), self.file.url, self.file_type, filesizeformat(self.file.size)) def get_format_view(self): if self.file_type in PLAIN_FILE_FORMATS: image = 'images/fileformats/{}.png'.format( PLAIN_FILE_FORMATS[self.file_type]) else: image = FILE_STUB_IMAGE w, h = get_static_dimensions(image) return ''\ ''\ ''.format(self.file.url, static(image), w, h) class VideoViewer(AbstractViewer): @staticmethod def supports(file_type): return file_type in FILE_TYPES_VIDEO def get_format_view(self): return ''\ .format(self.file.url) class AudioViewer(AbstractViewer): @staticmethod def supports(file_type): return file_type in FILE_TYPES_AUDIO def get_format_view(self): return ''.format(self.file.url) class SvgViewer(AbstractViewer): @staticmethod def supports(file_type): return file_type == FILE_TYPE_SVG def get_format_view(self): return ''\ ''\ ''.format(self.file.url, self.file.url) class ImageViewer(AbstractViewer): @staticmethod def supports(file_type): return file_type in FILE_TYPES_IMAGE def get_format_view(self): metadata = '{}, {}'.format(self.file.name.split('.')[-1], filesizeformat(self.file.size)) width, height = get_image_dimensions(self.file.file) preview_path = self.file.path.replace('.', '.200x150.') pre_width, pre_height = get_image_dimensions(preview_path) split = self.file.url.rsplit('.', 1) w, h = 200, 150 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1]) return '' \ '{}' \ '' \ .format(CSS_CLASS_THUMB, thumb_url, self.hash, str(pre_width), str(pre_height), str(width), str(height), full=self.file.url, image_meta=metadata) class UrlViewer(AbstractViewer): @staticmethod def supports(file_type): return file_type is None def get_view(self): return '
' \ '{}' \ '
'.format(self.get_format_view()) def get_format_view(self): protocol = self.url.split('://')[0] full_domain = self.url.split('/')[2] domain = REGEX_DOMAIN.search(full_domain).group(2) if protocol in URL_PROTOCOLS: url_image_name = URL_PROTOCOLS.get(protocol) else: filename = 'images/domains/{}.png'.format(domain) if file_exists(filename): url_image_name = 'domains/' + domain else: url_image_name = FILE_STUB_URL image_path = 'images/{}.png'.format(url_image_name) image = static(image_path) w, h = get_static_dimensions(image_path) return '' \ '' \ ''.format(self.url, image, w, h)