diff options
-rw-r--r-- | app/jrnl/models.py | 21 | ||||
-rw-r--r-- | app/lib/django_comments/akismet.py | 105 | ||||
-rw-r--r-- | app/locations/models.py | 17 |
3 files changed, 135 insertions, 8 deletions
diff --git a/app/jrnl/models.py b/app/jrnl/models.py index 0deb8d3..5290e37 100644 --- a/app/jrnl/models.py +++ b/app/jrnl/models.py @@ -221,6 +221,27 @@ class EntryModerator(CommentModerator): moderator.register(Entry, EntryModerator) +from django_comments.signals import comment_will_be_posted +from django_comments import akismet + + +@receiver(comment_will_be_posted, sender=Comment) +def spam_check(sender, comment, request, **kwargs): + akismet.USERAGENT = "David Lynch's Python library/1.0" + + try: + real_key = akismet.verify_key(settings.AKISMET_KEY, "https://luxagraf.net/") + if real_key: + is_spam = akismet.comment_check(settings.AKISMET_KEY, "https://luxagraf.net/", request.META['REMOTE_ADDR'], request.META['HTTP_USER_AGENT'], comment_content=comment.comment) + if is_spam: + return False + else: + return True + except akismet.AkismetError as e: + print('Something went wrong, allowing comment') + print(e.response, e.statuscode) + return True + @receiver(comment_was_posted, sender=Comment) def cache_gravatar(sender, comment, **kwargs): diff --git a/app/lib/django_comments/akismet.py b/app/lib/django_comments/akismet.py new file mode 100644 index 0000000..daa4281 --- /dev/null +++ b/app/lib/django_comments/akismet.py @@ -0,0 +1,105 @@ +#!/usr/bin/python + +__version__ = "0.3" +__date__ = "2005-12-01" +__author__ = "David Lynch (kemayo AT Google's mail service DOT com)" +__copyright__ = "Copyright 2005, David Lynch" +__license__ = "New BSD" +__history__ = """ +0.3 - 20051205 - Cleaned up __post. +0.2 - 20051201 - Added documentation, and tweaked the circumstances where an error + will be thrown. +0.1 - 20051201 - Initial release. Everything pretty much works. Probably. +""" + +import http.client +from urllib.parse import urlencode + +USERAGENT = "" +AKISMET_URL = "rest.akismet.com" +AKISMET_PORT = 80 + + +class AkismetError(Exception): + def __init__(self, response, statuscode): + self.response = response + self.statuscode = statuscode + + def __str__(self): + return repr(self.value) + + +def __post(request, host, path, port=80): + connection = http.client.HTTPConnection(host, port) + connection.request("POST", path, request, { + "User-Agent": "%s | %s/%s" % (USERAGENT, "Akistmet.py", __version__), + "Content-type": "application/x-www-form-urlencoded" + }) + response = connection.getresponse() + return response.read(), response.status + + +def verify_key(key, blog): + """Find out whether a given WordPress.com API key is valid. + Required parameters: + key: A WordPress.com API key. + blog: URL of the front page of the site comments will be submitted to. + Returns True if a valid key, False if invalid. + """ + response, status = __post("key=%s&blog=%s" % (key, blog), AKISMET_URL, "/1.1/verify-key", AKISMET_PORT) + if response == "valid": + return True + elif response == "invalid": + return False + else: + raise AkismetError(response, status) + + +def comment_check(key, blog, user_ip, user_agent, **other): + """Submit a comment to find out whether Akismet thinks that it's spam. + Required parameters: + key: A valid WordPress.com API key, as tested with verify_key(). + blog: URL of the front page of the site the comment will appear on. + user_ip: IP address of the being which submitted the comment. + user_agent: User agent reported by said being. + Suggested "other" keys: "permalink", "referrer", "comment_type", "comment_author", + "comment_author_email", "comment_author_url", "comment_content", and any other HTTP + headers sent from the client. + More detail on what should be submitted is available at: + http://akismet.com/development/api/ + Returns True if spam, False if ham. Throws an AkismetError if the server says + anything unexpected. + """ + request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} + request.update(other) + response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/comment-check", AKISMET_PORT) + if response == "true": + return True + elif response == "false": + return False + else: + raise AkismetError(response, status) + + +def submit_spam(key, blog, user_ip, user_agent, **other): + """Report a false negative to Akismet. + Same arguments as comment_check. + Doesn't return anything. Throws an AkismetError if the server says anything. + """ + request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} + request.update(other) + response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/submit-spam", AKISMET_PORT) + if status != 200 or response != "": + raise AkismetError(response, status) + + +def submit_ham(key, blog, user_ip, user_agent, **other): + """Report a false positive to Akismet. + Same arguments as comment_check. + Doesn't return anything. Throws an AkismetError if the server says anything. + """ + request = {'blog': blog, 'user_ip': user_ip, 'user_agent': user_agent} + request.update(other) + response, status = __post(urlencode(request), "%s.%s" % (key, AKISMET_URL), "/1.1/submit-ham", AKISMET_PORT) + if status != 200 or response != "": + raise AkismetError(response, status) diff --git a/app/locations/models.py b/app/locations/models.py index 1ac48cb..a56299e 100644 --- a/app/locations/models.py +++ b/app/locations/models.py @@ -7,6 +7,7 @@ from django.utils.safestring import mark_safe "http://staticmap.openstreetmap.de/staticmap.php?center=object.location.geometry.centroid.y,object.location.geometry.centroid.x&zoom=14&size=1140x300&maptype=osmarenderer&markers=40.702147,-74.015794,lightblue1" + class Region(models.Model): """Model to define arbitrary regions based on where I've been""" name = models.CharField(max_length=50) @@ -181,14 +182,14 @@ def get_bounds(lat, lon): state = adr.get('state') country = adr.get('country') r = requests.get('http://nominatim.openstreetmap.org/search', - params={ - 'city': city, - 'state': state, - 'country': country, - 'polygon_text': 1, - 'format': 'json', - 'featuretype': 'neighborhood' - }) + params={ + 'city': city, + 'state': state, + 'country': country, + 'polygon_text': 1, + 'format': 'json', + 'featuretype': 'neighborhood' + }) r.raise_for_status() data = json.loads(r.text) poly = GEOSGeometry(data[0]['geotext']) |