def save(self, *args, **kwargs): created = self.pk is None self.content = smart_lower(self.content) if created: self.author.invalidate_entry_counts() super().save(*args, **kwargs) # Check if the user has written 10 entries, If so make them available for novice lookup if self.author.is_novice and self.author.application_status == "OH" and self.author.entry_count >= 10: self.author.application_status = "PN" self.author.application_date = timezone.now() self.author.save() Message.objects.compose( get_generic_superuser(), self.author, gettext( "as you entered your first 10 entries, you have been admitted to" " the novice list. you can see your queue number in your profile page." " if your entry count drops below 10, you will be kicked from the list." ), ) # assign topic creator (includes novices) if not self.is_draft and not self.topic.created_by: self.topic.created_by = self.author self.topic.save() self.topic.register_wishes(fulfiller_entry=self)
def process(self): if self.is_ready: return serializer = ArchiveSerializer() entries = self.author.entry_set( manager="objects_published").select_related("topic") conversations = self.author.conversationarchive_set.all() entries_text = serializer.serialize(entries, fields=("topic__title", "content", "date_created", "date_edited")) conversations_text = ( "[%s]" % "".join('{"target": "%s", "messages": %s},' % (item.target, item.messages) for item in conversations)[:-1] ) # Formatting already-serialized data ([:-1] removes the trailing comma). content = '{"entries": %s, "conversations": %s}' % (entries_text, conversations_text) self.is_ready = True self.file.save("backup", ContentFile(content.encode("utf-8")), save=True) settings.get_model("Message").objects.compose( get_generic_superuser(), self.author, gettext( "your backup is now ready. you may download your backup" " file using the link provided in the backup tab of settings." ), )
def register_wishes(self, fulfiller_entry=None): """To delete fulfilled wishes and inform wishers.""" if self.wishes.exists() and self.has_entries: invoked_by_entry = fulfiller_entry is not None wishes = self.wishes.all().select_related("author") for wish in wishes: self_fulfillment = invoked_by_entry and fulfiller_entry.author == wish.author if not self_fulfillment: message = (gettext( "`%(title)s`, the topic you wished for, had an entry" " entered by `@%(username)s`: (see: #%(entry)d)" ) % { "title": self.title, "username": fulfiller_entry.author.username, "entry": fulfiller_entry.pk, } if invoked_by_entry else gettext( "`%(title)s`, the topic you wished for, is now populated with some entries." ) % { "title": self.title }) Message.objects.compose(get_generic_superuser(), wish.author, message) return wishes.delete() return None
def post(self, request): reference = request.POST.get("reference") == "yes" target_topic = request.POST.get("target_topic", "").strip() from_date = parse_date_or_none(request.POST.get("from_date")) to_date = parse_date_or_none(request.POST.get("to_date")) try: target_topic = Topic.objects.get(title=target_topic) generic_superuser = get_generic_superuser() topic_list_raw = list(self.get_object_list()) entries_list = Entry.objects_published.filter( topic__in=topic_list_raw) if from_date: entries_list = entries_list.filter(date_created__gte=from_date) if to_date: entries_list = entries_list.filter(date_created__lte=to_date) entries_count = entries_list.count() entries_list.update( topic=target_topic) # Bulk update, does not call save() target_topic.register_wishes() # Include an informative entry on old topic to indicate the new topic if reference: bulk_list = [ Entry( topic=obj, content= f"({pgettext('editor', 'see')}: {target_topic.title})", author=generic_superuser, ) for obj in topic_list_raw ] Entry.objects.bulk_create(bulk_list) # Admin log log_admin( f"TopicMove action, count: {entries_count}. sources->{topic_list_raw}," f"from->{from_date} to->{to_date}", request.user, Topic, target_topic, ) notifications.success( request, ngettext("%(count)d entry was transferred", "%(count)d entries were transferred", entries_count) % {"count": entries_count}, ) except Topic.DoesNotExist: notifications.error(request, gettext("Couldn't find the target topic.")) except Author.DoesNotExist: notifications.error(request, gettext("GENERIC_SUPERUSER is missing?")) return redirect(self.get_changelist_url())
def accept_application(self): # Alter the user status user = self.novice user.application_status = Author.APPROVED user.is_novice = False user.save() # Log admin info admin_info_msg = _( "Authorship of the user '%(username)s' was approved.") % { "username": user.username } log_admin(admin_info_msg, self.request.user, Author, user) # Send information messages to the user user_info_msg = _( "dear %(username)s, congratulations! your application" " of authorship has been approved. you can utilize your" " authorship by logging in.") % { "username": user.username } Message.objects.compose(get_generic_superuser(), user, user_info_msg) user.email_user(_("your authorship has been approved"), user_info_msg, settings.FROM_EMAIL) notifications.success(self.request, admin_info_msg) return True
def decline_application(self): # Alter the user status & delete entries user = self.novice Entry.objects_published.filter( author=user).delete() # does not trigger model's delete() user.application_status = Author.ON_HOLD user.application_date = None user.save() # Log admin info admin_info_msg = _( "Authorship of the user '%(username)s' was rejected.") % { "username": user.username } log_admin(admin_info_msg, self.request.user, Author, user) # Send information messages to the user user_info_msg = _( "dear %(username)s, your application of authorship has been" " rejected and all of your entries has been deleted. if you" " fill up 10 entries, you will be admitted to novice list again." ) % { "username": user.username } Message.objects.compose(get_generic_superuser(), user, user_info_msg) user.email_user(_("your authorship has been rejected"), user_info_msg, settings.FROM_EMAIL) notifications.success(self.request, admin_info_msg) return True
def post(self, request): time_choices = { "D1": timedelta(days=1), "W1": timedelta(days=7), "W2": timedelta(days=14), "M1": timedelta(days=30), "M3": timedelta(days=90), "PM": None, } choice = request.POST.get("suspension_time") if choice in time_choices.keys(): if choice == "PM": suspended_until = parse_date_or_none("01.01.2038") else: suspended_until = timezone.now() + time_choices[choice] # Evaluate it immediately because it needs to be iterated and we need to call len() user_list_raw = list(self.get_object_list()) # Get and parse information for suspension action_information = request.POST.get("information", gettext("No information was given.")) message_for_user = gettext( "your account has been suspended. administration message: %(message)s\n\n" "in your profile page, you can see the remaining time until your account gets reactivated." ) % {"message": action_information} message_for_log = f"Suspended until {suspended_until}, information: {action_information}" log_list = [] # Reserve list that hold instances for bulk creation generic_superuser = get_generic_superuser() # Set new suspended_until and append instances to reserved lists for user in user_list_raw: user.suspended_until = suspended_until log_list.append(logentry_instance(message_for_log, request.user, Author, user)) Message.objects.compose(generic_superuser, user, message_for_user) # Bulk creation/updates Author.objects.bulk_update(user_list_raw, ["suspended_until"]) # Update Author, does not call save() logentry_bulk_create(log_list) # Log user suspension for admin history count = len(user_list_raw) notifications.success( request, ngettext("%(count)d author was suspended.", "%(count)d authors were suspended.", count) % {"count": count}, ) else: notifications.error(request, gettext("The selected duration was invalid.")) return redirect(self.get_changelist_url())
def post(self, request): response = redirect(self.get_changelist_url()) factors = (request.POST.get("multiplier", ""), request.POST.get("quantity", "")) if not all(map(str.isdigit, factors)): notifications.error(request, gettext("The selected duration was invalid.")) return response ban_hours = math.prod(map(int, factors)) suspended_until = timezone.now() + timedelta(hours=ban_hours) # Evaluate it immediately because it needs to be iterated and we need to call len() user_list_raw = list(self.get_object_list()) action_information = request.POST.get( "information", gettext("No information was given.")) message_for_user = gettext( "your account has been suspended. administration message: %(message)s\n\n" "in your profile page, you can see the remaining time until your account gets reactivated." ) % { "message": action_information } message_for_log = f"Suspended until {suspended_until}, information: {action_information}" log_list = [] # Reserve list that hold instances for bulk creation generic_superuser = get_generic_superuser() # Set new suspended_until and append instances to reserved lists for user in user_list_raw: user.suspended_until = suspended_until log_list.append( logentry_instance(message_for_log, request.user, Author, user)) Message.objects.compose(generic_superuser, user, message_for_user) # Bulk creation/updates Author.objects.bulk_update( user_list_raw, ["suspended_until"]) # Update Author, does not call save() logentry_bulk_create(log_list) # Log user suspension for admin history count = len(user_list_raw) notifications.success( request, ngettext("%(count)d author was suspended.", "%(count)d authors were suspended.", count) % {"count": count}, ) return response