##// END OF EJS Templates
Refactored attachment viewers to store view htmls as constants
Refactored attachment viewers to store view htmls as constants

File last commit:

r1828:fb6d2612 default
r1828:fb6d2612 default
Show More
viewers.py
238 lines | 6.5 KiB | text/x-python | PythonLexer
neko259
Added an image for wikipedia domain. Retrieve only 2nd level domain for the image, ignoring the 3rd level
r1715 import re
neko259
Use real image stub sizes, not 200x150
r1684
neko259
Decompression bomb protection in image viewing
r1820 from PIL import Image
neko259
Move attachment domains list to a separate module
r1716 from django.contrib.staticfiles import finders
from django.contrib.staticfiles.templatetags.staticfiles import static
neko259
Store images as regular attachments instead of separate model
r1590 from django.core.files.images import get_image_dimensions
neko259
Added support for different attachment types
r1273 from django.template.defaultfilters import filesizeformat
neko259
Image search in every image view, using context menu
r1812 from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _, ungettext_lazy
neko259
Move attachment domains list to a separate module
r1716
neko259
Search for image for every domain level starting from the lowest one. Cache this into memcached
r1772 from boards.utils import get_domain, cached_result
neko259
Image search in every image view, using context menu
r1812 from boards import settings
neko259
Added support for different attachment types
r1273
neko259
Added an image for wikipedia domain. Retrieve only 2nd level domain for the image, ignoring the 3rd level
r1715
neko259
Support audio viewer
r1279 FILE_STUB_IMAGE = 'images/file.png'
neko259
Different images for different URL protocols
r1677 FILE_STUB_URL = 'url'
neko259
Added image for midi/mid file format. Store only common file formats (e.g. same image for different formats) in the code, otherwise get the image file directly from the statics
r1779 FILE_FILEFORMAT = 'images/fileformats/{}.png'
neko259
Support audio viewer
r1279
neko259
Added statistics management command
r1727
neko259
Video formats are not limited to webm
r1307 FILE_TYPES_VIDEO = (
'webm',
'mp4',
neko259
Treat .mpeg files as video
r1342 'mpeg',
neko259
View ogv format as video
r1493 'ogv',
neko259
Video formats are not limited to webm
r1307 )
neko259
Added basic SVG support
r1284 FILE_TYPE_SVG = 'svg'
neko259
Support audio viewer
r1279 FILE_TYPES_AUDIO = (
'ogg',
'mp3',
neko259
Opus is an audio format too
r1339 'opus',
neko259
Support audio viewer
r1279 )
neko259
Store images as regular attachments instead of separate model
r1590 FILE_TYPES_IMAGE = (
'jpeg',
'jpg',
'png',
'bmp',
'gif',
)
neko259
Support audio viewer
r1279
neko259
Added images for different file formats
r1326 PLAIN_FILE_FORMATS = {
neko259
Added image for archive file format
r1713 'zip': 'archive',
'tar': 'archive',
'gz': 'archive',
neko259
Added image for midi/mid file format. Store only common file formats (e.g. same image for different formats) in the code, otherwise get the image file directly from the statics
r1779 'mid' : 'midi',
neko259
Added images for different file formats
r1326 }
neko259
Different images for different URL protocols
r1677 URL_PROTOCOLS = {
'magnet': 'magnet',
}
neko259
Store images as regular attachments instead of separate model
r1590 CSS_CLASS_IMAGE = 'image'
CSS_CLASS_THUMB = 'thumb'
neko259
Refactored attachment viewers to store view htmls as constants
r1828 ABSTRACT_VIEW = '<div class="image">'\
'{}'\
'<div class="image-metadata"><a href="{}" download >{}, {}</a>'\
' <a class="file-menu" href="#" data-type="{}" data-search-url="{}" data-filename="{}">🔍 </a></div>'\
'</div>'
URL_VIEW = '<div class="image">' \
'{}' \
'<div class="image-metadata">{}</div>' \
'</div>'
ABSTRACT_FORMAT_VIEW = '<a href="{}">'\
'<img class="url-image" src="{}" width="{}" height="{}"/>'\
'</a>'
VIDEO_FORMAT_VIEW = '<video width="200" height="150" controls src="{}"></video>'
AUDIO_FORMAT_VIEW = '<audio controls src="{}"></audio>'
IMAGE_FORMAT_VIEW = '<a class="{}" href="{full}">' \
'<img class="post-image-preview"' \
' src="{}"' \
' alt="{}"' \
' width="{}"' \
' height="{}"' \
' data-width="{}"' \
' data-height="{}" />' \
'</a>'
SVG_FORMAT_VIEW = '<a class="thumb" href="{}">'\
'<img class="post-image-preview" width="200" height="150" src="{}" />'\
'</a>'
URL_FORMAT_VIEW = '<a href="{}">' \
'<img class="url-image" src="{}" width="{}" height="{}"/>' \
'</a>'
neko259
Added support for different attachment types
r1273
neko259
Autodetect attachment viewers by getting all abstract viewer subclasses
r1286 def get_viewers():
return AbstractViewer.__subclasses__()
neko259
Use real image stub sizes, not 200x150
r1684 def get_static_dimensions(filename):
file_path = finders.find(filename)
return get_image_dimensions(file_path)
neko259
Simplify adding new domain images. Not there is no separate dict, just searching a file by name from a static finder
r1718 # TODO Move this to utils
def file_exists(filename):
return finders.find(filename) is not None
neko259
Added support for different attachment types
r1273 class AbstractViewer:
neko259
Load URL if the file could not be loaded
r1660 def __init__(self, file, file_type, hash, url):
neko259
Added support for different attachment types
r1273 self.file = file
self.file_type = file_type
neko259
Fixed popup image preview
r1596 self.hash = hash
neko259
Load URL if the file could not be loaded
r1660 self.url = url
neko259
Added support for different attachment types
r1273
@staticmethod
def supports(file_type):
neko259
Support audio viewer
r1279 return True
neko259
Added support for different attachment types
r1273
def get_view(self):
neko259
Build file search menu on the JS side
r1817 search_host = settings.get('External', 'ImageSearchHost')
if search_host:
neko259
Remove backslash from image search host
r1821 if search_host.endswith('/'):
search_host = search_host[:-1]
neko259
Build file search menu on the JS side
r1817 search_url = search_host + self.file.url
else:
search_url = ''
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return ABSTRACT_VIEW.format(self.get_format_view(), self.file.url,
self.file_type, filesizeformat(self.file.size),
self.file_type, search_url, self.file.name)
neko259
Show file metadata for all attachments
r1300
def get_format_view(self):
neko259
Added image for midi/mid file format. Store only common file formats (e.g. same image for different formats) in the code, otherwise get the image file directly from the statics
r1779 image_name = PLAIN_FILE_FORMATS.get(self.file_type, self.file_type)
file_name = FILE_FILEFORMAT.format(image_name)
if file_exists(file_name):
image = file_name
neko259
Added images for different file formats
r1326 else:
image = FILE_STUB_IMAGE
neko259
Use real image stub sizes, not 200x150
r1684 w, h = get_static_dimensions(image)
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return ABSTRACT_FORMAT_VIEW.format(self.file.url, static(image), w, h)
neko259
Added support for different attachment types
r1273
neko259
Video formats are not limited to webm
r1307 class VideoViewer(AbstractViewer):
neko259
Added support for different attachment types
r1273 @staticmethod
def supports(file_type):
neko259
Video formats are not limited to webm
r1307 return file_type in FILE_TYPES_VIDEO
neko259
Added support for different attachment types
r1273
neko259
Show file metadata for all attachments
r1300 def get_format_view(self):
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return VIDEO_FORMAT_VIEW.format(self.file.url)
neko259
Added support for different attachment types
r1273
neko259
Support audio viewer
r1279
class AudioViewer(AbstractViewer):
@staticmethod
def supports(file_type):
return file_type in FILE_TYPES_AUDIO
neko259
Show file metadata for all attachments
r1300 def get_format_view(self):
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return AUDIO_FORMAT_VIEW.format(self.file.url)
neko259
Added basic SVG support
r1284
class SvgViewer(AbstractViewer):
@staticmethod
def supports(file_type):
return file_type == FILE_TYPE_SVG
neko259
Show file metadata for all attachments
r1300 def get_format_view(self):
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return SVG_FORMAT_VIEW.format(self.file.url, self.file.url)
neko259
Store images as regular attachments instead of separate model
r1590
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))
neko259
Decompression bomb protection in image viewing
r1820
try:
width, height = get_image_dimensions(self.file.path)
except Exception:
# If the image is a decompression bomb, treat it as just a regular
# file
return super().get_format_view()
neko259
Store images as regular attachments instead of separate model
r1590 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])
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return IMAGE_FORMAT_VIEW.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)
neko259
Store images as regular attachments instead of separate model
r1590
neko259
Load URL if the file could not be loaded
r1660
class UrlViewer(AbstractViewer):
@staticmethod
def supports(file_type):
return file_type is None
def get_view(self):
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return URL_VIEW.format(self.get_format_view(), get_domain(self.url))
neko259
Different images for different URL protocols
r1677
neko259
Load URL if the file could not be loaded
r1660 def get_format_view(self):
neko259
Fixed magnet link protocol detection
r1776 protocol = self.url.split(':')[0]
neko259
Show domain next to URL if available
r1765
domain = get_domain(self.url)
neko259
Added ability to add links to specific domains and show the domain logo as an image substitute
r1695
if protocol in URL_PROTOCOLS:
url_image_name = URL_PROTOCOLS.get(protocol)
neko259
Show domain next to URL if available
r1765 elif domain:
neko259
Search for image for every domain level starting from the lowest one. Cache this into memcached
r1772 url_image_name = self._find_image_for_domains(domain) or FILE_STUB_URL
neko259
Show domain next to URL if available
r1765 else:
url_image_name = FILE_STUB_URL
neko259
Added ability to add links to specific domains and show the domain logo as an image substitute
r1695
neko259
Simplify adding new domain images. Not there is no separate dict, just searching a file by name from a static finder
r1718 image_path = 'images/{}.png'.format(url_image_name)
image = static(image_path)
w, h = get_static_dimensions(image_path)
neko259
Use real image stub sizes, not 200x150
r1684
neko259
Refactored attachment viewers to store view htmls as constants
r1828 return URL_FORMAT_VIEW.format(self.url, image, w, h)
neko259
Show domain next to URL if available
r1765
neko259
Search for image for every domain level starting from the lowest one. Cache this into memcached
r1772 @cached_result()
def _find_image_for_domains(self, domain):
"""
Searches for the domain image for every domain level except top.
E.g. for l3.example.co.uk it will search for l3.example.co.uk, then
example.co.uk, then co.uk
"""
levels = domain.split('.')
while len(levels) > 1:
domain = '.'.join(levels)
neko259
Show domain next to URL if available
r1765
neko259
Search for image for every domain level starting from the lowest one. Cache this into memcached
r1772 filename = 'images/domains/{}.png'.format(domain)
if file_exists(filename):
return 'domains/' + domain
else:
del levels[0]
neko259
Show domain next to URL if available
r1765