Add a basic blog manager.
rlgnotes is an experimental script for managing a static blog.
This commit is contained in:
parent
8fc67392d9
commit
172d389ba5
4 changed files with 173 additions and 0 deletions
|
|
@ -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<x.y>/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.
|
||||
|
|
|
|||
153
py/rlgnotes
Executable file
153
py/rlgnotes
Executable file
|
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import rlgall
|
||||
import pytz
|
||||
|
||||
navbar = '<div class="nav"><a href="/">rlgallery.org</a> -> \
|
||||
<a href="/notes/">Notes</a> -> {0}</div>'
|
||||
|
||||
rsshead = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>Roguelike Gallery</title>
|
||||
<description>News and notes from the Roguelike Gallery.</description>
|
||||
<link>http://rlgallery.org/notes/</link>
|
||||
"""
|
||||
|
||||
indexintro = """<p>The Gallery's blog, with news and thoughts on roguelike
|
||||
games. A comment system is planned but does not exist yet. There is an
|
||||
<a href="feed.rss">RSS feed</a> for the benefit of robots.</p>
|
||||
"""
|
||||
|
||||
phead = rlgall.phead.replace("/scoring/scores.css", "notes.css")
|
||||
|
||||
ptitle = '<h2 class="pagetitle">{0}</h2>\n'
|
||||
|
||||
posthead = '<h3 class="posttitle">{0}</h2>\n'
|
||||
|
||||
datediv = '<div class="datehead">{0}</div>\n'
|
||||
|
||||
def noteurl(tag):
|
||||
return "http://rlgallery.org/notes/" + tag + ".html"
|
||||
|
||||
def itementry(tagname, value):
|
||||
return " <{0}>{1}</{0}>\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('<body>\n<h1>Roguelike Gallery Notes</h1>\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('<p>' + note[3] + '</p>')
|
||||
indexfile.write('<p><a href="{0}.html">More</a></p>\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("<lastBuildDate>" + nowstr + "</lastBuildDate>\n")
|
||||
for post in postdata:
|
||||
rssfile.write("<item>\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("</item>\n")
|
||||
rssfile.write('</channel>\n</rss>\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('<body>\n<h1>Roguelike Gallery Notes</h1>\n')
|
||||
pagefi.write(navbar.format(title))
|
||||
pagefi.write(ptitle.format(title))
|
||||
pagefi.write(datediv.format(ddate.strftime("%B %e, %Y")))
|
||||
pagefi.write('<div class="content">\n')
|
||||
if firstline[0] == '<':
|
||||
pagefi.write(firstline)
|
||||
else:
|
||||
pagefi.write('<p>' + firstline + '</p>')
|
||||
for line in notefi:
|
||||
if line == '\n':
|
||||
continue
|
||||
elif line[0] == '<':
|
||||
pagefi.write(line)
|
||||
elif line[0] == '\\':
|
||||
pagefi.write(line[1:])
|
||||
else:
|
||||
pagefi.write('<p>' + line + '</p>')
|
||||
pagefi.write('</div>\n')
|
||||
pagefi.write(rlgall.pend)
|
||||
pagefi.close()
|
||||
notefi.close()
|
||||
|
||||
if force or anynew:
|
||||
mkindexfile(metadata, webdir)
|
||||
mkrssfile(metadata, webdir)
|
||||
|
|
@ -28,6 +28,7 @@ of historical roguelikes is being restored and made available for play on this s
|
|||
<li><a href="/archive.cgi">ttyrec files</a></li>
|
||||
</ul>
|
||||
<h2>News</h2>
|
||||
<p>For more details, check <a href="/notes/">the blog</a>.</p>
|
||||
<p><strong>Jan. 12, 2015</strong>: Some bugs in the Web app have been fixed.</p>
|
||||
<p><strong>Mar. 31, 2014</strong>: A few bugs have been fixed. The length limit for player names has been increased from 10 characters to 20.</p>
|
||||
<p><strong>Jan. 10, 2014</strong>: Statistical charts have been added to the <a href="/scoring/">scores section</a>.</p>
|
||||
|
|
|
|||
16
web/notes/notes.css
Normal file
16
web/notes/notes.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue