##// END OF EJS Templates
Fixed posting a message without sticker
neko259 -
r1938:42e6fbb6 default
parent child Browse files
Show More
@@ -1,168 +1,171 b''
1 1 from itertools import zip_longest
2 2
3 3 import boards
4 4 from boards.models import STATUS_ARCHIVE
5 5 from django.core.files.images import get_image_dimensions
6 6 from django.db import models
7 7
8 8 from boards import utils
9 9 from boards.models.attachment.viewers import get_viewers, AbstractViewer, \
10 10 FILE_TYPES_IMAGE
11 11 from boards.utils import get_upload_filename, get_extension, cached_result, \
12 12 get_file_mimetype
13 13
14 14
15 15 class AttachmentManager(models.Manager):
16 16 def create_with_hash(self, file):
17 17 file_hash = utils.get_file_hash(file)
18 18 attachment = self.get_existing_duplicate(file_hash, file)
19 19 if not attachment:
20 20 file_type = get_file_mimetype(file)
21 21 attachment = self.create(file=file, mimetype=file_type,
22 22 hash=file_hash)
23 23
24 24 return attachment
25 25
26 26 def create_from_url(self, url):
27 27 existing = self.filter(url=url)
28 28 if len(existing) > 0:
29 29 attachment = existing[0]
30 30 else:
31 31 attachment = self.create(url=url)
32 32 return attachment
33 33
34 34 def get_random_images(self, count, tags=None):
35 35 images = self.filter(mimetype__in=FILE_TYPES_IMAGE).exclude(
36 36 attachment_posts__thread__status=STATUS_ARCHIVE)
37 37 if tags is not None:
38 38 images = images.filter(attachment_posts__threads__tags__in=tags)
39 39 return images.order_by('?')[:count]
40 40
41 41 def get_existing_duplicate(self, file_hash, file):
42 42 """
43 43 Gets an attachment with the same file if one exists.
44 44 """
45 45 existing = self.filter(hash=file_hash)
46 46 attachment = None
47 47 for existing_attachment in existing:
48 48 existing_file = existing_attachment.file
49 49
50 50 file_chunks = file.chunks()
51 51 existing_file_chunks = existing_file.chunks()
52 52
53 53 if self._compare_chunks(file_chunks, existing_file_chunks):
54 54 attachment = existing_attachment
55 55 return attachment
56 56
57 57 def get_by_alias(self, name):
58 return AttachmentSticker.objects.get(name=name).attachment
58 try:
59 return AttachmentSticker.objects.get(name=name).attachment
60 except AttachmentSticker.DoesNotExist:
61 return None
59 62
60 63 def _compare_chunks(self, chunks1, chunks2):
61 64 """
62 65 Compares 2 chunks of different sizes (e.g. first chunk array contains
63 66 all data in 1 chunk, and other one -- in a multiple of smaller ones.
64 67 """
65 68 equal = True
66 69
67 70 position1 = 0
68 71 position2 = 0
69 72 chunk1 = None
70 73 chunk2 = None
71 74 chunk1ended = False
72 75 chunk2ended = False
73 76 while True:
74 77 if not chunk1 or len(chunk1) <= position1:
75 78 try:
76 79 chunk1 = chunks1.__next__()
77 80 position1 = 0
78 81 except StopIteration:
79 82 chunk1ended = True
80 83 if not chunk2 or len(chunk2) <= position2:
81 84 try:
82 85 chunk2 = chunks2.__next__()
83 86 position2 = 0
84 87 except StopIteration:
85 88 chunk2ended = True
86 89
87 90 if chunk1ended and chunk2ended:
88 91 # Same size chunksm checked for equality previously
89 92 break
90 93 elif chunk1ended or chunk2ended:
91 94 # Different size chunks, not equal
92 95 equal = False
93 96 break
94 97 elif chunk1[position1] != chunk2[position2]:
95 98 # Different bytes, not equal
96 99 equal = False
97 100 break
98 101 else:
99 102 position1 += 1
100 103 position2 += 1
101 104 return equal
102 105
103 106
104 107 class Attachment(models.Model):
105 108 objects = AttachmentManager()
106 109
107 110 class Meta:
108 111 app_label = 'boards'
109 112 ordering = ('id',)
110 113
111 114 file = models.FileField(upload_to=get_upload_filename, null=True)
112 115 mimetype = models.CharField(max_length=200, null=True)
113 116 hash = models.CharField(max_length=36, null=True)
114 117 url = models.TextField(blank=True, default='')
115 118
116 119 def get_view(self):
117 120 file_viewer = None
118 121 for viewer in get_viewers():
119 122 if viewer.supports(self.mimetype):
120 123 file_viewer = viewer
121 124 break
122 125 if file_viewer is None:
123 126 file_viewer = AbstractViewer
124 127
125 128 return file_viewer(self.file, self.mimetype, self.hash, self.url).get_view()
126 129
127 130 def __str__(self):
128 131 return self.url or self.file.url
129 132
130 133 def get_random_associated_post(self):
131 134 posts = boards.models.Post.objects.filter(attachments__in=[self])
132 135 return posts.order_by('?').first()
133 136
134 137 @cached_result()
135 138 def get_size(self):
136 139 if self.file:
137 140 if self.mimetype in FILE_TYPES_IMAGE:
138 141 return get_image_dimensions(self.file)
139 142 else:
140 143 return 200, 150
141 144
142 145 def get_thumb_url(self):
143 146 split = self.file.url.rsplit('.', 1)
144 147 w, h = 200, 150
145 148 return '%s.%sx%s.%s' % (split[0], w, h, split[1])
146 149
147 150 @cached_result()
148 151 def get_preview_size(self):
149 152 size = 200, 150
150 153 if self.mimetype in FILE_TYPES_IMAGE:
151 154 preview_path = self.file.path.replace('.', '.200x150.')
152 155 try:
153 156 size = get_image_dimensions(preview_path)
154 157 except Exception:
155 158 pass
156 159
157 160 return size
158 161
159 162 def is_internal(self):
160 163 return self.url is None or len(self.url) == 0
161 164
162 165
163 166 class AttachmentSticker(models.Model):
164 167 attachment = models.ForeignKey('Attachment')
165 168 name = models.TextField(unique=True)
166 169
167 170 def __str__(self):
168 171 return self.name
General Comments 0
You need to be logged in to leave comments. Login now