annotate antispam/utils.py @ 861:e4f8d87c3d30

Configure Markdown logger to reduce noise in logs. Markdown is logging at the INFO level whenever it loads an extension. This looks like it has been fixed in master at GitHub. But until then we will explicitly configure the MARKDOWN logger to log at WARNING or higher.
author Brian Neal <bgneal@gmail.com>
date Mon, 01 Dec 2014 18:36:27 -0600
parents 9e803323a0d0
children
rev   line source
bgneal@214 1 """Antispam utility functions other apps can use."""
bgneal@215 2 import datetime
bgneal@215 3 import logging
bgneal@215 4 import textwrap
bgneal@215 5
bgneal@214 6 from django.core.cache import cache
bgneal@214 7
bgneal@214 8 from antispam import SPAM_PHRASE_KEY
bgneal@214 9 from antispam.models import SpamPhrase
bgneal@215 10 from core.functions import email_admins
bgneal@563 11 from bio.models import STA_SUSPENDED, STA_SPAMMER
bgneal@563 12 from comments.models import Comment
bgneal@563 13 from forums.tools import delete_user_posts
bgneal@780 14 from user_photos.s3 import delete_photos
bgneal@214 15
bgneal@214 16
bgneal@214 17 def contains_spam(s):
bgneal@214 18 """This function returns True if the supplied string s contains any spam
bgneal@214 19 phrases and False otherwise.
bgneal@214 20 """
bgneal@214 21 phrases = _get_spam_phrases()
bgneal@215 22 s = s.lower()
bgneal@214 23 for spam in phrases:
bgneal@214 24 if spam in s:
bgneal@214 25 return True
bgneal@214 26
bgneal@214 27 return False
bgneal@214 28
bgneal@214 29
bgneal@215 30 def spam_check(request, content):
bgneal@215 31 """This function checks the supplied content for spam if the user from the
bgneal@215 32 supplied request is a stranger (new to the site). If spam is found, the
bgneal@215 33 function makes a log entry, emails the admins, suspends the user's account
bgneal@215 34 and returns True. If spam is not found, False is returned.
bgneal@215 35 It is assumed that request.user is an authenticated user and thus has a
bgneal@215 36 user profile.
bgneal@215 37 """
bgneal@215 38 user = request.user
bgneal@789 39 if user.profile.is_stranger() and contains_spam(content):
bgneal@215 40
bgneal@215 41 ip = request.META.get('REMOTE_ADDR', "unknown")
bgneal@215 42
bgneal@215 43 msg = textwrap.dedent("""\
bgneal@215 44 SPAM FILTER TRIPPED by %s
bgneal@215 45 PATH: %s
bgneal@215 46 IP: %s
bgneal@215 47 Message:
bgneal@215 48 %s
bgneal@215 49 """ % (user.username, request.path, ip, content))
bgneal@215 50
bgneal@215 51 logging.info(msg)
bgneal@215 52 email_admins("SPAM FILTER TRIPPED BY %s" % user.username, msg)
bgneal@215 53 suspend_user(user)
bgneal@215 54 return True
bgneal@215 55
bgneal@215 56 return False
bgneal@215 57
bgneal@215 58
bgneal@215 59 def suspend_user(user):
bgneal@215 60 """This function marks the user as suspended."""
bgneal@215 61 user.is_active = False
bgneal@215 62 user.save()
bgneal@789 63 profile = user.profile
bgneal@215 64 profile.status = STA_SUSPENDED
bgneal@215 65 profile.status_date = datetime.datetime.now()
bgneal@562 66 profile.save(content_update=False)
bgneal@563 67 logging.info("User suspended: %s", user.username)
bgneal@563 68
bgneal@563 69
bgneal@563 70 def deactivate_spammer(user):
bgneal@563 71 """
bgneal@563 72 This function deactivate's the user, marks them as a spammer, then
bgneal@563 73 deletes the user's comments and forum posts. The spammer's profile is
bgneal@563 74 cleared so any spam links won't show up anymore.
bgneal@563 75
bgneal@563 76 """
bgneal@563 77 user.is_active = False
bgneal@563 78 user.save()
bgneal@563 79
bgneal@789 80 profile = user.profile
bgneal@563 81 profile.status = STA_SPAMMER
bgneal@563 82 profile.status_date = datetime.datetime.now()
bgneal@625 83 profile.reset()
bgneal@608 84 if profile.avatar:
bgneal@608 85 profile.avatar.delete(save=False)
bgneal@563 86 profile.save()
bgneal@563 87
bgneal@625 88 # delete comments & forum posts
bgneal@563 89 Comment.objects.filter(user=user).delete()
bgneal@563 90 delete_user_posts(user)
bgneal@563 91
bgneal@625 92 # delete elsewhere links
bgneal@625 93 user.social_network_profiles.all().delete()
bgneal@625 94 user.instant_messenger_profiles.all().delete()
bgneal@625 95 user.website_profiles.all().delete()
bgneal@625 96
bgneal@625 97 # delete shouts
bgneal@625 98 user.shout_set.all().delete()
bgneal@625 99
bgneal@780 100 # delete any uploaded photos
bgneal@780 101 photos = user.uploaded_photos.all()
bgneal@780 102 if len(photos):
bgneal@780 103 delete_photos(photos)
bgneal@780 104 photos.delete()
bgneal@780 105
bgneal@563 106 logging.info("User deactivated for spam: %s", user.username)
bgneal@316 107
bgneal@215 108
bgneal@214 109 def _get_spam_phrases():
bgneal@563 110 """
bgneal@563 111 This function returns the current list of spam phrase strings.
bgneal@214 112 The strings are cached to avoid hitting the database.
bgneal@563 113
bgneal@214 114 """
bgneal@214 115 phrases = cache.get(SPAM_PHRASE_KEY)
bgneal@214 116 if phrases:
bgneal@214 117 return phrases
bgneal@214 118
bgneal@214 119 phrases = SpamPhrase.objects.values_list('phrase', flat=True)
bgneal@214 120 cache.set(SPAM_PHRASE_KEY, phrases)
bgneal@214 121 return phrases