bgneal@214: """Antispam utility functions other apps can use.""" bgneal@215: import datetime bgneal@215: import logging bgneal@215: import textwrap bgneal@215: bgneal@214: from django.core.cache import cache bgneal@214: bgneal@214: from antispam import SPAM_PHRASE_KEY bgneal@214: from antispam.models import SpamPhrase bgneal@215: from core.functions import email_admins bgneal@563: from bio.models import STA_SUSPENDED, STA_SPAMMER bgneal@563: from comments.models import Comment bgneal@563: from forums.tools import delete_user_posts bgneal@780: from user_photos.s3 import delete_photos bgneal@214: bgneal@214: bgneal@214: def contains_spam(s): bgneal@214: """This function returns True if the supplied string s contains any spam bgneal@214: phrases and False otherwise. bgneal@214: """ bgneal@214: phrases = _get_spam_phrases() bgneal@215: s = s.lower() bgneal@214: for spam in phrases: bgneal@214: if spam in s: bgneal@214: return True bgneal@214: bgneal@214: return False bgneal@214: bgneal@214: bgneal@215: def spam_check(request, content): bgneal@215: """This function checks the supplied content for spam if the user from the bgneal@215: supplied request is a stranger (new to the site). If spam is found, the bgneal@215: function makes a log entry, emails the admins, suspends the user's account bgneal@215: and returns True. If spam is not found, False is returned. bgneal@215: It is assumed that request.user is an authenticated user and thus has a bgneal@215: user profile. bgneal@215: """ bgneal@215: user = request.user bgneal@215: if user.get_profile().is_stranger() and contains_spam(content): bgneal@215: bgneal@215: ip = request.META.get('REMOTE_ADDR', "unknown") bgneal@215: bgneal@215: msg = textwrap.dedent("""\ bgneal@215: SPAM FILTER TRIPPED by %s bgneal@215: PATH: %s bgneal@215: IP: %s bgneal@215: Message: bgneal@215: %s bgneal@215: """ % (user.username, request.path, ip, content)) bgneal@215: bgneal@215: logging.info(msg) bgneal@215: email_admins("SPAM FILTER TRIPPED BY %s" % user.username, msg) bgneal@215: suspend_user(user) bgneal@215: return True bgneal@215: bgneal@215: return False bgneal@215: bgneal@215: bgneal@215: def suspend_user(user): bgneal@215: """This function marks the user as suspended.""" bgneal@215: user.is_active = False bgneal@215: user.save() bgneal@215: profile = user.get_profile() bgneal@215: profile.status = STA_SUSPENDED bgneal@215: profile.status_date = datetime.datetime.now() bgneal@562: profile.save(content_update=False) bgneal@563: logging.info("User suspended: %s", user.username) bgneal@563: bgneal@563: bgneal@563: def deactivate_spammer(user): bgneal@563: """ bgneal@563: This function deactivate's the user, marks them as a spammer, then bgneal@563: deletes the user's comments and forum posts. The spammer's profile is bgneal@563: cleared so any spam links won't show up anymore. bgneal@563: bgneal@563: """ bgneal@563: user.is_active = False bgneal@563: user.save() bgneal@563: bgneal@563: profile = user.get_profile() bgneal@563: profile.status = STA_SPAMMER bgneal@563: profile.status_date = datetime.datetime.now() bgneal@625: profile.reset() bgneal@608: if profile.avatar: bgneal@608: profile.avatar.delete(save=False) bgneal@563: profile.save() bgneal@563: bgneal@625: # delete comments & forum posts bgneal@563: Comment.objects.filter(user=user).delete() bgneal@563: delete_user_posts(user) bgneal@563: bgneal@625: # delete elsewhere links bgneal@625: user.social_network_profiles.all().delete() bgneal@625: user.instant_messenger_profiles.all().delete() bgneal@625: user.website_profiles.all().delete() bgneal@625: bgneal@625: # delete shouts bgneal@625: user.shout_set.all().delete() bgneal@625: bgneal@780: # delete any uploaded photos bgneal@780: photos = user.uploaded_photos.all() bgneal@780: if len(photos): bgneal@780: delete_photos(photos) bgneal@780: photos.delete() bgneal@780: bgneal@563: logging.info("User deactivated for spam: %s", user.username) bgneal@316: bgneal@215: bgneal@214: def _get_spam_phrases(): bgneal@563: """ bgneal@563: This function returns the current list of spam phrase strings. bgneal@214: The strings are cached to avoid hitting the database. bgneal@563: bgneal@214: """ bgneal@214: phrases = cache.get(SPAM_PHRASE_KEY) bgneal@214: if phrases: bgneal@214: return phrases bgneal@214: bgneal@214: phrases = SpamPhrase.objects.values_list('phrase', flat=True) bgneal@214: cache.set(SPAM_PHRASE_KEY, phrases) bgneal@214: return phrases