Show More
@@ -0,0 +1,54 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | # Generated by Django 1.11 on 2017-10-25 08:48 | |||
|
3 | from __future__ import unicode_literals | |||
|
4 | ||||
|
5 | from django.db import migrations, models | |||
|
6 | import django.db.models.deletion | |||
|
7 | ||||
|
8 | ||||
|
9 | class Migration(migrations.Migration): | |||
|
10 | ||||
|
11 | dependencies = [ | |||
|
12 | ('boards', '0065_attachmentsticker'), | |||
|
13 | ] | |||
|
14 | ||||
|
15 | def stickers_to_pack(apps, schema_editor): | |||
|
16 | AttachmentSticker = apps.get_model('boards', 'AttachmentSticker') | |||
|
17 | StickerPack = apps.get_model('boards', 'StickerPack') | |||
|
18 | ||||
|
19 | stickers = AttachmentSticker.objects.all() | |||
|
20 | if len(stickers) > 0: | |||
|
21 | stickerpack = StickerPack.objects.create(name='general') | |||
|
22 | for sticker in stickers: | |||
|
23 | sticker.stickerpack = stickerpack | |||
|
24 | if '/' in sticker.name: | |||
|
25 | sticker.name = sticker.name.split('/')[1] | |||
|
26 | sticker.save() | |||
|
27 | ||||
|
28 | operations = [ | |||
|
29 | migrations.CreateModel( | |||
|
30 | name='StickerPack', | |||
|
31 | fields=[ | |||
|
32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |||
|
33 | ('name', models.TextField(unique=True)), | |||
|
34 | ('tripcode', models.TextField(blank=True)), | |||
|
35 | ], | |||
|
36 | ), | |||
|
37 | migrations.AddField( | |||
|
38 | model_name='attachmentsticker', | |||
|
39 | name='stickerpack', | |||
|
40 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='boards.StickerPack', null=True), | |||
|
41 | preserve_default=False, | |||
|
42 | ), | |||
|
43 | migrations.AddField( | |||
|
44 | model_name='thread', | |||
|
45 | name='stickerpack', | |||
|
46 | field=models.BooleanField(default=False), | |||
|
47 | ), | |||
|
48 | migrations.RunPython(stickers_to_pack), | |||
|
49 | migrations.AlterField( | |||
|
50 | model_name='attachmentsticker', | |||
|
51 | name='stickerpack', | |||
|
52 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='boards.StickerPack', null=False), | |||
|
53 | ), | |||
|
54 | ] |
@@ -1,1 +1,4 b'' | |||||
|
1 | import re | |||
|
2 | ||||
1 | FILE_DIRECTORY = 'files/' |
|
3 | FILE_DIRECTORY = 'files/' | |
|
4 | REGEX_TAGS = re.compile(r'^[\w\s\d]+$', re.UNICODE) |
@@ -18,7 +18,8 b' class SessionStickerFactory(StickerFacto' | |||||
18 |
|
18 | |||
19 | class ModelStickerFactory(StickerFactory): |
|
19 | class ModelStickerFactory(StickerFactory): | |
20 | def get_image(self, alias): |
|
20 | def get_image(self, alias): | |
21 | return Attachment.objects.get_by_alias(alias) |
|
21 | if alias.count('/') == 1: | |
|
22 | return Attachment.objects.get_by_alias(alias) | |||
22 |
|
23 | |||
23 |
|
24 | |||
24 | def get_attachment_by_alias(alias, session): |
|
25 | def get_attachment_by_alias(alias, session): |
@@ -1,5 +1,6 b'' | |||||
1 | from boards.abstracts.sticker_factory import StickerFactory |
|
1 | from boards.abstracts.sticker_factory import StickerFactory | |
2 | from boards.models.attachment import FILE_TYPES_IMAGE, AttachmentSticker |
|
2 | from boards.models.attachment import FILE_TYPES_IMAGE, AttachmentSticker, \ | |
|
3 | StickerPack | |||
3 | from django.contrib import admin |
|
4 | from django.contrib import admin | |
4 | from django.utils.translation import ugettext_lazy as _ |
|
5 | from django.utils.translation import ugettext_lazy as _ | |
5 | from django.core.urlresolvers import reverse |
|
6 | from django.core.urlresolvers import reverse | |
@@ -166,6 +167,11 b' class AttachmentStickerAdmin(admin.Model' | |||||
166 | search_fields = ('name',) |
|
167 | search_fields = ('name',) | |
167 |
|
168 | |||
168 |
|
169 | |||
|
170 | @admin.register(StickerPack) | |||
|
171 | class StickerPackAdmin(admin.ModelAdmin): | |||
|
172 | search_fields = ('name',) | |||
|
173 | ||||
|
174 | ||||
169 | @admin.register(GlobalId) |
|
175 | @admin.register(GlobalId) | |
170 | class GlobalIdAdmin(admin.ModelAdmin): |
|
176 | class GlobalIdAdmin(admin.ModelAdmin): | |
171 | def is_linked(self, obj): |
|
177 | def is_linked(self, obj): |
@@ -2,7 +2,6 b' import hashlib' | |||||
2 | import logging |
|
2 | import logging | |
3 | import re |
|
3 | import re | |
4 | import time |
|
4 | import time | |
5 | import traceback |
|
|||
6 |
|
5 | |||
7 | import pytz |
|
6 | import pytz | |
8 |
|
7 | |||
@@ -18,12 +17,14 b' from django.core.cache import cache' | |||||
18 | import boards.settings as board_settings |
|
17 | import boards.settings as board_settings | |
19 | import neboard |
|
18 | import neboard | |
20 | from boards import utils |
|
19 | from boards import utils | |
|
20 | from boards.abstracts.constants import REGEX_TAGS | |||
21 | from boards.abstracts.sticker_factory import get_attachment_by_alias |
|
21 | from boards.abstracts.sticker_factory import get_attachment_by_alias | |
22 | from boards.abstracts.settingsmanager import get_settings_manager |
|
22 | from boards.abstracts.settingsmanager import get_settings_manager | |
23 | from boards.forms.fields import UrlFileField |
|
23 | from boards.forms.fields import UrlFileField | |
24 | from boards.mdx_neboard import formatters |
|
24 | from boards.mdx_neboard import formatters | |
25 | from boards.models import Attachment |
|
25 | from boards.models import Attachment | |
26 | from boards.models import Tag |
|
26 | from boards.models import Tag | |
|
27 | from boards.models.attachment import StickerPack | |||
27 | from boards.models.attachment.downloaders import download, REGEX_MAGNET |
|
28 | from boards.models.attachment.downloaders import download, REGEX_MAGNET | |
28 | from boards.models.post import TITLE_MAX_LENGTH |
|
29 | from boards.models.post import TITLE_MAX_LENGTH | |
29 | from boards.utils import validate_file_size, get_file_mimetype, \ |
|
30 | from boards.utils import validate_file_size, get_file_mimetype, \ | |
@@ -36,7 +37,6 b" SECTION_FORMS = 'Forms'" | |||||
36 | POW_HASH_LENGTH = 16 |
|
37 | POW_HASH_LENGTH = 16 | |
37 | POW_LIFE_MINUTES = 5 |
|
38 | POW_LIFE_MINUTES = 5 | |
38 |
|
39 | |||
39 | REGEX_TAGS = re.compile(r'^[\w\s\d]+$', re.UNICODE) |
|
|||
40 | REGEX_USERNAMES = re.compile(r'^[\w\s\d,]+$', re.UNICODE) |
|
40 | REGEX_USERNAMES = re.compile(r'^[\w\s\d,]+$', re.UNICODE) | |
41 | REGEX_URL = re.compile(r'^(http|https|ftp):\/\/', re.UNICODE) |
|
41 | REGEX_URL = re.compile(r'^(http|https|ftp):\/\/', re.UNICODE) | |
42 |
|
42 | |||
@@ -485,6 +485,7 b' class ThreadForm(PostForm):' | |||||
485 | widget=forms.TextInput(attrs={ATTRIBUTE_PLACEHOLDER: TAGS_PLACEHOLDER}), |
|
485 | widget=forms.TextInput(attrs={ATTRIBUTE_PLACEHOLDER: TAGS_PLACEHOLDER}), | |
486 | max_length=100, label=_('Tags'), required=True) |
|
486 | max_length=100, label=_('Tags'), required=True) | |
487 | monochrome = forms.BooleanField(label=_('Monochrome'), required=False) |
|
487 | monochrome = forms.BooleanField(label=_('Monochrome'), required=False) | |
|
488 | stickerpack = forms.BooleanField(label=_('Sticker Pack'), required=False) | |||
488 |
|
489 | |||
489 | def clean_tags(self): |
|
490 | def clean_tags(self): | |
490 | tags = self.cleaned_data['tags'].strip() |
|
491 | tags = self.cleaned_data['tags'].strip() | |
@@ -534,6 +535,36 b' class ThreadForm(PostForm):' | |||||
534 | def is_monochrome(self): |
|
535 | def is_monochrome(self): | |
535 | return self.cleaned_data['monochrome'] |
|
536 | return self.cleaned_data['monochrome'] | |
536 |
|
537 | |||
|
538 | def clean_stickerpack(self): | |||
|
539 | stickerpack = self.cleaned_data['stickerpack'] | |||
|
540 | if stickerpack: | |||
|
541 | tripcode = self.get_tripcode() | |||
|
542 | if not tripcode: | |||
|
543 | raise forms.ValidationError(_( | |||
|
544 | 'Tripcode should be specified to own a stickerpack.')) | |||
|
545 | title = self.get_title() | |||
|
546 | if not title: | |||
|
547 | raise forms.ValidationError(_( | |||
|
548 | 'Title should be specified as a stickerpack name.')) | |||
|
549 | if not REGEX_TAGS.match(title): | |||
|
550 | raise forms.ValidationError(_('Inappropriate sticker pack name.')) | |||
|
551 | ||||
|
552 | existing_pack = StickerPack.objects.filter(name=title).first() | |||
|
553 | if existing_pack: | |||
|
554 | if existing_pack.tripcode != tripcode: | |||
|
555 | raise forms.ValidationError(_( | |||
|
556 | 'A sticker pack with this name already exists and is' | |||
|
557 | ' owned by another tripcode.')) | |||
|
558 | if not existing_pack.tripcode: | |||
|
559 | raise forms.ValidationError(_( | |||
|
560 | 'This sticker pack can only be updated by an ' | |||
|
561 | 'administrator.')) | |||
|
562 | ||||
|
563 | return stickerpack | |||
|
564 | ||||
|
565 | def is_stickerpack(self): | |||
|
566 | return self.cleaned_data['stickerpack'] | |||
|
567 | ||||
537 |
|
568 | |||
538 | class SettingsForm(NeboardForm): |
|
569 | class SettingsForm(NeboardForm): | |
539 |
|
570 |
1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
@@ -619,3 +619,24 b' msgstr "\xd0\x93\xd0\xbb\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x8b\xd0\xb5 \xd1\x81\xd1\x82\xd0\xb8\xd0\xba\xd0\xb5\xd1\x80\xd1\x8b"' | |||||
619 |
|
619 | |||
620 | msgid "Remove sticker" |
|
620 | msgid "Remove sticker" | |
621 | msgstr "Удалить стикер" |
|
621 | msgstr "Удалить стикер" | |
|
622 | ||||
|
623 | msgid "Sticker Pack" | |||
|
624 | msgstr "Набор Стикеров" | |||
|
625 | ||||
|
626 | msgid "Tripcode should be specified to own a stickerpack." | |||
|
627 | msgstr "Для владения набором стикеров необходимо указать трипкод." | |||
|
628 | ||||
|
629 | msgid "Title should be specified as a stickerpack name." | |||
|
630 | msgstr "Заголовок должен быть указан в качестве имени набора стикеров." | |||
|
631 | ||||
|
632 | msgid "A sticker pack with this name already exists and is owned by another tripcode." | |||
|
633 | msgstr "Набор стикеров с данным именем уже существует и принадлежит другому трипкоду." | |||
|
634 | ||||
|
635 | msgid "This sticker pack can only be updated by an administrator." | |||
|
636 | msgstr "Этот набор стикеров может быть изменён только администратором." | |||
|
637 | ||||
|
638 | msgid "To add a sticker, create a stickerpack thread using the title as a pack name, and a tripcode to own the pack. Then, add posts with title as a sticker name, and the same tripcode, to the thread. Their attachments would become stickers." | |||
|
639 | msgstr "Чтобы добавить стикер, создайте тему-набор с заголовком в качестве названия набора стикеров, и трипкодом для подтверждения владения набором. Затем, добавляйте сообщения с заголовком в качестве имени стикера, и тем же трипкодомм. Их вложения станут стикерами." | |||
|
640 | ||||
|
641 | msgid "Inappropriate sticker pack name." | |||
|
642 | msgstr "Недопустимое имя набора стикеров." |
1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
@@ -619,3 +619,24 b' msgstr "\xd0\x93\xd0\xbb\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xbb\xd1\x8c\xd0\xbd\xd1\x96 \xd1\x81\xd1\x82\xd1\x96\xd0\xba\xd0\xb5\xd1\x80\xd0\xb8"' | |||||
619 |
|
619 | |||
620 | msgid "Remove sticker" |
|
620 | msgid "Remove sticker" | |
621 | msgstr "Видалити стікер" |
|
621 | msgstr "Видалити стікер" | |
|
622 | ||||
|
623 | msgid "Sticker Pack" | |||
|
624 | msgstr "Набір Стікерів" | |||
|
625 | ||||
|
626 | msgid "Tripcode should be specified to own a stickerpack." | |||
|
627 | msgstr "Для володіння набором стікерів необхідно вказати тріпкод." | |||
|
628 | ||||
|
629 | msgid "Title should be specified as a stickerpack name." | |||
|
630 | msgstr "Заголовок повинен бути вказаний в якості імені набору стікерів." | |||
|
631 | ||||
|
632 | msgid "A sticker pack with this name already exists and is owned by another tripcode." | |||
|
633 | msgstr "Набір стікерів з вказаним іменем вже є в наявності та належить іншому тріпкоду." | |||
|
634 | ||||
|
635 | msgid "This sticker pack can only be updated by an administrator." | |||
|
636 | msgstr "Цей набір стікерів може бути змінений лише адміністратором." | |||
|
637 | ||||
|
638 | msgid "To add a sticker, create a stickerpack thread using the title as a pack name, and a tripcode to own the pack. Then, add posts with title as a sticker name, and the same tripcode, to the thread. Their attachments would become stickers." | |||
|
639 | msgstr "Щоб додати стікер, створіть тему-набір з заголовком у якості набору стікерів, та тріпкодом для підтвердження володіння наборомт. Потім, додавайте повідомлення з заголовком у якості імені стікеру та з тим самим тріпкодом. Їхні вкладення станут стікерами." | |||
|
640 | ||||
|
641 | msgid "Inappropriate sticker pack name." | |||
|
642 | msgstr "Неприпустиме ім'я набору стікерів." |
@@ -55,8 +55,9 b' class AttachmentManager(models.Manager):' | |||||
55 | return attachment |
|
55 | return attachment | |
56 |
|
56 | |||
57 | def get_by_alias(self, name): |
|
57 | def get_by_alias(self, name): | |
|
58 | pack_name, sticker_name = name.split('/') | |||
58 | try: |
|
59 | try: | |
59 | return AttachmentSticker.objects.get(name=name).attachment |
|
60 | return AttachmentSticker.objects.get(name=sticker_name, stickerpack__name=pack_name).attachment | |
60 | except AttachmentSticker.DoesNotExist: |
|
61 | except AttachmentSticker.DoesNotExist: | |
61 | return None |
|
62 | return None | |
62 |
|
63 | |||
@@ -163,9 +164,22 b' class Attachment(models.Model):' | |||||
163 | return self.url is None or len(self.url) == 0 |
|
164 | return self.url is None or len(self.url) == 0 | |
164 |
|
165 | |||
165 |
|
166 | |||
|
167 | class StickerPack(models.Model): | |||
|
168 | name = models.TextField(unique=True) | |||
|
169 | tripcode = models.TextField(blank=True) | |||
|
170 | ||||
|
171 | def __str__(self): | |||
|
172 | return self.name | |||
|
173 | ||||
|
174 | ||||
166 | class AttachmentSticker(models.Model): |
|
175 | class AttachmentSticker(models.Model): | |
167 | attachment = models.ForeignKey('Attachment') |
|
176 | attachment = models.ForeignKey('Attachment') | |
168 | name = models.TextField(unique=True) |
|
177 | name = models.TextField(unique=True) | |
|
178 | stickerpack = models.ForeignKey('StickerPack') | |||
169 |
|
179 | |||
170 | def __str__(self): |
|
180 | def __str__(self): | |
171 | return self.name |
|
181 | # Local stickers do not have a sticker pack | |
|
182 | if hasattr(self, 'stickerpack'): | |||
|
183 | return '{}/{}'.format(str(self.stickerpack), self.name) | |||
|
184 | else: | |||
|
185 | return self.name |
@@ -1,20 +1,20 b'' | |||||
1 | import logging |
|
1 | import logging | |
2 |
|
||||
3 | from datetime import datetime, timedelta, date |
|
2 | from datetime import datetime, timedelta, date | |
4 | from datetime import time as dtime |
|
3 | from datetime import time as dtime | |
5 |
|
4 | |||
6 | from boards.abstracts.exceptions import BannedException, ArchiveException |
|
5 | from django.core.exceptions import PermissionDenied | |
7 | from django.db import models, transaction |
|
6 | from django.db import models, transaction | |
|
7 | from django.dispatch import Signal | |||
8 | from django.utils import timezone |
|
8 | from django.utils import timezone | |
9 | from django.dispatch import Signal |
|
|||
10 | from django.core.exceptions import PermissionDenied |
|
|||
11 |
|
9 | |||
12 | import boards |
|
10 | import boards | |
13 |
|
11 | from boards import utils | ||
14 | from boards.models.user import Ban |
|
12 | from boards.abstracts.exceptions import ArchiveException | |
|
13 | from boards.abstracts.constants import REGEX_TAGS | |||
15 | from boards.mdx_neboard import Parser |
|
14 | from boards.mdx_neboard import Parser | |
16 | from boards.models import Attachment |
|
15 | from boards.models import Attachment | |
17 | from boards import utils |
|
16 | from boards.models.attachment import StickerPack, AttachmentSticker | |
|
17 | from boards.models.user import Ban | |||
18 |
|
18 | |||
19 | __author__ = 'neko259' |
|
19 | __author__ = 'neko259' | |
20 |
|
20 | |||
@@ -30,7 +30,7 b' class PostManager(models.Manager):' | |||||
30 | def create_post(self, title: str, text: str, files=[], thread=None, |
|
30 | def create_post(self, title: str, text: str, files=[], thread=None, | |
31 | ip=NO_IP, tags: list=None, |
|
31 | ip=NO_IP, tags: list=None, | |
32 | tripcode='', monochrome=False, images=[], |
|
32 | tripcode='', monochrome=False, images=[], | |
33 | file_urls=[]): |
|
33 | file_urls=[], stickerpack=False): | |
34 | """ |
|
34 | """ | |
35 | Creates new post |
|
35 | Creates new post | |
36 | """ |
|
36 | """ | |
@@ -54,7 +54,7 b' class PostManager(models.Manager):' | |||||
54 | if not thread: |
|
54 | if not thread: | |
55 | thread = boards.models.thread.Thread.objects.create( |
|
55 | thread = boards.models.thread.Thread.objects.create( | |
56 | bump_time=posting_time, last_edit_time=posting_time, |
|
56 | bump_time=posting_time, last_edit_time=posting_time, | |
57 | monochrome=monochrome) |
|
57 | monochrome=monochrome, stickerpack=stickerpack) | |
58 | list(map(thread.tags.add, tags)) |
|
58 | list(map(thread.tags.add, tags)) | |
59 | new_thread = True |
|
59 | new_thread = True | |
60 |
|
60 | |||
@@ -89,6 +89,8 b' class PostManager(models.Manager):' | |||||
89 | thread.bump() |
|
89 | thread.bump() | |
90 | thread.save() |
|
90 | thread.save() | |
91 |
|
91 | |||
|
92 | self._create_stickers(post) | |||
|
93 | ||||
92 | return post |
|
94 | return post | |
93 |
|
95 | |||
94 | def delete_posts_by_ip(self, ip): |
|
96 | def delete_posts_by_ip(self, ip): | |
@@ -190,3 +192,37 b' class PostManager(models.Manager):' | |||||
190 |
|
192 | |||
191 | def _add_file_to_post(self, file, post): |
|
193 | def _add_file_to_post(self, file, post): | |
192 | post.attachments.add(Attachment.objects.create_with_hash(file)) |
|
194 | post.attachments.add(Attachment.objects.create_with_hash(file)) | |
|
195 | ||||
|
196 | def _create_stickers(self, post): | |||
|
197 | thread = post.get_thread() | |||
|
198 | stickerpack_thread = thread.is_stickerpack() | |||
|
199 | if stickerpack_thread: | |||
|
200 | logger = logging.getLogger('boards.stickers') | |||
|
201 | if not post.is_opening(): | |||
|
202 | has_title = len(post.title) > 0 | |||
|
203 | has_one_attachment = post.attachments.count() == 1 | |||
|
204 | opening_post = thread.get_opening_post() | |||
|
205 | valid_name = REGEX_TAGS.match(post.title) | |||
|
206 | if has_title and has_one_attachment and valid_name: | |||
|
207 | existing_sticker = AttachmentSticker.objects.filter( | |||
|
208 | name=post.get_title()).first() | |||
|
209 | attachment = post.attachments.first() | |||
|
210 | if existing_sticker: | |||
|
211 | existing_sticker.attachment = attachment | |||
|
212 | existing_sticker.save() | |||
|
213 | logger.info('Updated sticker {} with new attachment'.format(existing_sticker)) | |||
|
214 | else: | |||
|
215 | try: | |||
|
216 | stickerpack = StickerPack.objects.get( | |||
|
217 | name=opening_post.get_title(), tripcode=post.tripcode) | |||
|
218 | sticker = AttachmentSticker.objects.create( | |||
|
219 | stickerpack=stickerpack, name=post.get_title(), | |||
|
220 | attachment=attachment) | |||
|
221 | logger.info('Created sticker {}'.format(sticker)) | |||
|
222 | except StickerPack.DoesNotExist: | |||
|
223 | pass | |||
|
224 | else: | |||
|
225 | stickerpack, created = StickerPack.objects.get_or_create( | |||
|
226 | name=post.get_title(), tripcode=post.tripcode) | |||
|
227 | if created: | |||
|
228 | logger.info('Created stickerpack {}'.format(stickerpack)) |
@@ -97,6 +97,7 b' class Thread(models.Model):' | |||||
97 | status = models.CharField(max_length=50, default=STATUS_ACTIVE, |
|
97 | status = models.CharField(max_length=50, default=STATUS_ACTIVE, | |
98 | choices=STATUS_CHOICES, db_index=True) |
|
98 | choices=STATUS_CHOICES, db_index=True) | |
99 | monochrome = models.BooleanField(default=False) |
|
99 | monochrome = models.BooleanField(default=False) | |
|
100 | stickerpack = models.BooleanField(default=False) | |||
100 |
|
101 | |||
101 | def get_tags(self) -> QuerySet: |
|
102 | def get_tags(self) -> QuerySet: | |
102 | """ |
|
103 | """ | |
@@ -262,6 +263,9 b' class Thread(models.Model):' | |||||
262 | def is_monochrome(self): |
|
263 | def is_monochrome(self): | |
263 | return self.monochrome |
|
264 | return self.monochrome | |
264 |
|
265 | |||
|
266 | def is_stickerpack(self): | |||
|
267 | return self.stickerpack | |||
|
268 | ||||
265 | # If tags have parent, add them to the tag list |
|
269 | # If tags have parent, add them to the tag list | |
266 | @transaction.atomic |
|
270 | @transaction.atomic | |
267 | def refresh_tags(self): |
|
271 | def refresh_tags(self): |
@@ -1,5 +1,6 b'' | |||||
1 | import re |
|
1 | import re | |
2 | import os |
|
2 | import os | |
|
3 | import logging | |||
3 |
|
4 | |||
4 | from django.db.models.signals import post_save, pre_save, pre_delete, \ |
|
5 | from django.db.models.signals import post_save, pre_save, pre_delete, \ | |
5 | post_delete |
|
6 | post_delete | |
@@ -9,7 +10,8 b' from django.utils import timezone' | |||||
9 | from boards import thumbs |
|
10 | from boards import thumbs | |
10 | from boards.mdx_neboard import get_parser |
|
11 | from boards.mdx_neboard import get_parser | |
11 |
|
12 | |||
12 | from boards.models import Post, GlobalId, Attachment |
|
13 | from boards.models import Post, GlobalId, Attachment, Thread | |
|
14 | from boards.models.attachment import StickerPack, AttachmentSticker | |||
13 | from boards.models.attachment.viewers import FILE_TYPES_IMAGE |
|
15 | from boards.models.attachment.viewers import FILE_TYPES_IMAGE | |
14 | from boards.models.post import REGEX_NOTIFICATION, REGEX_REPLY,\ |
|
16 | from boards.models.post import REGEX_NOTIFICATION, REGEX_REPLY,\ | |
15 | REGEX_GLOBAL_REPLY |
|
17 | REGEX_GLOBAL_REPLY |
@@ -15,7 +15,7 b'' | |||||
15 | {% for sticker in local_stickers %} |
|
15 | {% for sticker in local_stickers %} | |
16 | <div class="gallery_image"> |
|
16 | <div class="gallery_image"> | |
17 | {{ sticker.attachment.get_view|safe }} |
|
17 | {{ sticker.attachment.get_view|safe }} | |
18 |
<div>{{ sticker |
|
18 | <div>{{ sticker }}</div> | |
19 | <div><a href="?action=remove&name={{ sticker.name }}">{% trans "Remove sticker" %}</a></div> |
|
19 | <div><a href="?action=remove&name={{ sticker.name }}">{% trans "Remove sticker" %}</a></div> | |
20 | </div> |
|
20 | </div> | |
21 | {% endfor %} |
|
21 | {% endfor %} | |
@@ -25,7 +25,7 b'' | |||||
25 | {% for sticker in global_stickers %} |
|
25 | {% for sticker in global_stickers %} | |
26 | <div class="gallery_image"> |
|
26 | <div class="gallery_image"> | |
27 | {{ sticker.attachment.get_view|safe }} |
|
27 | {{ sticker.attachment.get_view|safe }} | |
28 |
<div>{{ sticker |
|
28 | <div>{{ sticker }}</div> | |
29 | </div> |
|
29 | </div> | |
30 | {% endfor %} |
|
30 | {% endfor %} | |
31 | {% endif %} |
|
31 | {% endif %} |
@@ -6,6 +6,9 b'' | |||||
6 | <div class="{{ css_class }}" id="{{ post.id }}" data-uid="{{ post.uid }}" {% if tree_depth %}style="margin-left: {{ tree_depth }}em;"{% endif %}> |
|
6 | <div class="{{ css_class }}" id="{{ post.id }}" data-uid="{{ post.uid }}" {% if tree_depth %}style="margin-left: {{ tree_depth }}em;"{% endif %}> | |
7 | <div class="post-info"> |
|
7 | <div class="post-info"> | |
8 | <a class="post_id" href="{{ post.get_absolute_url }}">#{{ post.id }}</a> |
|
8 | <a class="post_id" href="{{ post.get_absolute_url }}">#{{ post.id }}</a> | |
|
9 | {% if is_opening and thread.is_stickerpack %} | |||
|
10 | 📷 | |||
|
11 | {% endif %} | |||
9 | <span class="title">{{ post.title }}</span> |
|
12 | <span class="title">{{ post.title }}</span> | |
10 | {% if perms.boards.change_post and post.has_ip %} |
|
13 | {% if perms.boards.change_post and post.has_ip %} | |
11 | <span class="pub_time" style="border-bottom: solid 2px #{{ post.get_ip_color }};" title="{{ post.poster_ip }}"> |
|
14 | <span class="pub_time" style="border-bottom: solid 2px #{{ post.get_ip_color }};" title="{{ post.poster_ip }}"> |
@@ -9,6 +9,7 b'' | |||||
9 | {% block staticcontent %} |
|
9 | {% block staticcontent %} | |
10 | <h2>{% trans 'Help' %}</h2> |
|
10 | <h2>{% trans 'Help' %}</h2> | |
11 | <p>{% trans 'View available stickers:' %} <a href="{% url 'stickers' %}">{% trans 'Stickers' %}</a></p> |
|
11 | <p>{% trans 'View available stickers:' %} <a href="{% url 'stickers' %}">{% trans 'Stickers' %}</a></p> | |
|
12 | <p>{% trans 'To add a sticker, create a stickerpack thread using the title as a pack name, and a tripcode to own the pack. Then, add posts with title as a sticker name, and the same tripcode, to the thread. Their attachments would become stickers.' %}</p> | |||
12 | <hr /> |
|
13 | <hr /> | |
13 | <p>[i]<i>{% trans 'Italic text' %}</i>[/i]</p> |
|
14 | <p>[i]<i>{% trans 'Italic text' %}</i>[/i]</p> | |
14 | <p>[b]<b>{% trans 'Bold text' %}</b>[/b]</p> |
|
15 | <p>[b]<b>{% trans 'Bold text' %}</b>[/b]</p> |
@@ -142,12 +142,13 b' class AllThreadsView(PostMixin, FileUplo' | |||||
142 |
|
142 | |||
143 | tags = data[FORM_TAGS] |
|
143 | tags = data[FORM_TAGS] | |
144 | monochrome = form.is_monochrome() |
|
144 | monochrome = form.is_monochrome() | |
|
145 | stickerpack = form.is_stickerpack() | |||
145 |
|
146 | |||
146 | post = Post.objects.create_post(title=title, text=text, files=files, |
|
147 | post = Post.objects.create_post(title=title, text=text, files=files, | |
147 | ip=ip, tags=tags, |
|
148 | ip=ip, tags=tags, | |
148 | tripcode=form.get_tripcode(), |
|
149 | tripcode=form.get_tripcode(), | |
149 | monochrome=monochrome, images=images, |
|
150 | monochrome=monochrome, images=images, | |
150 | file_urls=file_urls) |
|
151 | file_urls=file_urls, stickerpack=stickerpack) | |
151 |
|
152 | |||
152 | if form.is_subscribe(): |
|
153 | if form.is_subscribe(): | |
153 | settings_manager = get_settings_manager(request) |
|
154 | settings_manager = get_settings_manager(request) |
@@ -3,6 +3,7 b' import logging' | |||||
3 |
|
3 | |||
4 | from django.core import serializers |
|
4 | from django.core import serializers | |
5 | from django.db import transaction |
|
5 | from django.db import transaction | |
|
6 | from django.db.models import Q | |||
6 | from django.http import HttpResponse, HttpResponseBadRequest |
|
7 | from django.http import HttpResponse, HttpResponseBadRequest | |
7 | from django.shortcuts import get_object_or_404 |
|
8 | from django.shortcuts import get_object_or_404 | |
8 | from django.views.decorators.csrf import csrf_protect |
|
9 | from django.views.decorators.csrf import csrf_protect | |
@@ -194,12 +195,12 b' def api_get_stickers(request):' | |||||
194 | if not term: |
|
195 | if not term: | |
195 | return HttpResponseBadRequest() |
|
196 | return HttpResponseBadRequest() | |
196 |
|
197 | |||
197 | global_stickers = AttachmentSticker.objects.filter(name__contains=term) |
|
198 | global_stickers = AttachmentSticker.objects.filter(Q(name__icontains=term) | Q(stickerpack__name__icontains=term)) | |
198 | local_stickers = [sticker for sticker in get_settings_manager(request).get_stickers() if term in sticker.name] |
|
199 | local_stickers = [sticker for sticker in get_settings_manager(request).get_stickers() if term in sticker.name] | |
199 | stickers = list(global_stickers) + local_stickers |
|
200 | stickers = list(global_stickers) + local_stickers | |
200 |
|
201 | |||
201 | image_dict = [{'thumb': sticker.attachment.get_thumb_url(), |
|
202 | image_dict = [{'thumb': sticker.attachment.get_thumb_url(), | |
202 |
'alias': sticker |
|
203 | 'alias': str(sticker)} | |
203 | for sticker in stickers] |
|
204 | for sticker in stickers] | |
204 |
|
205 | |||
205 | return HttpResponse(content=json.dumps(image_dict)) |
|
206 | return HttpResponse(content=json.dumps(image_dict)) |
General Comments 0
You need to be logged in to leave comments.
Login now