1 # -*- coding: utf-8 -*-
2 from os
.path
import dirname
, join
3 from urllib
import urlopen
5 from werkzeug
import escape
, url_encode
9 from zine
.widgets
import Widget
10 from zine
.views
.admin
import flash
, render_admin_response
11 from zine
.models
import COMMENT_BLOCKED_SPAM
, Comment
12 from zine
.privileges
import BLOG_ADMIN
, require_privilege
13 from zine
.utils
.validators
import ValidationError
, check
14 from zine
.utils
.http
import redirect_to
15 from zine
.utils
import forms
17 # Check do we have the recaptcha library installed
23 have_recaptcha
= False
25 USER_AGENT
= 'Zine /%s | reCatpcha/1.11' % zine
.__version
__
26 #AKISMET_URL_BASE = 'rest.akismet.com'
27 #AKISMET_VERSION = '1.1'
28 TEMPLATES
= join(dirname(__file__
), 'templates')
29 #BLOCKED_MSG = 'blocked by akismet'
32 #: because we need the information about verified keys quite often
33 #: we store verified keys here.
34 _verified_keys
= set()
37 class InvalidKey(ValueError):
38 """Raised with a message if the key is invalid."""
40 def __init__(self
, message
):
41 self
.message
= message
42 ValueError.__init
__(self
, message
)
45 def is_valid_key(message
=None, memorize
=False):
46 """A validator that validates keys."""
48 message
= _('The key is invalid.')
50 def validate(form
, apikey
):
51 blog_url
= get_application().cfg
['blog_url']
52 cachekey
= (apikey
, blog_url
)
53 if cachekey
in _verified_keys
:
56 data
= {'key': apikey
, 'blog': blog_url
}
57 resp
= send_request(apikey
, False, data
, 'verify-key')
59 raise ValidationError(_('Could not verify key because of a '
60 'server to server connection error.'))
62 raise ValidationError(message
)
64 _verified_keys
.add(cachekey
)
68 def get_akismet_key():
69 """Return the akismet key for the current application or
70 `None` if there is no key or the key is invalid.
72 app
= get_application()
73 key
= app
.cfg
['akismet_spam_filter/apikey']
74 if key
and check(is_valid_key
, key
, memorize
=True):
78 class ConfigurationForm(forms
.Form
):
79 """The configuration form."""
80 api_key
= forms
.TextField(validators
=[is_valid_key()])
83 def do_spamcheck(req
, comment
):
84 """Do spamchecking for all new comments."""
85 # something blocked the comment already. no need to check for
90 key
= get_akismet_key()
96 'blog': req
.app
['blog_url'],
97 'user_ip': comment
.submitter_ip
,
98 'user_agent': USER_AGENT
,
99 'comment_type': 'comment',
100 'comment_author': comment
.author
,
101 'comment_author_email': comment
.email
,
102 'comment_author_url': comment
.www
,
103 'comment_content': comment
.body
106 # if we have a request object for testing we can provide some
107 # more information for akismet.
109 data
['referrer'] = req
.environ
.get('HTTP_REFERER', '')
110 for key
in 'SERVER_ADDR', 'SERVER_NAME', 'SERVER_PORT', \
111 'SERVER_SOFTWARE', 'HTTP_ACCEPT', 'REMOTE_ADDR':
112 data
[key
] = req
.environ
.get(key
, '')
114 resp
= send_request(apikey
, True, data
, 'comment-check')
116 comment
.status
= COMMENT_BLOCKED_SPAM
117 comment
.blocked_msg
= BLOCKED_MSG
120 def add_akismet_link(req
, navigation_bar
):
121 """Add a button for akismet to the comments page."""
122 if req
.user
.has_privilege(BLOG_ADMIN
):
123 for link_id
, url
, title
, children
in navigation_bar
:
124 if link_id
== 'options':
125 children
.insert(-3, ('akismet_spam_filter',
126 url_for('akismet_spam_filter/config'),
130 @require_privilege(BLOG_ADMIN
)
131 def show_akismet_config(req
):
132 """Show the akismet control panel."""
133 form
= ConfigurationForm(initial
=dict(
134 pubkey
=req
.app
.cfg
['akismet_spam_filter/pubkey']
135 privkey
=req
.app
.cfg
['akismet_spam_filter/privkey']
138 if req
.method
== 'POST' and form
.validate(req
.form
):
140 req
.app
.cfg
.change_single('recaptcha_spam_filter/pubkey',
142 req
.app
.cfg
.change_single('recaptcha_spam_filter/privkey',
145 flash(_('reCAPTCHA has been successfully enabled.'), 'ok')
147 flash(_('reCAPTCHA disabled.'), 'ok')
148 return redirect_to('recaptcha_spam_filter/config')
149 return render_admin_response('admin/recaptcha_spam_filter.html',
150 'options.recaptcha_spam_filter',
151 form
=form
.as_widget())
154 #class AkismetBlockedCommentsCounterWidget(Widget):
155 # NAME = 'get_akismet_blocked_comments'
156 # TEMPLATE = 'akismet_widget.html'
158 # def __init__(self, show_title=False, title='Akismet Blocked Comments'):
159 # self.show_title = show_title
161 # self.spam_comments = Comment.objects.filter(
162 # Comment.blocked_msg == BLOCKED_MSG).count()
165 # def get_display_name():
166 # return _('Comments Blocked by Akismet')
169 def setup(app
, plugin
):
170 if not have_recaptcha
:
171 raise SetupError("The reCAPTCHA plugin requires the recaptcha python library")
172 app
.add_config_var('recaptcha_spam_filter/pubkey',
173 forms
.TextField(default
=u
''))
174 app
.add_config_var('recaptcha_spam_filter/privkey',
175 forms
.TextField(default
=u
''))
176 app
.add_url_rule('/options/recaptcha', prefix
='admin',
177 endpoint
='recaptcha/config',
178 view
=show_akismet_config
)
179 app
.connect_event('before-comment-saved', do_spamcheck
)
180 app
.connect_event('modify-admin-navigation-bar', add_akismet_link
)
181 app
.add_template_searchpath(TEMPLATES
)
182 #app.add_widget(AkismetBlockedCommentsCounterWidget)