Mercurial > hg > rlgallery-misc
comparison py/rlgnotes @ 61:5b4ff5680037
Add a basic blog manager.
rlgnotes is an experimental script for managing a static blog.
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 30 Jan 2015 09:25:32 -0500 |
| parents | |
| children | d417016bbf73 |
comparison
equal
deleted
inserted
replaced
| 60:876786c55450 | 61:5b4ff5680037 |
|---|---|
| 1 #!/usr/bin/python3 | |
| 2 | |
| 3 import os | |
| 4 import sys | |
| 5 import datetime | |
| 6 import rlgall | |
| 7 import pytz | |
| 8 | |
| 9 navbar = '<div class="nav"><a href="/">rlgallery.org</a> -> \ | |
| 10 <a href="/notes/">Notes</a> -> {0}</div>' | |
| 11 | |
| 12 rsshead = """<?xml version="1.0" encoding="UTF-8"?> | |
| 13 <rss version="2.0"> | |
| 14 <channel> | |
| 15 <title>Roguelike Gallery</title> | |
| 16 <description>News and notes from the Roguelike Gallery.</description> | |
| 17 <link>http://rlgallery.org/notes/</link> | |
| 18 """ | |
| 19 | |
| 20 indexintro = """<p>The Gallery's blog, with news and thoughts on roguelike | |
| 21 games. A comment system is planned but does not exist yet. There is an | |
| 22 <a href="feed.rss">RSS feed</a> for the benefit of robots.</p> | |
| 23 """ | |
| 24 | |
| 25 phead = rlgall.phead.replace("/scoring/scores.css", "notes.css") | |
| 26 | |
| 27 ptitle = '<h2 class="pagetitle">{0}</h2>\n' | |
| 28 | |
| 29 posthead = '<h3 class="posttitle">{0}</h2>\n' | |
| 30 | |
| 31 datediv = '<div class="datehead">{0}</div>\n' | |
| 32 | |
| 33 def noteurl(tag): | |
| 34 return "http://rlgallery.org/notes/" + tag + ".html" | |
| 35 | |
| 36 def itementry(tagname, value): | |
| 37 return " <{0}>{1}</{0}>\n".format(tagname, value) | |
| 38 | |
| 39 def fmtdate(dt): | |
| 40 if dt == None: | |
| 41 dt = datetime.datetime.now(pytz.utc) | |
| 42 return dt.strftime("%a, %d %b %Y %H:%M:%S %z") | |
| 43 | |
| 44 def qdetag(istr): | |
| 45 nstart = istr.find('>') | |
| 46 if nstart < 0: | |
| 47 return istr | |
| 48 mstr = istr[nstart + 1:] | |
| 49 nend = mstr.find('<') | |
| 50 if nend < 0: | |
| 51 return mstr | |
| 52 return mstr[:nend] | |
| 53 | |
| 54 def mkindexfile(postdata, notedir): | |
| 55 indexfile = open(notedir + "/index.html", "w") | |
| 56 postdata.sort(key=lambda m: m[2], reverse=True) | |
| 57 indexfile.write(phead.format("Roguelike Gallery Notes")) | |
| 58 indexfile.write('<body>\n<h1>Roguelike Gallery Notes</h1>\n') | |
| 59 indexfile.write(rlgall.navtop.format("Notes")) | |
| 60 indexfile.write(indexintro) | |
| 61 for note in postdata: | |
| 62 indexfile.write(posthead.format(note[1])) | |
| 63 datestr = note[2].strftime("%B %e, %Y") | |
| 64 indexfile.write(datediv.format(datestr)) | |
| 65 if note[3][0] == '<': | |
| 66 indexfile.write(note[3]) | |
| 67 else: | |
| 68 indexfile.write('<p>' + note[3] + '</p>') | |
| 69 indexfile.write('<p><a href="{0}.html">More</a></p>\n'.format(note[0])) | |
| 70 indexfile.write(rlgall.pend) | |
| 71 indexfile.close() | |
| 72 | |
| 73 def mkrssfile(postdata, notedir): | |
| 74 rssfile = open(notedir + "/feed.rss", "w") | |
| 75 rssfile.write(rsshead) | |
| 76 nowstr = fmtdate(None) | |
| 77 rssfile.write("<lastBuildDate>" + nowstr + "</lastBuildDate>\n") | |
| 78 for post in postdata: | |
| 79 rssfile.write("<item>\n") | |
| 80 rssfile.write(itementry("title", post[1])) | |
| 81 rssfile.write(itementry("link", noteurl(post[0]))) | |
| 82 rssfile.write(itementry("pubDate", fmtdate(post[2]))) | |
| 83 rssfile.write(itementry("description", qdetag(post[3]))) | |
| 84 rssfile.write("</item>\n") | |
| 85 rssfile.write('</channel>\n</rss>\n') | |
| 86 | |
| 87 webdir = "/var/www/lighttpd/notes/" | |
| 88 if len(sys.argv) > 1: | |
| 89 srcdir = sys.argv[-1] | |
| 90 else: | |
| 91 srcdir = "." | |
| 92 | |
| 93 if "-f" in sys.argv[1:]: | |
| 94 force = True | |
| 95 else: | |
| 96 force = False | |
| 97 | |
| 98 metadata = [] | |
| 99 anynew = False | |
| 100 | |
| 101 notefiles = os.listdir(srcdir) | |
| 102 for note in notefiles: | |
| 103 pagename = webdir + note + ".html" | |
| 104 try: | |
| 105 os.stat(pagename) | |
| 106 except FileNotFoundError: | |
| 107 anynew = True | |
| 108 createpage = True | |
| 109 else: | |
| 110 # It already exists, only create it if given -f option | |
| 111 createpage = force | |
| 112 notefi = open(srcdir + "/" + note) | |
| 113 if createpage: | |
| 114 pagefi = open(pagename, "w") | |
| 115 title = notefi.readline().rstrip() | |
| 116 pdate = notefi.readline().rstrip() | |
| 117 try: | |
| 118 ddate = datetime.datetime.strptime(pdate, "%Y-%m-%d.%H:%M").replace(tzinfo=pytz.utc) | |
| 119 except ValueError: | |
| 120 continue | |
| 121 firstline = notefi.readline().rstrip() | |
| 122 metadata.append((note, title, ddate, firstline)) | |
| 123 if not createpage: | |
| 124 # Only the metadata is needed, for the index | |
| 125 notefi.close() | |
| 126 continue | |
| 127 pagefi.write(phead.format(title)) | |
| 128 pagefi.write('<body>\n<h1>Roguelike Gallery Notes</h1>\n') | |
| 129 pagefi.write(navbar.format(title)) | |
| 130 pagefi.write(ptitle.format(title)) | |
| 131 pagefi.write(datediv.format(ddate.strftime("%B %e, %Y"))) | |
| 132 pagefi.write('<div class="content">\n') | |
| 133 if firstline[0] == '<': | |
| 134 pagefi.write(firstline) | |
| 135 else: | |
| 136 pagefi.write('<p>' + firstline + '</p>') | |
| 137 for line in notefi: | |
| 138 if line == '\n': | |
| 139 continue | |
| 140 elif line[0] == '<': | |
| 141 pagefi.write(line) | |
| 142 elif line[0] == '\\': | |
| 143 pagefi.write(line[1:]) | |
| 144 else: | |
| 145 pagefi.write('<p>' + line + '</p>') | |
| 146 pagefi.write('</div>\n') | |
| 147 pagefi.write(rlgall.pend) | |
| 148 pagefi.close() | |
| 149 notefi.close() | |
| 150 | |
| 151 if force or anynew: | |
| 152 mkindexfile(metadata, webdir) | |
| 153 mkrssfile(metadata, webdir) |
