Skip to content

Commit a1ba14f

Browse files
committed
Merge branch 'matteocrippa.it'
2 parents 88c75c1 + b474729 commit a1ba14f

File tree

12 files changed

+150
-5
lines changed

12 files changed

+150
-5
lines changed

config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
# If another string is used besides 'default', calls to static files and
3535
# use of template files in /views will go to directory by that name.
3636
"theme": "default",
37+
38+
# Display gravatars alongside user comments?
39+
"use_gravatars": True,
40+
41+
# Do you want to be emailed when new comments are posted?
42+
"send_comment_notification": True,
3743

3844
# If you want to use legacy ID mapping for your former blog platform,
3945
# define it here and insert the necessary mapping code in the

handlers/bloog/blog.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
from google.appengine.api import users
5151
from google.appengine.ext import db
5252
from google.appengine.ext.webapp import template
53+
from google.appengine.api import mail
54+
from google.appengine.api import urlfetch
5355

5456
from handlers import restful
5557
from utils import authorized
@@ -143,7 +145,13 @@ def get_sanitizer_func(handler, **kwargs):
143145
logging.debug("Content-type: %s", handler.request.headers['CONTENT_TYPE'])
144146
logging.debug("In sanitizer: %s", kwlist)
145147
return lambda html : sanitizer.sanitize_html(html, **kwlist)
146-
148+
149+
def do_sitemap_ping():
150+
form_fields = { "sitemap": "%s/sitemap.xml" % (config.BLOG['root_url'],) }
151+
urlfetch.fetch(url="http://www.google.com/webmasters/tools/ping",
152+
payload=urllib.urlencode(form_fields),
153+
method=urlfetch.GET)
154+
147155
def process_embedded_code(article):
148156
# TODO -- Check for embedded code, escape opening triangular brackets
149157
# within code, and set article embedded_code strings so we can
@@ -212,6 +220,7 @@ def process_article_submission(handler, article_type):
212220
article.put()
213221
for key in article.tag_keys:
214222
db.get(key).counter.increment()
223+
do_sitemap_ping()
215224
restful.send_successful_response(handler, '/' + article.permalink)
216225
view.invalidate_cache()
217226
else:
@@ -280,6 +289,16 @@ def process_comment_submission(handler, article):
280289
logging.debug("Bad comment: %s", property_hash)
281290
handler.error(400)
282291
return
292+
293+
# Notify the author of a new comment (from matteocrippa.it)
294+
if config.BLOG['send_comment_notification']:
295+
recipient = "%s <%s>" % (config.BLOG['author'], config.BLOG['email'],)
296+
body = ("A new comment has just been posted on %s/%s by %s."
297+
% (config.BLOG['root_url'], article.permalink, comment.name))
298+
mail.send_mail(sender=config.BLOG['email'],
299+
to=recipient,
300+
subject="New comment by %s" % (comment.name,),
301+
body=body)
283302

284303
# Render just this comment and send it to client
285304
response = template.render(
@@ -318,7 +337,9 @@ def render_article(handler, article):
318337
"allow_comments": allow_comments,
319338
"article": article,
320339
"captcha1": captcha[:3],
321-
"captcha2": captcha[3:6] })
340+
"captcha2": captcha[3:6],
341+
"use_gravatars": config.BLOG['use_gravatars']
342+
})
322343
else:
323344
# This didn't fall into any of our pages or aliases.
324345
# Page not found.
@@ -565,3 +586,16 @@ def get(self):
565586
page = view.ViewPage()
566587
page.render(self, {"blog_updated_timestamp": updated,
567588
"articles": articles, "ext": "xml"})
589+
590+
class SitemapHandler(webapp.RequestHandler):
591+
def get(self):
592+
logging.debug("Sending Sitemap")
593+
articles = db.Query(models.blog.Article).order('-published').fetch(1000)
594+
if articles:
595+
self.response.headers['Content-Type'] = 'text/xml'
596+
page = view.ViewPage()
597+
page.render(self, {
598+
"articles": articles,
599+
"ext": "xml",
600+
"root_url": config.BLOG['root_url']
601+
})

