Commit e30e9baf authored by Joseph Wilhelm's avatar Joseph Wilhelm

Initial commit of everything. Not a single bit of this is tested, but I...

Initial commit of everything. Not a single bit of this is tested, but I believe it’s feature complete.
parents
*.log
*.pot
*.pyc
.*project
.DS_Store
.settings/
django-botscout
===============
This provides an easy hook into the Botscout system for Django forms
import logging
from urllib import urlencode
import urllib2
from django.core import cache
from django import forms
from django.utils.translation import ugettext_lazy as _
from .settings import (BOTSCOUT_API_KEY, BOTSCOUT_API_URL,
BOTSCOUT_CACHE_TIMEOUT, BOTSCOUT_NETWORK_TIMEOUT)
logger = logging.getLogger(__name__)
class BotScoutForm(object):
"""
BotScoutForm is a form mixin which should work with both regular and model
forms to prevent spam bots. It checks all available data against the
botscout.com database for any bots known to them.
This mixin should precede forms.Form/ModelForm.
"""
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
error_msg = getattr(self, 'BOTSCOUT_ERROR_MESSAGE',
_('This request was matched in the BotScout database'))
super(BotScoutForm, self).__init__(*args, **kwargs)
self.error_messages['botscout'] = error_msg
def clean(self):
data = super(BotScoutForm, self).clean()
try:
bot_cache = cache.get_cache('botscout')
except cache.InvalidCacheBackendError:
bot_cache = cache.get_cache('default')
using_ip = self.request is not None
name_field = getattr(self, 'BOTSCOUT_NAME_FIELD', 'name')
email_field = getattr(self, 'BOTSCOUT_EMAIL_FIELD', 'email')
test_data = {'name': data.get(name_field, None),
'mail': data.get(email_field, None)}
if using_ip:
test_data['ip'] = self.request.META.get('REMOTE_ADDR', None)
test_data = dict((x, y) for x, y in test_data.iteritems() if y is not None)
cached_data = bot_cache.get_many(['botscout:%s:%s' % (x, y)
for x, y in test_data.iteritems()])
if any(cached_data.values()):
raise forms.ValidationError(self.error_messages['botscout'])
untested = dict((x, y) for x, y in test_data.iteritems()
if 'botscout:%s:%s' % (x, y) not in cached_data)
if untested:
test_url = '%s?multi%s' % (BOTSCOUT_API_URL, urlencode(untested))
if BOTSCOUT_API_KEY is not None:
test_url = '%s&key=%s' % (test_url, BOTSCOUT_API_KEY)
try:
scout_handle = urllib2.urlopen(test_url, timeout=BOTSCOUT_NETWORK_TIMEOUT)
response = scout_handle.read(1024)
if response.startswith('!'):
logger.error(response)
else:
# Format: Y|MULTI|IP|3|MAIL|1|NAME|2
(unused, unused, unused, ip_hits, unused, mail_hits,
unused, name_hits) = response.split('|')
hit_data = {}
if 'ip' in untested:
hit_data['botscout:ip:%s' % untested['ip']] = int(ip_hits)
if 'mail' in untested:
hit_data['botscout:mail:%s' % untested['mail']] = int(mail_hits)
if 'name' in untested:
hit_data['botscout:name:%s' % untested['name']] = int(name_hits)
bot_cache.set_many(hit_data)
if any(hit_data.values()):
raise forms.ValidationError(self.error_messages['botscout'])
except urllib2.URLError:
"""
In case of an error on BotScout's side, we don't want to block this
request.
"""
pass
return data
from django.conf import settings
BOTSCOUT_API_KEY = getattr(settings, 'BOTSCOUT_API_KEY', None)
BOTSCOUT_API_URL = getattr(settings, 'BOTSCOUT_API_URL', 'http://botscout.com/test/')
BOTSCOUT_CACHE_TIMEOUT = getattr(settings, 'BOTSCOUT_CACHE_TIMEOUT', (60 * 30))
BOTSCOUT_NETWORK_TIMEOUT = getattr(settings, 'BOTSCOUT_NETWORK_TIMEOUT', 5)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment