EatEmAll / django-djeddit

Minimalistic Reddit clone developed as a Django reusable app
http://eatemall.pythonanywhere.com
Other
42 stars 13 forks source link

Akismet spam filter #5

Open Zerokami opened 6 years ago

Zerokami commented 6 years ago

Maybe a spam filter can be implemented in djeddit

Here is a decorator I found in askbot for akismet spam filter

https://github.com/erichegt/askbot-devel/blob/6ad4cb23d6ab24d6d69e2f4523d356b113a79301/askbot/utils/decorators.py

def check_spam(field):
    '''Decorator to check if there is spam in the form'''

    def decorator(view_func):
        @functools.wraps(view_func)
        def wrapper(request, *args, **kwargs):

            if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
                raise ImproperlyConfigured('You have not set AKISMET_API_KEY')

            if askbot_settings.USE_AKISMET and request.method == "POST":
                comment = smart_str(request.POST[field])
                data = {'user_ip': request.META["REMOTE_ADDR"],
                        'user_agent': request.environ['HTTP_USER_AGENT'],
                        'comment_author': smart_str(request.user.username),
                        }
                if request.user.is_authenticated():
                    data.update({'comment_author_email': request.user.email})

                from akismet import Akismet
                api = Akismet(
                    askbot_settings.AKISMET_API_KEY, 
                    smart_str(askbot_settings.APP_URL), 
                    "Askbot/%s" % get_version()
                )

                if api.comment_check(comment, data, build_data=False):
                    logging.debug(
                        'Spam detected in %s post at: %s',
                        request.user.username,
                        datetime.datetime.now()
                    )
                    spam_message = _(
                        'Spam was detected on your post, sorry '
                        'for if this is a mistake'
                    )
                    if request.is_ajax():
                        return HttpResponseForbidden(
                                spam_message, 
                                mimetype="application/json"
                            )
                    else:
                        request.user.message_set.create(message=spam_message)
                        return HttpResponseRedirect(reverse('index'))

            return view_func(request, *args, **kwargs)
        return wrapper

    return decorator
Zerokami commented 6 years ago

https://github.com/ASKBOT/askbot-devel/blob/master/askbot/utils/akismet_utils.py

from akismet import Akismet, APIKeyError, AkismetError
from askbot.conf import settings as askbot_settings
from askbot import get_version
from django.core.exceptions import ImproperlyConfigured
from django.utils.encoding import smart_str
from askbot.utils.html import site_url
from django.core.urlresolvers import reverse
import logging

def akismet_check_spam(text, request):
    """Returns True if spam found, false if not,
    May raise exceptions if something is not right with
    the Akismet account/service/setup"""
    if not askbot_settings.USE_AKISMET:
        return False
    try:
        if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
            raise ImproperlyConfigured('You have not set AKISMET_API_KEY')
        data = {'user_ip': request.META.get('REMOTE_ADDR'),
                'user_agent': request.environ['HTTP_USER_AGENT'],
                'comment_author': smart_str(request.user.username)
                }
        if request.user.is_authenticated():
            data.update({'comment_author_email': request.user.email})

        api = Akismet(
            askbot_settings.AKISMET_API_KEY,
            smart_str(site_url(reverse('questions'))),
            "Askbot/%s" % get_version()
        )
        return api.comment_check(text, data, build_data=False)
    except APIKeyError:
        logging.critical('Akismet Key is missing')
    except AkismetError:
        logging.critical('Akismet error: Invalid Akismet key or Akismet account issue!')
    except Exception as e:
        logging.critical((u'Akismet error: %s' % unicode(e)).encode('utf-8'))
    return False
EatEmAll commented 6 years ago

If an anti spam filter is to be added it needs to be optional. The option to use it as well as the API keys to Akismet could be provided in settings.py.

The filter could used in Thread creation form in title and url fields and in Post creation form in content field.

I think that it would be idea to look into multiple Django apps that implement this feature before implementing it here. Here's another app worth looking in to: https://github.com/mixkorshun/django-antispam https://django-antispam.readthedocs.io/en/latest/usage.html

Btw, if you think you're up to it, you're welcome to implement this yourself, commit it on another branch, and make a pull request. I'll merge your changes into master after reviewing & accepting your changes. Let me know if you're interested.

Zerokami commented 6 years ago

For sites like communities akismet charges atleast 5$ per month.

So, it's a big no for me.