# HG changeset patch # User neko259 # Date 2016-10-08 15:17:52 # Node ID 80bdd1ce44c241e1cacba9dc5edee27d71b3a8e4 # Parent ed673873695f38941e78bb133e4631faddda138f Load URL if the file could not be loaded diff --git a/boards/forms.py b/boards/forms.py --- a/boards/forms.py +++ b/boards/forms.py @@ -69,6 +69,9 @@ MIMETYPE_EXTENSIONS = { } +logger = logging.getLogger('boards.forms') + + def get_timezones(): timezones = [] for tz in pytz.common_timezones: @@ -235,19 +238,24 @@ class PostForm(NeboardForm): file = None if url: - file = get_image_by_alias(url, self.session) - self.image = file + try: + file = get_image_by_alias(url, self.session) + self.image = file - if file is not None: - return + if file is not None: + return - if file is None: - file = self._get_file_from_url(url) - if not file: - raise forms.ValidationError(_('Invalid URL')) - else: - validate_file_size(file.size) - self._update_file_extension(file) + if file is None: + file = self._get_file_from_url(url) + if not file: + raise forms.ValidationError(_('Invalid URL')) + else: + validate_file_size(file.size) + self._update_file_extension(file) + except forms.ValidationError as e: + # Assume we will get the plain URL instead of a file and save it + logger.info('Error in forms: {}'.format(e)) + return url return file @@ -298,7 +306,6 @@ class PostForm(NeboardForm): self._validate_posting_speed() settings_manager.set_setting('confirmed_user', True) - return cleaned_data def get_file(self): @@ -307,7 +314,15 @@ class PostForm(NeboardForm): """ file = self.cleaned_data['file'] - return file or self.cleaned_data['file_url'] + if type(self.cleaned_data['file_url']) is not str: + file_url = self.cleaned_data['file_url'] + else: + file_url = None + return file or file_url + + def get_file_url(self): + if not self.get_file(): + return self.cleaned_data['file_url'] def get_tripcode(self): title = self.cleaned_data['title'] @@ -337,9 +352,10 @@ class PostForm(NeboardForm): def _clean_text_file(self): text = self.cleaned_data.get('text') file = self.get_file() + file_url = self.get_file_url() images = self.get_images() - if (not text) and (not file) and len(images) == 0: + if (not text) and (not file) and (not file_url) and len(images) == 0: error_message = _('Either text or file must be entered.') self._errors['text'] = self.error_class([error_message]) diff --git a/boards/models/attachment/__init__.py b/boards/models/attachment/__init__.py --- a/boards/models/attachment/__init__.py +++ b/boards/models/attachment/__init__.py @@ -23,6 +23,14 @@ class AttachmentManager(models.Manager): return attachment + def create_from_url(self, url): + existing = self.filter(url=url) + if len(existing) > 0: + attachment = existing[0] + else: + attachment = self.create(url=url) + return attachment + def get_random_images(self, count, tags=None): images = self.filter(mimetype__in=FILE_TYPES_IMAGE).exclude( attachment_posts__thread__status=STATUS_ARCHIVE) @@ -34,10 +42,11 @@ class AttachmentManager(models.Manager): class Attachment(models.Model): objects = AttachmentManager() - file = models.FileField(upload_to=get_upload_filename) - mimetype = models.CharField(max_length=50) - hash = models.CharField(max_length=36) + file = models.FileField(upload_to=get_upload_filename, null=True) + mimetype = models.CharField(max_length=50, null=True) + hash = models.CharField(max_length=36, null=True) alias = models.TextField(unique=True, null=True, blank=True) + url = models.TextField(null=True) def get_view(self): file_viewer = None @@ -48,10 +57,10 @@ class Attachment(models.Model): if file_viewer is None: file_viewer = AbstractViewer - return file_viewer(self.file, self.mimetype, self.hash).get_view() + return file_viewer(self.file, self.mimetype, self.hash, self.url).get_view() def __str__(self): - return self.file.url + return self.url or self.file.url def get_random_associated_post(self): posts = boards.models.Post.objects.filter(attachments__in=[self]) @@ -59,10 +68,11 @@ class Attachment(models.Model): @cached_result() def get_size(self): - if self.mimetype in FILE_TYPES_IMAGE: - return get_image_dimensions(self.file) - else: - return 200, 150 + if self.file: + if self.mimetype in FILE_TYPES_IMAGE: + return get_image_dimensions(self.file) + else: + return 200, 150 def get_thumb_url(self): split = self.file.url.rsplit('.', 1) diff --git a/boards/models/attachment/viewers.py b/boards/models/attachment/viewers.py --- a/boards/models/attachment/viewers.py +++ b/boards/models/attachment/viewers.py @@ -3,6 +3,7 @@ from django.template.defaultfilters impo from django.contrib.staticfiles.templatetags.staticfiles import static FILE_STUB_IMAGE = 'images/file.png' +FILE_STUB_URL = 'images/url.png' FILE_TYPES_VIDEO = ( 'webm', @@ -39,10 +40,11 @@ def get_viewers(): class AbstractViewer: - def __init__(self, file, file_type, hash): + 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): @@ -129,3 +131,17 @@ class ImageViewer(AbstractViewer): 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): + return '' \ + '' \ + ''.format(self.url, static(FILE_STUB_URL)) diff --git a/boards/models/post/manager.py b/boards/models/post/manager.py --- a/boards/models/post/manager.py +++ b/boards/models/post/manager.py @@ -28,7 +28,8 @@ class PostManager(models.Manager): @transaction.atomic def create_post(self, title: str, text: str, file=None, thread=None, ip=NO_IP, tags: list=None, opening_posts: list=None, - tripcode='', monochrome=False, images=[]): + tripcode='', monochrome=False, images=[], + file_url=None): """ Creates new post """ @@ -79,6 +80,8 @@ class PostManager(models.Manager): self._add_file_to_post(file, post) for image in images: post.attachments.add(image) + if file_url: + post.attachments.add(Attachment.objects.create_from_url(file_url)) post.connect_threads(opening_posts) post.set_global_id() diff --git a/boards/static/images/file.png b/boards/static/images/url.png copy from boards/static/images/file.png copy to boards/static/images/url.png index 82bdefe6ecf5166733a158ee930526796d87207a..2d2a5bb546299ddd7d0d76af9e7fc6c7d32e5a94 GIT binary patch literal 6724 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 a9{)ct&7D%cz^G>c0000