| # 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)) |