from django.contrib.auth import get_user_model from django.core.exceptions import PermissionDenied from django.utils.translation import ugettext_lazy as _, ungettext from misago.conf import settings from misago.core import forms from misago.markup import common_flavour from misago.threads.permissions import allow_message_user from misago.threads.validators import validate_title class ReplyForm(forms.Form): is_main = True legend = _("Reply") template = "misago/posting/replyform.html" post = forms.CharField(label=_("Message body"), required=False) def __init__(self, post=None, request=None, *args, **kwargs): self.request = request self.post_instance = post self.parsing_result = {} super(ReplyForm, self).__init__(*args, **kwargs) def validate_post(self, post): if not self.post_instance.pk or self.post_instance.original != post: self._validate_post(post) self.parse_post(post) def _validate_post(self, post): post_len = len(post) if not post_len: raise forms.ValidationError(_("Enter message.")) if post_len < settings.post_length_min: message = ungettext( "Posted message should be at least %(limit)s character long.", "Posted message should be at least %(limit)s characters long.", settings.post_length_min) message = message % {'limit': settings.post_length_min} raise forms.ValidationError(message) if settings.post_length_max and post_len > settings.post_length_max: message = ungettext( "Posted message can't be longer than %(limit)s character.", "Posted message can't be longer than %(limit)s characters.", settings.post_length_max) message = message % {'limit': settings.post_length_max} raise forms.ValidationError(message) def parse_post(self, post): self.parsing_result = common_flavour( self.request, self.post_instance.poster, post) self.post_instance.original = self.parsing_result['original_text'] self.post_instance.parsed = self.parsing_result['parsed_text'] def validate_data(self, data): self.validate_post(data.get('post', '')) def clean(self): data = super(ReplyForm, self).clean() self.validate_data(data) return data class ThreadForm(ReplyForm): legend = _("Thread ") title = forms.CharField(label=_("Thread title"), required=False) def __init__(self, thread=None, *args, **kwargs): self.thread_instance = thread super(ThreadForm, self).__init__(*args, **kwargs) def validate_data(self, data): errors = [] if not data.get('title') and not data.get('post'): raise forms.ValidationError(_("Enter thread title and message.")) try: validate_title(data.get('title', '')) except forms.ValidationError as e: errors.append(e) try: self.validate_post(data.get('post', '')) except forms.ValidationError as e: errors.append(e) if errors: raise forms.ValidationError(errors) class ThreadParticipantsForm(forms.Form): is_supporting = True location = 'reply_top' template = "misago/posting/threadparticipantsform.html" users = forms.CharField(label=_("Invite users to thread"), required=False) def __init__(self, *args, **kwargs): self.users_cache = [] self.user = kwargs.pop('user', None) super(ThreadParticipantsForm, self).__init__(*args, **kwargs) def clean(self): cleaned_data = super(ThreadParticipantsForm, self).clean() if not cleaned_data.get('users'): raise forms.ValidationError( _("You have to specify message recipients.")) clean_usernames = [] for name in cleaned_data['users'].split(','): clean_name = name.strip().lower() if clean_name == self.user.slug: raise forms.ValidationError( _("You can't addres message to yourself.")) if clean_name not in clean_usernames: clean_usernames.append(clean_name) max_participants = self.user.acl['max_private_thread_participants'] if max_participants and len(clean_usernames) > max_participants: message = ungettext("You can't start private thread " "with more than than %(users)s user.", "You can't start private thread " "with more than than %(users)s users.", max_participants) message = message % {'users': max_participants} raise forms.ValidationError(message) users_qs = get_user_model().objects.filter(slug__in=clean_usernames) for user in users_qs: try: allow_message_user(self.user, user) except PermissionDenied as e: raise forms.ValidationError(unicode(e)) self.users_cache.append(user) if len(self.users_cache) != len(clean_usernames): valid_usernames = [u.slug for u in self.users_cache] invalid_usernames = [] for username in clean_usernames: if username not in valid_usernames: invalid_usernames.append(username) message = _("One or more message recipients could " "not be found: %(usernames)s") formats = {'usernames': ', '.join(invalid_usernames)} raise forms.ValidationError(message % formats) valid_usernames = [u.username for u in self.users_cache] cleaned_data['users'] = ','.join(valid_usernames) return cleaned_data class ThreadLabelFormBase(forms.Form): is_supporting = True location = 'after_title' template = "misago/posting/threadlabelform.html" def ThreadLabelForm(*args, **kwargs): labels = kwargs.pop('labels') choices = [(0, _("No label"))] choices.extend([(label.pk, label.name ) for label in labels]) field = forms.TypedChoiceField( label=_("Thread label"), coerce=int, choices=choices) FormType = type("ThreadLabelFormFinal", (ThreadLabelFormBase,), {'label': field}) return FormType(*args, **kwargs) class ThreadPinForm(forms.Form): is_supporting = True location = 'lefthand' template = "misago/posting/threadpinform.html" is_pinned = forms.YesNoSwitch( label=_("Pin thread"), yes_label=_("Pinned thread"), no_label=_("Unpinned thread")) class ThreadCloseForm(forms.Form): is_supporting = True location = 'lefthand' template = "misago/posting/threadcloseform.html" is_closed = forms.YesNoSwitch( label=_("Close thread"), yes_label=_("Closed thread"), no_label=_("Open thread"))