# vim:fileencoding=utf8 """ Copyright © 2011 Pádraig Brady This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ import cgi import datetime import re import wsgiref.handlers #from google.appengine.api import users from google.appengine.api import mail from google.appengine.api import memcache from google.appengine.ext import webapp from google.appengine.ext import db class Comment(db.Model): user = db.UserProperty() author = db.StringProperty() url = db.StringProperty() page = db.StringProperty(required=True) content = db.TextProperty() date = db.DateTimeProperty(auto_now_add=True) def previous_year_month_day(): last_year = datetime.datetime.now() - datetime.timedelta(days=1*365) return last_year.strftime("%Y-%m-%d") def age(date): age = datetime.datetime.now() - date if age.days: return date.strftime("%d %b %Y") elif not age.seconds: return "just now" else: hours = age.seconds/3600 if hours: return "%s hours ago" % hours mins = age.seconds/60 if mins: return "%s minutes ago" % mins return "%s seconds ago" % age.seconds def getcache(key, compute, time=600): value = memcache.get(key) if value is None: value = compute() memcache.set(key, value, time=time) return value class MainPage(webapp.RequestHandler): def get(self): mode = self.request.get('mode') if mode != "count": self.response.out.write(""" """) if mode == "count": value = memcache.get(self.request.path) if value is not None: self.response.out.write('%d' % value) return # Caveat is anchor '#' is not sent to server (in self.request.url) # so any links on web before Aug 7 2021 referencing specific comments, wont work # All anchors now specify the "all" parameter so will be valid going forward. if mode == "count" or self.request.get("all"): limit = "" else: self.response.out.write('load older comments\n

\n') # Note the "query by GQL" form on the GAE console expects the date # in a different format. I.e.: '%sT00:00:00Z' limit = "AND date > DATETIME('%s 00:00:00')" % previous_year_month_day() #TODO: can have simpler query for just counting. May not need Gql at all? comments = db.GqlQuery("SELECT * FROM Comment WHERE page = '%s' %s ORDER BY date" % (self.request.path, limit)) if mode == "count": value=comments.count() memcache.set(self.request.path, value, 600) #timeout as can delete comments in dashboard self.response.out.write('%d' % value) return num=0 for comment in comments: self.response.out.write('\n
\n' % (comment.key().id(), (num%2 and "odd" or ""))) self.response.out.write('# ' % comment.key().id()) if comment.author: if comment.url.startswith("http://") or comment.url.startswith("https://"): self.response.out.write('%s:' % (cgi.escape(comment.url,quote=True), cgi.escape(comment.author))) else: self.response.out.write('%s:' % cgi.escape(comment.author)) else: self.response.out.write('anonymous:') self.response.out.write(' ' + age(comment.date)) self.response.out.write('\n
%s
' % comment.content) self.response.out.write('\n
\n') num+=1 #Use this to auto fill form #user = users.get_current_user() #if user: # self.response.out.write('Hello, ' + user.nickname()) self.response.out.write("""
Name:
Website:
comments:
(no HTML)
31+9
""") self.response.out.write('\n\n') def post(self): comment = Comment(page = self.request.path) #use path_qs for dynamic sites # google account #if users.get_current_user(): # comment.user = users.get_current_user() # 20/07/2023: Disable comments on root as most spam there if comment.page == '/': self.redirect('#commentform') return if self.request.get('scheck') != '4' + '0': self.redirect('#commentform') return comment.author = self.request.get('author') url = self.request.get('url') if "://" not in url and "@" not in url and "." in url: url = "http://" + url comment.url = url content = cgi.escape(self.request.get('content')) if not content: self.redirect('#commentform') return r="((?:ftp|https?)://[^ \t\n\r()\"']+)" content=re.sub(r,r'\1',content) content=content.replace("\n","
\n") comment.content = db.Text(content) comment.put() # Ask client to reload ASAP self.redirect('#commentform') # Send notification email notification = mail.AdminEmailMessage() notification.sender = "pixelbeat@gmail.com" #TODO: don't hardcode notification.subject = (comment.author.encode("utf-8") or "anonymous") + '@' + self.request.host notification.body = 'http://'+self.request.host+self.request.path+'#comment-'+str(comment.key().id()) notification.send() def main(): application = webapp.WSGIApplication( [('/.*', MainPage)], debug=True ) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main()