From 172d389ba5a73f652d0e51741a8c3dc7475c9c76 Mon Sep 17 00:00:00 2001 From: "John \"Elwin\" Edwards" Date: Fri, 30 Jan 2015 09:25:32 -0500 Subject: [PATCH] Add a basic blog manager. rlgnotes is an experimental script for managing a static blog. --- README.txt | 3 + py/rlgnotes | 153 ++++++++++++++++++++++++++++++++++++++++++++ web/index.html | 1 + web/notes/notes.css | 16 +++++ 4 files changed, 173 insertions(+) create mode 100755 py/rlgnotes create mode 100644 web/notes/notes.css diff --git a/README.txt b/README.txt index 97c3141..3d6321d 100644 --- a/README.txt +++ b/README.txt @@ -19,6 +19,9 @@ are included in the Web pages. It should be run from cron, daily or so. py/rlgall.py is a module which recorder.py requires. It should be installed in /lib/python/site-packages or the equivalent location. +py/rlgnotes is a basic blog creator. It makes a blog (with RSS feed!) at +the URL /notes using text files as the source. Currently experimental. + web/ contains the static parts of the rlgallery.org website. Note that when installed, scoring/ needs to be writable by whatever user is running the recorder.py script. diff --git a/py/rlgnotes b/py/rlgnotes new file mode 100755 index 0000000..9f3ed74 --- /dev/null +++ b/py/rlgnotes @@ -0,0 +1,153 @@ +#!/usr/bin/python3 + +import os +import sys +import datetime +import rlgall +import pytz + +navbar = '' + +rsshead = """ + + +Roguelike Gallery +News and notes from the Roguelike Gallery. +http://rlgallery.org/notes/ +""" + +indexintro = """

The Gallery's blog, with news and thoughts on roguelike +games. A comment system is planned but does not exist yet. There is an +RSS feed for the benefit of robots.

+""" + +phead = rlgall.phead.replace("/scoring/scores.css", "notes.css") + +ptitle = '

{0}

\n' + +posthead = '

{0}

\n' + +datediv = '
{0}
\n' + +def noteurl(tag): + return "http://rlgallery.org/notes/" + tag + ".html" + +def itementry(tagname, value): + return " <{0}>{1}\n".format(tagname, value) + +def fmtdate(dt): + if dt == None: + dt = datetime.datetime.now(pytz.utc) + return dt.strftime("%a, %d %b %Y %H:%M:%S %z") + +def qdetag(istr): + nstart = istr.find('>') + if nstart < 0: + return istr + mstr = istr[nstart + 1:] + nend = mstr.find('<') + if nend < 0: + return mstr + return mstr[:nend] + +def mkindexfile(postdata, notedir): + indexfile = open(notedir + "/index.html", "w") + postdata.sort(key=lambda m: m[2], reverse=True) + indexfile.write(phead.format("Roguelike Gallery Notes")) + indexfile.write('\n

Roguelike Gallery Notes

\n') + indexfile.write(rlgall.navtop.format("Notes")) + indexfile.write(indexintro) + for note in postdata: + indexfile.write(posthead.format(note[1])) + datestr = note[2].strftime("%B %e, %Y") + indexfile.write(datediv.format(datestr)) + if note[3][0] == '<': + indexfile.write(note[3]) + else: + indexfile.write('

' + note[3] + '

') + indexfile.write('

More

\n'.format(note[0])) + indexfile.write(rlgall.pend) + indexfile.close() + +def mkrssfile(postdata, notedir): + rssfile = open(notedir + "/feed.rss", "w") + rssfile.write(rsshead) + nowstr = fmtdate(None) + rssfile.write("" + nowstr + "\n") + for post in postdata: + rssfile.write("\n") + rssfile.write(itementry("title", post[1])) + rssfile.write(itementry("link", noteurl(post[0]))) + rssfile.write(itementry("pubDate", fmtdate(post[2]))) + rssfile.write(itementry("description", qdetag(post[3]))) + rssfile.write("\n") + rssfile.write('
\n
\n') + +webdir = "/var/www/lighttpd/notes/" +if len(sys.argv) > 1: + srcdir = sys.argv[-1] +else: + srcdir = "." + +if "-f" in sys.argv[1:]: + force = True +else: + force = False + +metadata = [] +anynew = False + +notefiles = os.listdir(srcdir) +for note in notefiles: + pagename = webdir + note + ".html" + try: + os.stat(pagename) + except FileNotFoundError: + anynew = True + createpage = True + else: + # It already exists, only create it if given -f option + createpage = force + notefi = open(srcdir + "/" + note) + if createpage: + pagefi = open(pagename, "w") + title = notefi.readline().rstrip() + pdate = notefi.readline().rstrip() + try: + ddate = datetime.datetime.strptime(pdate, "%Y-%m-%d.%H:%M").replace(tzinfo=pytz.utc) + except ValueError: + continue + firstline = notefi.readline().rstrip() + metadata.append((note, title, ddate, firstline)) + if not createpage: + # Only the metadata is needed, for the index + notefi.close() + continue + pagefi.write(phead.format(title)) + pagefi.write('\n

Roguelike Gallery Notes

\n') + pagefi.write(navbar.format(title)) + pagefi.write(ptitle.format(title)) + pagefi.write(datediv.format(ddate.strftime("%B %e, %Y"))) + pagefi.write('
\n') + if firstline[0] == '<': + pagefi.write(firstline) + else: + pagefi.write('

' + firstline + '

') + for line in notefi: + if line == '\n': + continue + elif line[0] == '<': + pagefi.write(line) + elif line[0] == '\\': + pagefi.write(line[1:]) + else: + pagefi.write('

' + line + '

') + pagefi.write('
\n') + pagefi.write(rlgall.pend) + pagefi.close() + notefi.close() + +if force or anynew: + mkindexfile(metadata, webdir) + mkrssfile(metadata, webdir) diff --git a/web/index.html b/web/index.html index 40dc21c..d81af49 100644 --- a/web/index.html +++ b/web/index.html @@ -28,6 +28,7 @@ of historical roguelikes is being restored and made available for play on this s
  • ttyrec files
  • News

    +

    For more details, check the blog.

    Jan. 12, 2015: Some bugs in the Web app have been fixed.

    Mar. 31, 2014: A few bugs have been fixed. The length limit for player names has been increased from 10 characters to 20.

    Jan. 10, 2014: Statistical charts have been added to the scores section.

    diff --git a/web/notes/notes.css b/web/notes/notes.css new file mode 100644 index 0000000..9213cf7 --- /dev/null +++ b/web/notes/notes.css @@ -0,0 +1,16 @@ +@import url("/main.css"); + +h2.pagetitle { + text-align: center; +} + +h3.posttitle { + background-color: #E0FFE0; + text-align: center; +} + +div.datehead { + text-align: center; + font-size: 0.8em; + font-style: italic; +}