mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	Calculate has_* fields before saving Messages
Before saving a Message object, call update_calculated_fields() to set the has_attachment/has_image/has_link fields. Note that the pre_save hook we added here does not get called if you call bulk_create, hence the explicit call to update_calculated_fields() in do_send_messages(). (imported from commit 1d60ae5908ef186aa5ff1e39277dbb2b765e60d4)
This commit is contained in:
		@@ -376,6 +376,7 @@ def do_send_messages(messages):
 | 
			
		||||
        message['active_recipients'] = filter(lambda user_profile: user_profile.is_active,
 | 
			
		||||
                                              message['recipients'])
 | 
			
		||||
        message['message'].maybe_render_content(None)
 | 
			
		||||
        message['message'].update_calculated_fields()
 | 
			
		||||
 | 
			
		||||
    # Save the message receipts in the database
 | 
			
		||||
    user_message_flags = defaultdict(dict)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ from django.db import models
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.auth.models import AbstractBaseUser, UserManager, \
 | 
			
		||||
    PermissionsMixin
 | 
			
		||||
from django.dispatch import receiver
 | 
			
		||||
from zerver.lib.cache import cache_with_key, flush_user_profile, flush_realm, \
 | 
			
		||||
    user_profile_by_id_cache_key, user_profile_by_email_cache_key, \
 | 
			
		||||
    generic_bulk_cached_fetch, cache_set, flush_stream, \
 | 
			
		||||
@@ -15,13 +16,14 @@ from zerver.lib.avatar import gravatar_hash, get_avatar_url
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.contrib.sessions.models import Session
 | 
			
		||||
from zerver.lib.timestamp import datetime_to_timestamp
 | 
			
		||||
from django.db.models.signals import post_save, post_delete
 | 
			
		||||
from django.db.models.signals import pre_save, post_save, post_delete
 | 
			
		||||
from guardian.shortcuts import get_users_with_perms
 | 
			
		||||
import zlib
 | 
			
		||||
 | 
			
		||||
from bitfield import BitField
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
import pylibmc
 | 
			
		||||
import re
 | 
			
		||||
import ujson
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
@@ -935,6 +937,31 @@ class Message(models.Model):
 | 
			
		||||
                                   'website', 'ios', 'android')) or \
 | 
			
		||||
                                   ('desktop app' in sending_client)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def content_has_attachment(content):
 | 
			
		||||
        return '/user_uploads/' in content
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def content_has_image(content):
 | 
			
		||||
        return bool(re.search('/user_uploads/\S+\.(bmp|gif|jpg|jpeg|png|webp)', content, re.IGNORECASE))
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def content_has_link(content):
 | 
			
		||||
        return 'http://' in content or 'https://' in content or '/user_uploads' in content
 | 
			
		||||
 | 
			
		||||
    def update_calculated_fields(self):
 | 
			
		||||
        # TODO: rendered_content could also be considered a calculated field
 | 
			
		||||
        content = self.content
 | 
			
		||||
        self.has_attachment = bool(Message.content_has_attachment(content))
 | 
			
		||||
        self.has_image = bool(Message.content_has_image(content))
 | 
			
		||||
        self.has_link = bool(Message.content_has_link(content))
 | 
			
		||||
 | 
			
		||||
@receiver(pre_save, sender=Message)
 | 
			
		||||
def pre_save_message(sender, **kwargs):
 | 
			
		||||
    if kwargs['update_fields'] is None or "content" in kwargs['update_fields']:
 | 
			
		||||
        message = kwargs['instance']
 | 
			
		||||
        message.update_calculated_fields()
 | 
			
		||||
 | 
			
		||||
class UserMessage(models.Model):
 | 
			
		||||
    user_profile = models.ForeignKey(UserProfile)
 | 
			
		||||
    message = models.ForeignKey(Message)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ from django.db.models import Q
 | 
			
		||||
from sqlalchemy.sql import (
 | 
			
		||||
    and_, select, column, compiler
 | 
			
		||||
)
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
from zerver.lib import bugdown
 | 
			
		||||
from zerver.decorator import JsonableError
 | 
			
		||||
from zerver.lib.test_runner import slow
 | 
			
		||||
@@ -1277,6 +1278,25 @@ class StarTests(AuthedTestCase):
 | 
			
		||||
        self.assertEqual(sent_message.message.content, content)
 | 
			
		||||
        self.assertFalse(sent_message.flags.starred)
 | 
			
		||||
 | 
			
		||||
class AttachmentTest(TestCase):
 | 
			
		||||
    def test_basics(self):
 | 
			
		||||
        self.assertFalse(Message.content_has_attachment('whatever'))
 | 
			
		||||
        self.assertFalse(Message.content_has_attachment('yo http://foo.com'))
 | 
			
		||||
        self.assertTrue(Message.content_has_attachment('yo\n https://staging.zulip.com/user_uploads/'))
 | 
			
		||||
        self.assertTrue(Message.content_has_attachment('yo\n /user_uploads/1/wEAnI-PEmVmCjo15xxNaQbnj/photo-10.jpg foo'))
 | 
			
		||||
 | 
			
		||||
        self.assertFalse(Message.content_has_image('whatever'))
 | 
			
		||||
        self.assertFalse(Message.content_has_image('yo http://foo.com'))
 | 
			
		||||
        self.assertFalse(Message.content_has_image('yo\n /user_uploads/1/wEAnI-PEmVmCjo15xxNaQbnj/photo-10.pdf foo'))
 | 
			
		||||
        for ext in [".bmp", ".gif", ".jpg", "jpeg", ".png", ".webp", ".JPG"]:
 | 
			
		||||
            content = 'yo\n /user_uploads/1/wEAnI-PEmVmCjo15xxNaQbnj/photo-10.%s foo' % (ext,)
 | 
			
		||||
            self.assertTrue(Message.content_has_image(content))
 | 
			
		||||
 | 
			
		||||
        self.assertFalse(Message.content_has_link('whatever'))
 | 
			
		||||
        self.assertTrue(Message.content_has_link('yo\n http://foo.com'))
 | 
			
		||||
        self.assertTrue(Message.content_has_link('yo\n https://example.com?spam=1&eggs=2'))
 | 
			
		||||
        self.assertTrue(Message.content_has_link('yo /user_uploads/1/wEAnI-PEmVmCjo15xxNaQbnj/photo-10.pdf foo'))
 | 
			
		||||
 | 
			
		||||
class CheckMessageTest(AuthedTestCase):
 | 
			
		||||
    def test_basic_check_message_call(self):
 | 
			
		||||
        sender = get_user_profile_by_email('othello@zulip.com')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user