main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
# Force sys.path to have our own directory first, so we can import from it.
3737
sys.path.insert(0, config.APP_ROOT_DIR)
3838

39+
# Import custom django libraries
40+
webapp.template.register_template_library('utils.django_libs.gravatar')
41+
webapp.template.register_template_library('utils.django_libs.description')
42+
3943
# Log a message each time this module get loaded.
4044
logging.info('Loading %s, app version = %s',
4145
__name__, os.getenv('CURRENT_VERSION_ID'))
@@ -54,6 +58,7 @@
5458
('/tag/(.*)', blog.TagHandler),
5559
(config.BLOG['master_atom_url'] + '/*$', blog.AtomHandler),
5660
('/articles', blog.ArticlesHandler),
61+
('/sitemap.xml', blog.SitemapHandler),
5762
('/(.*)', blog.ArticleHandler)]
5863

5964
def main():

static/default/style.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ h3#respond{color:#555;margin-bottom:7px;}
147147
.comment_text ul,
148148
.comment_text ol,
149149
.comment_text blockquote{margin:0 1em;}
150+
p.comment_meta .gravatar{vertical-align:top;margin-left:7px;}
150151
p.comment_meta span.subject{font-weight:bold;text-transform:uppercase;margin:0 0 0 7px;}
151152
p.comment_meta span.user{font-weight:bold;}
152153
p.comment_meta span.date{font-weight:normal;text-align:right;}

static/robots.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
User-agent: *
2-
Disallow:
2+
Disallow: /tag/*

utils/django_libs/__init__.py

Whitespace-only changes.

utils/django_libs/description.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# The MIT License
2+
#
3+
# Copyright (c) 2008 Matteo Crippa
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to
7+
# deal in the Software without restriction, including without limitation
8+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+
# and/or sell copies of the Software, and to permit persons to whom the
10+
# Software is furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21+
# DEALINGS IN THE SOFTWARE.
22+
23+
"""
24+
Description Support for Bloog
25+
"""
26+
__author__ = 'Matteo Crippa'
27+
28+
import re
29+
30+
from google.appengine.ext import webapp
31+
32+
register = webapp.template.create_template_register()
33+
34+
def description(value):
35+
return re.sub(r'<[^>]*?>', '', value).replace("\n","")[0:150]
36+
37+
register.filter(description)

utils/django_libs/gravatar.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# The MIT License
2+
#
3+
# Copyright (c) 2008 Matteo Crippa
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to
7+
# deal in the Software without restriction, including without limitation
8+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+
# and/or sell copies of the Software, and to permit persons to whom the
10+
# Software is furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21+
# DEALINGS IN THE SOFTWARE.
22+
23+
"""
24+
Gravatar Support for Bloog
25+
"""
26+
__author__ = 'Matteo Crippa'
27+
28+
import md5
29+
30+
from google.appengine.ext import webapp
31+
32+
register = webapp.template.create_template_register()
33+
34+
def gravatar(email):
35+
return md5.new(email).hexdigest()
36+
37+
register.filter(gravatar)

views/default/bloog/base.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ <h3>Categories</h3>
100100
<p class="tags">
101101
{% if blog_tags %}
102102
{% for tag in blog_tags %}
103-
<a href="/tag/{{ tag.name|urlencode }}">{{ tag.name }}</a>
104-
({{ tag.count }})<br />
103+
{% ifnotequal tag.count 0 %}
104+
<a href="/tag/{{ tag.name|urlencode }}">{{ tag.name }}</a>
105+
({{ tag.count }})<br />
106+
{% endifnotequal %}
105107
{% endfor %}
106108
{% else %}
107109
No posts have been tagged yet.

views/default/bloog/blog/article.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
{% if article.embedded_code %}
44
{% block head %}
55
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/SyntaxHighlighter.css"></link>
6+
<meta name="description" content="{{article.html|description}}" />
67
{% endblock %}
78
{% endif %}
89

0 commit comments

Comments
 (0)