mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 12:33:40 +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