def prune_data(weeks=10, days=1): # Delete spam spam_posts = Post.objects.filter(spam=Post.SPAM) logger.info(f"Deleting {spam_posts.count()} spam posts") spam_posts.delete() past_days = now() - timedelta(days=days) post_views = PostView.objects.filter(date__lt=past_days) logger.info(f"Deleting {post_views.count()} post views") post_views.delete() # Reduce overall messages. weeks_since = now() - timedelta(weeks=weeks) messages = Message.objects.filter(sent_at__lt=weeks_since) logger.info(f"Deleting {messages.count()} messages") messages.delete() # Get rid of too many messages users = User.objects.annotate(total=Count("recipients")).filter( total__gt=MAX_MSG)[:100] for user in users: since = now() - timedelta(days=1) Message.objects.filter(user=user, sent_at__lt=since).delete() return
def get_jobs(user, tag="", order="", limit=None): """ Generates a post list on a topic. """ query = Job.objects.all() if tag: query = query.filter(tags__name=tag.lower()) # Apply post ordering. if ORDER_MAPPER.get(order): ordering = ORDER_MAPPER.get(order) query = query.order_by(ordering) else: query = query.order_by("-creation_date") days = LIMIT_MAP.get(limit, 0) # Apply time limit if required. if days: delta = util.now() - timedelta(days=days) query = query.filter(lastedit_date__gt=delta) # Select related information used during rendering. query = query.select_related("author__profile") return query
def get_posts(user, topic="", tag="", order="", limit=None): """ Generates a post list on a topic. """ # Topics are case insensitive. topic = topic or LATEST topic = topic.lower() # Detect known post types. post_type = POST_TYPE_MAPPER.get(topic) query = Post.objects.valid_posts(u=user, is_toplevel=True) # Determines how to start the preform_search. if post_type: query = query.filter(type=post_type) elif topic == OPEN: query = query.filter(type=Post.QUESTION, answer_count=0) elif topic == BOOKMARKS and user.is_authenticated: query = query.filter(votes__author=user, votes__type=Vote.BOOKMARK) elif topic == FOLLOWING and user.is_authenticated: query = query.filter(subs__user=user) elif topic == MYPOSTS and user.is_authenticated: query = query.filter(author=user) elif topic == MYVOTES and user.is_authenticated: query = query.filter(votes__post__author=user) elif topic == MYTAGS and user.is_authenticated: tags = user.profile.my_tags.split(",") query = query.filter(tags__name__in=tags) if user.is_anonymous or not user.profile.is_moderator: query = query.exclude(Q(spam=Post.SPAM) | Q(status=Post.DELETED)) # Filter by tags if specified. if tag: query = query.filter(tags__name=tag.lower()) # Apply post ordering. if ORDER_MAPPER.get(order): ordering = ORDER_MAPPER.get(order) query = query.order_by(ordering) else: query = query.order_by("-rank") days = LIMIT_MAP.get(limit, 0) # Apply time limit if required. if days: delta = util.now() - timedelta(days=days) query = query.filter(lastedit_date__gt=delta) # Select related information used during rendering. query = query.select_related("root").select_related( "author__profile", "lastedit_user__profile") return query
def get_start(days, cursor): """ Return the start date stored in database """ if days < 0: recent = Sync.objects.filter(pk=1).first() recent = recent.last_synced if recent else most_recent(cursor=cursor) recent = recent + timedelta(days=2) else: # Get the most recently created post on the remote server. recent = Post.objects.old().order_by("-creation_date").first() recent = recent.creation_date if recent else None recent = recent - timedelta(days=2) start = recent or util.now() return start
def community_list(request): users = User.objects.select_related("profile") page = request.GET.get("page", 1) ordering = request.GET.get("order", "visit") limit_to = request.GET.get("limit", "time") query = request.GET.get('query', '') query = query.replace("'", "").replace('"', '').strip() days = LIMIT_MAP.get(limit_to, 0) if days: delta = util.now() - timedelta(days=days) users = users.filter(profile__last_login__gt=delta) if query and len(query) > 2: db_query = Q(profile__name__icontains=query) | Q(profile__uid__icontains=query) | \ Q(username__icontains=query) | Q(email__icontains=query) users = users.filter(db_query) # Remove the cache when filters are given. no_cache = days or (query and len(query) > 2) or ordering cache_key = None if no_cache else USERS_LIST_KEY order = ORDER_MAPPER.get(ordering, "visit") users = users.filter(profile__state__in=[Profile.NEW, Profile.TRUSTED]) users = users.order_by(order) # Create the paginator paginator = CachedPaginator(cache_key=cache_key, object_list=users, per_page=settings.POSTS_PER_PAGE) users = paginator.get_page(page) context = dict(tab="community", users=users, query=query, order=ordering, limit=limit_to) return render(request, "community_list.html", context=context)
def finalize_post(sender, instance, created, **kwargs): # Determine the root of the post. root = instance.root if instance.root is not None else instance # Update last contributor, last editor, and last edit date to the thread Post.objects.filter(uid=root.uid).update( lastedit_user=instance.lastedit_user, last_contributor=instance.last_contributor, lastedit_date=instance.lastedit_date) # Get newly created subscriptions since the last edit date. subs = Subscription.objects.filter(date__gte=instance.lastedit_date, post=instance.root) if created: # Make the Uid user friendly instance.uid = instance.uid or f"p{instance.pk}" if instance.parent: # When the parent is set the root must follow the parent root. instance.root = instance.parent.root else: # When there is no parent, root and parent are set to itself. instance.root = instance.parent = instance # Answers and comments may only have comments associated with them. if instance.parent.type in (Post.ANSWER, Post.COMMENT): instance.type = Post.COMMENT # Sanity check. assert instance.root and instance.parent if instance.is_toplevel: # Add tags for top level posts. tags = [ Tag.objects.get_or_create(name=name)[0] for name in instance.parse_tags() ] instance.tags.remove() instance.tags.add(*tags) else: # Title is inherited from top level. instance.title = "%s: %s" % (instance.get_type_display(), instance.root.title[:80]) # Make the last editor first in the list of contributors # Done on post creation to avoid moderators being added for editing a post. instance.root.thread_users.remove(instance.lastedit_user) instance.root.thread_users.add(instance.lastedit_user) # Update this post rank on create and not every edit. instance.rank = instance.lastedit_date.timestamp() # Save the instance. instance.save() instance.update_parent_counts() # Bump the root rank when a new descendant is added. Post.objects.filter(uid=instance.root.uid).update( rank=util.now().timestamp()) # Create subscription to the root. auth.create_subscription(post=instance.root, user=instance.author) # Get all subscribed users when a new post is created subs = Subscription.objects.filter(post=instance.root) # Notify users who are watching tags in this post tasks.notify_watched_tags.spool(post=instance) # Give it a spam score. tasks.spam_scoring.spool(post=instance) # Add this post to the spam index if it's spam. tasks.update_spam_index.spool(post=instance) # Ensure posts get re-indexed after being edited. Post.objects.filter(uid=instance.uid).update(indexed=False) # Exclude current authors from receiving messages from themselves subs = subs.exclude( Q(type=Subscription.NO_MESSAGES) | Q(user=instance.author)) extra_context = dict(post=instance) tasks.notify_followers.spool(subs=subs, author=instance.author, extra_context=extra_context)
def items(self): # Delay posts hours. delay_time = now() - timedelta(hours=2) posts = Post.objects.valid_posts(creation_date__lt=delay_time).exclude( type=Post.BLOG).order_by('-creation_date') return posts[:FEED_COUNT]