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
from boards.models.attachment.domains import URL_DOMAINS
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)
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)
elif domain in URL_DOMAINS:
url_image_name = 'domains/' + URL_DOMAINS.get(domain)
else:
url_image_name = FILE_STUB_URL
image = static('images/' + url_image_name + '.png')
w, h = get_static_dimensions('images/' + url_image_name + '.png')
return '' \
'' \
''.format(self.url, image, w, h)