I decided to remove the calendar from my blog’s sidebar, and replace it with a “recent posts” list. I realized that it’s not very helpful, since readers aren’t so much interested in when I posted as what I posted about.
There was no pyblosxom plugin to do this, so I rolled up my sleeves and learned some more Python, referring to the Pyblosxom API documentation along the way. The resultant plugin is simple, although I had to fill in the gaps in the API docs through trial and error.
The code I wrote is below. Note that I hardcoded the flavour type (1024px), but I believe there’s an value in the entry dictionary I could have gotten it from.
from Pyblosxom import tools from Pyblosxom import pyblosxom import time, re
def cb_prepare(args): request = args["request"] data = request.getData() entry_list = data["entry_list"] config = request.getConfiguration() root = config["datadir"] s="" txt_dict = {} for txt in tools.Walk(request, root, pattern=re.compile('.*\.txt$')): timetuple = tools.filestat(request, txt) txt_dict[time.strftime("%y%m%d%H%M",timetuple)]=txt keys = txt_dict.keys() keys.sort() keys.reverse() url_list = [] for k in keys: path = re.sub(root, "", re.sub(".txt$", "", txt_dict[k])) title = pyblosxom.blosxom_entry_parser(txt_dict[k],request)['title'] url_list.append("<li><a href='" + path + ".1024px'>" + title + "</a>") url_list = [url_list[x] for x in range(0,19)] for url in url_list: s += url data['recentPosts'] = s
Around the same time, I had the idea of adding a “voting” mechanism to allow people who don’t have anything to say (comment) to still indicate which entries are interesting. I figured an easy approach would be to add voting buttons that triggered an AJAX-style HTTP request to special URLs, which would show up in the Apache logs and could later be parsed out. Being unfamiliar with Python, I could just focus on reading data in the plugin and save on code to tally votes (I was feeling lazy at the time).
Shortly thereafter, I got a blog comment:
Name: Gunfus
Entry URL: http://blog.astradele.com/life/Why-blog-.2008-02-01-14-50
I don’t think your yes/no is working to well. If you click it it dissapears (this is fine), if you reload the page it shows again (this is aceptable), once you reload, the counter is at 0/0 (this is expected?)
I thought I tested it properly, but… So I got into it again and wrote the solution completely in Python. At least I’m getting more familiar with the language. The solution still uses a custom URL format that don’t resolve to an actual page, but it’s the Pyblosxom plugin that notes the URI, checks to see if it’s similiar to an existing entry, creates files to track the IP addresses of votes on a per entry basis, and generates tallies.
I considered trying to devise a way to auto-refresh the tally instead of just hiding the voting “bar”, but upon consideration I wasn’t up to the effort it would take on the Python side.
The code:
import sys, StringIO, os, os.path, re
def verify_installation(request): return 1 def include(req, filename): """ This takes in one argument--a filename. It opens the file, reads in the contents, and returns them as the value of this variable. (It actually takes in two, but one of them is provided by PyBlosxom.) """ if not filename.startswith(os.sep): data = req.getData() basedir = data["root_datadir"] if data.has_key("bl_type") and data["bl_type"] == "file": basedir = os.path.dirname(basedir) filename = os.path.normpath(basedir + os.sep + filename) try: f = open(filename, "r") lines = "".join(f.readlines()) f.close() return eval_python_blocks(req, lines) except: return "" def cb_logrequest(args): import os, time http = args['request'].getHttp() config = args['request'].getConfiguration() request_uri = http['REQUEST_URI'] remote_addr = http['REMOTE_ADDR'] entry_name = re.compile("^/vote_(yes|no)(/.*)\..*$").sub(r"\2",request_uri) if (os.path.exists(config['datadir'] + entry_name + ".txt")): try: os.makedirs(config['datadir'] + "/votes" + re.compile("^(.*)/.*$").sub(r"\1", entry_name)) except: pass if (re.compile("^/vote_yes").match(request_uri)): vote_file=config['datadir'] + "/votes" + entry_name + ".yes" else: vote_file=config['datadir'] + "/votes" + entry_name + ".no" is_dupe=False if (os.path.exists(vote_file)): f=open(vote_file, "r") for line in f: is_dupe = is_dupe or re.compile(remote_addr).match(line) f.close() if (not is_dupe): f=open(vote_file, "a") f.write(remote_addr + "\n") f.close() def cb_story(args): """ """ entry = args["entry"] request = args["request"] config = request.getConfiguration() http = request.getHttp() entry_filename = entry.getId() yes_votes_file = re.compile(".txt$").sub(".yes",re.compile("^" + config['datadir']).sub(config['datadir'] + "/votes",entry_filename)) no_votes_file = re.compile(".txt$").sub(".no",re.compile("^" + config['datadir']).sub(config['datadir'] + "/votes",entry_filename)) entry['vote_yes_url'] = "/vote_yes/" + entry['file_path'] + "." + entry['flavour'] entry['vote_no_url'] = "/vote_no/" + entry['file_path'] + "." + entry['flavour'] request_uri = request.getHttp()["REQUEST_URI"] remote_addr = request.getHttp()["REMOTE_ADDR"] count=0 if (os.path.exists(yes_votes_file)): f = open(yes_votes_file, "r") for line in f: count += 1 f.close() entry["yes_votes_count"]=str(count) count=0 if (os.path.exists(no_votes_file)): f = open(no_votes_file, "r") for line in f: count += 1 f.close() entry["no_votes_count"]=str(count)