blob: ee9b0ee739ed9ae5db5103dc3df2c54212007dbd [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import unicode_literals
from __future__ import absolute_import
import logging
from tg import request
from tg import tmpl_context as c
from allura.lib import helpers as h
from allura.lib import utils
from allura.lib.spam import SpamFilter
try:
import akismet
AKISMET_AVAILABLE = True
except ImportError:
AKISMET_AVAILABLE = False
log = logging.getLogger(__name__)
if AKISMET_AVAILABLE:
class AkismetWithoutStartupVerify(akismet.Akismet):
def __init__(self, key=None, blog_url=None):
# avoid possible errors at instantiation time, will encounter them later
self.api_key = key
self.blog_url = blog_url
class AkismetSpamFilter(SpamFilter):
"""Spam checking implementation via Akismet service.
To enable Akismet spam filtering in your Allura instance, first pip install akismet (see requirements-optional.txt)
and then include the following parameters in your .ini file::
spam.method = akismet
spam.key = <your Akismet key here>
"""
def __init__(self, config):
if not AKISMET_AVAILABLE:
raise ImportError('akismet not available')
self.service = AkismetWithoutStartupVerify(config['spam.key'], config['base_url'])
def get_data(self, text, artifact=None, user=None, content_type='comment', request=None, **kw):
# Docs: https://akismet.com/development/api/
kw['comment_content'] = text
kw['comment_type'] = content_type
if artifact:
try:
# if its a comment, get wiki, ticket, etc URL
url = artifact.main_url()
except Exception:
url = artifact.url()
kw['permalink'] = h.absurl(url)
if hasattr(artifact, 'timestamp'):
# Message & Post objects
date_created = artifact.timestamp
else:
# fallback for other artifacts, not exactly "created" date though
date_created = artifact.mod_date
kw['comment_date_gmt'] = date_created.isoformat()
kw['comment_post_modified_gmt'] = artifact.primary().mod_date.isoformat()
user = user or c.user
if user:
kw['comment_author'] = user.display_name or user.username
kw['comment_author_email'] = user.email_addresses[0] if user.email_addresses else ''
if request is not None:
kw['user_ip'] = utils.ip_address(request)
kw['user_agent'] = request.headers.get('USER_AGENT')
kw['referrer'] = request.headers.get('REFERER')
else:
# these are required fields, but for ham/spam reports we don't have the original values to send :/
kw['user_ip'] = None
kw['user_agent'] = None
if artifact and hasattr(artifact, 'get_version'): # VersionedArtifacts (includes comment posts)
try:
kw['user_ip'] = artifact.get_version(1).author.logged_ip
except IndexError:
log.debug("couldn't get Snapshot for this artifact %s", artifact)
# kw will be urlencoded, need to utf8-encode
for k, v in kw.items():
kw[k] = h.really_unicode(v).encode('utf8')
return kw
def check(self, text, artifact=None, user=None, content_type='comment', **kw):
res = self.service.comment_check(**self.get_data(text=text,
artifact=artifact,
user=user,
content_type=content_type,
request=request,
))
self.record_result(res, artifact, user)
return res
def submit_spam(self, text, artifact=None, user=None, content_type='comment'):
self.service.submit_spam(**self.get_data(text=text,
artifact=artifact,
user=user,
content_type=content_type))
def submit_ham(self, text, artifact=None, user=None, content_type='comment'):
self.service.submit_ham(**self.get_data(text=text,
artifact=artifact,
user=user,
content_type=content_type))