changeset 214:28988cce138b

Implement #83: a string filter facility like NukeSeSentinel. It currently isn't hooked up to anything. Will do that in #84.
author Brian Neal <bgneal@gmail.com>
date Fri, 14 May 2010 02:19:48 +0000
parents 65016249bf35
children 8c1832b9d815
files gpp/antispam/__init__.py gpp/antispam/admin.py gpp/antispam/models.py gpp/antispam/tests.py gpp/antispam/utils.py gpp/settings.py gpp/test_settings.py
diffstat 7 files changed, 117 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/antispam/__init__.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,1 @@
+SPAM_PHRASE_KEY = "antispam.spam_phrases"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/antispam/admin.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,12 @@
+"""Admin definitions for the antispam application."""
+
+from django.contrib import admin
+
+from antispam.models import SpamPhrase
+
+
+class SpamPhraseAdmin(admin.ModelAdmin):
+    search_fields = ('phrase', )
+
+
+admin.site.register(SpamPhrase, SpamPhraseAdmin)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/antispam/models.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,22 @@
+"""Models for the antispam application."""
+from django.db import models
+from django.core.cache import cache
+
+from antispam import SPAM_PHRASE_KEY
+
+
+class SpamPhrase(models.Model):
+    """A SpamPhrase is a string that is checked for in user input. User input
+    containing a SpamPhrase should be blocked and flagged.
+    """
+    phrase = models.CharField(max_length=64)
+
+    class Meta:
+        ordering = ('phrase', )
+
+    def __unicode__(self):
+        return self.phrase
+
+    def save(self, *args, **kwargs):
+        cache.delete(SPAM_PHRASE_KEY)
+        super(SpamPhrase, self).save(*args, **kwargs)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/antispam/tests.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,37 @@
+"""
+Tests for the antispam application.
+"""
+from django.test import TestCase
+from django.core.cache import cache
+
+from antispam import SPAM_PHRASE_KEY
+from antispam.models import SpamPhrase
+from antispam.utils import contains_spam
+
+
+class AntispamCase(TestCase):
+
+    def test_no_phrases(self):
+        """
+        Tests that an empty spam phrase table works.
+        """
+        cache.delete(SPAM_PHRASE_KEY)
+        self.assertFalse(contains_spam("Here is some random text."))
+
+    def test_phrases(self):
+        """
+        Simple test of some phrases.
+        """
+        SpamPhrase.objects.create(phrase="grytner")
+        SpamPhrase.objects.create(phrase="allday.ru")
+        SpamPhrase.objects.create(phrase="stefa.pl")
+
+        self.assert_(contains_spam("grytner"))
+        self.assert_(contains_spam("11grytner"))
+        self.assert_(contains_spam("11grytner>"))
+        self.assert_(contains_spam("1djkl jsd stefa.pl"))
+        self.assert_(contains_spam("1djkl jsd <stefa.pl---sd8"))
+        self.assert_(contains_spam("1dsdjallday.rukl jsd <stefa.pl---sd8"))
+        self.assert_(contains_spam(" 1djallday.rukl"))
+        self.assertFalse(contains_spam("this one is spam free."))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/antispam/utils.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,31 @@
+"""Antispam utility functions other apps can use."""
+from django.core.cache import cache
+
+from antispam import SPAM_PHRASE_KEY
+from antispam.models import SpamPhrase
+
+
+def contains_spam(s):
+    """This function returns True if the supplied string s contains any spam
+    phrases and False otherwise.
+    """
+    phrases = _get_spam_phrases()
+    for spam in phrases:
+        if spam in s:
+            return True
+
+    return False
+
+
+def _get_spam_phrases():
+    """This function returns the current list of spam phrase strings.
+    The strings are cached to avoid hitting the database.
+    """
+    phrases = cache.get(SPAM_PHRASE_KEY)
+    if phrases:
+        return phrases
+
+    phrases = SpamPhrase.objects.values_list('phrase', flat=True)
+    cache.set(SPAM_PHRASE_KEY, phrases)
+    return phrases
+
--- a/gpp/settings.py	Mon May 10 02:58:19 2010 +0000
+++ b/gpp/settings.py	Fri May 14 02:19:48 2010 +0000
@@ -127,6 +127,7 @@
     'elsewhere',
     'tagging',
     'accounts',
+    'antispam',
     'bio',
     'bulletins',
     'comments',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/test_settings.py	Fri May 14 02:19:48 2010 +0000
@@ -0,0 +1,13 @@
+"""
+Settings to use when running tests. Uses sqlite for speed.
+This idea was taken from
+http://blog.davidziegler.net/post/370368042/test-database-settings-in-django
+"""
+from settings import *
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': 'dev.db',
+    },
+}