##// END OF EJS Templates
Added image aliases to upload the same images (like "fake" or "gtfo")
neko259 -
r1500:9178427e default
parent child Browse files
Show More
@@ -0,0 +1,27 b''
1 from boards.abstracts.settingsmanager import SessionSettingsManager
2 from boards.models import PostImage
3
4 class AttachmentAlias:
5 def get_image(alias):
6 pass
7
8
9 class SessionAttachmentAlias(AttachmentAlias):
10 def __init__(self, session):
11 self.session = session
12
13 def get_image(self, alias):
14 settings_manager = SessionSettingsManager(self.session)
15 return settings_manager.get_image_by_alias(alias)
16
17
18 class ModelAttachmentAlias(AttachmentAlias):
19 def get_image(self, alias):
20 return PostImage.objects.filter(alias=alias).first()
21
22
23 def get_image_by_alias(alias, session):
24 image = SessionAttachmentAlias(session).get_image(alias) or ModelAttachmentAlias().get_image(alias)
25
26 if image is not None:
27 return image
@@ -0,0 +1,24 b''
1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
3
4 from django.db import migrations, models
5
6
7 class Migration(migrations.Migration):
8
9 dependencies = [
10 ('boards', '0040_thread_monochrome'),
11 ]
12
13 operations = [
14 migrations.AddField(
15 model_name='attachment',
16 name='original_filename',
17 field=models.TextField(null=True),
18 ),
19 migrations.AddField(
20 model_name='postimage',
21 name='original_filename',
22 field=models.TextField(null=True),
23 ),
24 ]
@@ -0,0 +1,28 b''
1 # -*- coding: utf-8 -*-
2 # Generated by Django 1.9.5 on 2016-04-22 07:53
3 from __future__ import unicode_literals
4
5 from django.db import migrations, models
6
7
8 class Migration(migrations.Migration):
9
10 dependencies = [
11 ('boards', '0041_auto_20160124_2341'),
12 ]
13
14 operations = [
15 migrations.RemoveField(
16 model_name='attachment',
17 name='original_filename',
18 ),
19 migrations.RemoveField(
20 model_name='postimage',
21 name='original_filename',
22 ),
23 migrations.AddField(
24 model_name='postimage',
25 name='alias',
26 field=models.TextField(blank=True, null=True, unique=True),
27 ),
28 ]
@@ -19,6 +19,7 b" SETTING_USERNAME = 'username'"
19 SETTING_LAST_NOTIFICATION_ID = 'last_notification'
19 SETTING_LAST_NOTIFICATION_ID = 'last_notification'
20 SETTING_IMAGE_VIEWER = 'image_viewer'
20 SETTING_IMAGE_VIEWER = 'image_viewer'
21 SETTING_TRIPCODE = 'tripcode'
21 SETTING_TRIPCODE = 'tripcode'
22 SETTING_IMAGES = 'images_aliases'
22
23
23 DEFAULT_THEME = 'md'
24 DEFAULT_THEME = 'md'
24
25
@@ -153,6 +154,17 b' class SettingsManager:'
153 names = set(name.strip() for name in names)
154 names = set(name.strip() for name in names)
154 return names
155 return names
155
156
157 def get_image_by_alias(self, alias):
158 images = self.get_setting(SETTING_IMAGES)
159 if images is not None and len(images) > 0:
160 return images.get(alias)
161
162 def add_image_alias(self, alias, image):
163 images = self.get_setting(SETTING_IMAGES)
164 if images is None:
165 images = dict()
166 images.put(alias, image)
167
156
168
157 class SessionSettingsManager(SettingsManager):
169 class SessionSettingsManager(SettingsManager):
158 """
170 """
@@ -1,16 +1,17 b''
1 from django.contrib import admin
1 from django.contrib import admin
2 from boards.models import Post, Tag, Ban, Thread, Banner
3 from django.utils.translation import ugettext_lazy as _
2 from django.utils.translation import ugettext_lazy as _
3 from django.core.urlresolvers import reverse
4 from boards.models import Post, Tag, Ban, Thread, Banner, PostImage
4
5
5
6
6 @admin.register(Post)
7 @admin.register(Post)
7 class PostAdmin(admin.ModelAdmin):
8 class PostAdmin(admin.ModelAdmin):
8
9
9 list_display = ('id', 'title', 'text', 'poster_ip')
10 list_display = ('id', 'title', 'text', 'poster_ip', 'linked_images')
10 list_filter = ('pub_time',)
11 list_filter = ('pub_time',)
11 search_fields = ('id', 'title', 'text', 'poster_ip')
12 search_fields = ('id', 'title', 'text', 'poster_ip')
12 exclude = ('referenced_posts', 'refmap')
13 exclude = ('referenced_posts', 'refmap')
13 readonly_fields = ('poster_ip', 'threads', 'thread', 'images',
14 readonly_fields = ('poster_ip', 'threads', 'thread', 'linked_images',
14 'attachments', 'uid', 'url', 'pub_time', 'opening')
15 'attachments', 'uid', 'url', 'pub_time', 'opening')
15
16
16 def ban_poster(self, request, queryset):
17 def ban_poster(self, request, queryset):
@@ -35,6 +36,12 b' class PostAdmin(admin.ModelAdmin):'
35 posts.update(hidden=True)
36 posts.update(hidden=True)
36 self.message_user(request, _('{} posters were banned, {} messages were hidden').format(bans, hidden))
37 self.message_user(request, _('{} posters were banned, {} messages were hidden').format(bans, hidden))
37
38
39 def linked_images(self, obj: Post):
40 images = obj.images.all()
41 image_urls = ['<a href="{}">{}</a>'.format(reverse('admin:%s_%s_change' %(image._meta.app_label, image._meta.model_name), args=[image.id]), image.hash) for image in images]
42 return ', '.join(image_urls)
43 linked_images.allow_tags = True
44
38
45
39 actions = ['ban_poster', 'ban_with_hiding']
46 actions = ['ban_poster', 'ban_with_hiding']
40
47
@@ -97,3 +104,8 b' class BanAdmin(admin.ModelAdmin):'
97 @admin.register(Banner)
104 @admin.register(Banner)
98 class BannerAdmin(admin.ModelAdmin):
105 class BannerAdmin(admin.ModelAdmin):
99 list_display = ('title', 'text')
106 list_display = ('title', 'text')
107
108
109 @admin.register(PostImage)
110 class PostImageAdmin(admin.ModelAdmin):
111 search_fields = ('alias',)
@@ -13,6 +13,7 b' from django.utils.translation import uge'
13 from django.utils import timezone
13 from django.utils import timezone
14
14
15 from boards.abstracts.settingsmanager import get_settings_manager
15 from boards.abstracts.settingsmanager import get_settings_manager
16 from boards.abstracts.attachment_alias import get_image_by_alias
16 from boards.mdx_neboard import formatters
17 from boards.mdx_neboard import formatters
17 from boards.models.attachment.downloaders import Downloader
18 from boards.models.attachment.downloaders import Downloader
18 from boards.models.post import TITLE_MAX_LENGTH
19 from boards.models.post import TITLE_MAX_LENGTH
@@ -183,6 +184,7 b' class PostForm(NeboardForm):'
183
184
184 session = None
185 session = None
185 need_to_ban = False
186 need_to_ban = False
187 image = None
186
188
187 def _update_file_extension(self, file):
189 def _update_file_extension(self, file):
188 if file:
190 if file:
@@ -229,13 +231,20 b' class PostForm(NeboardForm):'
229 url = self.cleaned_data['file_url']
231 url = self.cleaned_data['file_url']
230
232
231 file = None
233 file = None
234
232 if url:
235 if url:
233 file = self._get_file_from_url(url)
236 file = get_image_by_alias(url, self.session)
237 self.image = file
234
238
235 if not file:
239 if file is not None:
236 raise forms.ValidationError(_('Invalid URL'))
240 return
237 else:
241
238 validate_file_size(file.size)
242 if file is None:
243 file = self._get_file_from_url(url)
244 if not file:
245 raise forms.ValidationError(_('Invalid URL'))
246 else:
247 validate_file_size(file.size)
239 self._update_file_extension(file)
248 self._update_file_extension(file)
240
249
241 return file
250 return file
@@ -312,11 +321,18 b' class PostForm(NeboardForm):'
312 else:
321 else:
313 return title
322 return title
314
323
324 def get_images(self):
325 if self.image:
326 return [self.image]
327 else:
328 return []
329
315 def _clean_text_file(self):
330 def _clean_text_file(self):
316 text = self.cleaned_data.get('text')
331 text = self.cleaned_data.get('text')
317 file = self.get_file()
332 file = self.get_file()
333 images = self.get_images()
318
334
319 if (not text) and (not file):
335 if (not text) and (not file) and len(images) == 0:
320 error_message = _('Either text or file must be entered.')
336 error_message = _('Either text or file must be entered.')
321 self._errors['text'] = self.error_class([error_message])
337 self._errors['text'] = self.error_class([error_message])
322
338
@@ -67,3 +67,4 b' class YouTubeDownloader(Downloader):'
67 @staticmethod
67 @staticmethod
68 def handles(url: str) -> bool:
68 def handles(url: str) -> bool:
69 return YOUTUBE_URL.match(url)
69 return YOUTUBE_URL.match(url)
70
@@ -56,6 +56,7 b' class PostImage(models.Model, Viewable):'
56 preview_width_field='pre_width',
56 preview_width_field='pre_width',
57 preview_height_field='pre_height')
57 preview_height_field='pre_height')
58 hash = models.CharField(max_length=HASH_LENGTH)
58 hash = models.CharField(max_length=HASH_LENGTH)
59 alias = models.TextField(unique=True, null=True, blank=True)
59
60
60 def save(self, *args, **kwargs):
61 def save(self, *args, **kwargs):
61 """
62 """
@@ -31,7 +31,7 b' class PostManager(models.Manager):'
31 @transaction.atomic
31 @transaction.atomic
32 def create_post(self, title: str, text: str, file=None, thread=None,
32 def create_post(self, title: str, text: str, file=None, thread=None,
33 ip=NO_IP, tags: list=None, opening_posts: list=None,
33 ip=NO_IP, tags: list=None, opening_posts: list=None,
34 tripcode='', monochrome=False):
34 tripcode='', monochrome=False, images=[]):
35 """
35 """
36 Creates new post
36 Creates new post
37 """
37 """
@@ -87,6 +87,8 b' class PostManager(models.Manager):'
87 post.images.add(PostImage.objects.create_with_hash(file))
87 post.images.add(PostImage.objects.create_with_hash(file))
88 else:
88 else:
89 post.attachments.add(Attachment.objects.create_with_hash(file))
89 post.attachments.add(Attachment.objects.create_with_hash(file))
90 for image in images:
91 post.images.add(image)
90
92
91 post.connect_threads(opening_posts)
93 post.connect_threads(opening_posts)
92
94
@@ -24,6 +24,10 b''
24 {% else %}
24 {% else %}
25 <p>{% trans 'No hidden tags.' %}</p>
25 <p>{% trans 'No hidden tags.' %}</p>
26 {% endif %}
26 {% endif %}
27
28 {% for image in image_aliases %}
29 {{ image.alias }}: <img src="{{ image.image.url_200x150 }}" /> <br />
30 {% endfor %}
27 </div>
31 </div>
28
32
29 <div class="post-form-w">
33 <div class="post-form-w">
@@ -138,6 +138,7 b' class AllThreadsView(PostMixin, FileUplo'
138 text = data[FORM_TEXT]
138 text = data[FORM_TEXT]
139 file = form.get_file()
139 file = form.get_file()
140 threads = data[FORM_THREADS]
140 threads = data[FORM_THREADS]
141 images = form.get_images()
141
142
142 text = self._remove_invalid_links(text)
143 text = self._remove_invalid_links(text)
143
144
@@ -147,7 +148,7 b' class AllThreadsView(PostMixin, FileUplo'
147 post = Post.objects.create_post(title=title, text=text, file=file,
148 post = Post.objects.create_post(title=title, text=text, file=file,
148 ip=ip, tags=tags, opening_posts=threads,
149 ip=ip, tags=tags, opening_posts=threads,
149 tripcode=form.get_tripcode(),
150 tripcode=form.get_tripcode(),
150 monochrome=monochrome)
151 monochrome=monochrome, images=images)
151
152
152 # This is required to update the threads to which posts we have replied
153 # This is required to update the threads to which posts we have replied
153 # when creating this one
154 # when creating this one
@@ -8,6 +8,7 b' from boards.middlewares import SESSION_T'
8 from boards.views.base import BaseBoardView, CONTEXT_FORM
8 from boards.views.base import BaseBoardView, CONTEXT_FORM
9 from boards.forms import SettingsForm, PlainErrorList
9 from boards.forms import SettingsForm, PlainErrorList
10 from boards import settings
10 from boards import settings
11 from boards.models import PostImage
11
12
12 FORM_THEME = 'theme'
13 FORM_THEME = 'theme'
13 FORM_USERNAME = 'username'
14 FORM_USERNAME = 'username'
@@ -15,6 +16,7 b" FORM_TIMEZONE = 'timezone'"
15 FORM_IMAGE_VIEWER = 'image_viewer'
16 FORM_IMAGE_VIEWER = 'image_viewer'
16
17
17 CONTEXT_HIDDEN_TAGS = 'hidden_tags'
18 CONTEXT_HIDDEN_TAGS = 'hidden_tags'
19 CONTEXT_IMAGE_ALIASES = 'image_aliases'
18
20
19 TEMPLATE = 'boards/settings.html'
21 TEMPLATE = 'boards/settings.html'
20
22
@@ -41,6 +43,7 b' class SettingsView(BaseBoardView):'
41
43
42 params[CONTEXT_FORM] = form
44 params[CONTEXT_FORM] = form
43 params[CONTEXT_HIDDEN_TAGS] = settings_manager.get_hidden_tags()
45 params[CONTEXT_HIDDEN_TAGS] = settings_manager.get_hidden_tags()
46 params[CONTEXT_IMAGE_ALIASES] = PostImage.objects.exclude(alias='').exclude(alias=None)
44
47
45 return render(request, TEMPLATE, params)
48 return render(request, TEMPLATE, params)
46
49
@@ -129,6 +129,7 b' class ThreadView(BaseBoardView, PostMixi'
129 text = data[FORM_TEXT]
129 text = data[FORM_TEXT]
130 file = form.get_file()
130 file = form.get_file()
131 threads = data[FORM_THREADS]
131 threads = data[FORM_THREADS]
132 images = form.get_images()
132
133
133 text = self._remove_invalid_links(text)
134 text = self._remove_invalid_links(text)
134
135
@@ -137,7 +138,8 b' class ThreadView(BaseBoardView, PostMixi'
137 post = Post.objects.create_post(title=title, text=text, file=file,
138 post = Post.objects.create_post(title=title, text=text, file=file,
138 thread=post_thread, ip=ip,
139 thread=post_thread, ip=ip,
139 opening_posts=threads,
140 opening_posts=threads,
140 tripcode=form.get_tripcode())
141 tripcode=form.get_tripcode(),
142 images=images)
141 post.notify_clients()
143 post.notify_clients()
142
144
143 if html_response:
145 if html_response:
General Comments 0
You need to be logged in to leave comments. Login now