Skip to content

Instantly share code, notes, and snippets.

@woolsweater
Last active December 12, 2015 12:39
Show Gist options
  • Save woolsweater/4773918 to your computer and use it in GitHub Desktop.
Save woolsweater/4773918 to your computer and use it in GitHub Desktop.
Display recently played tracks on All Classical.
import sys
import urllib
import re
import argparse
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
parser = argparse.ArgumentParser(description="Display recently played tracks on All Classical.")
parser.add_argument("-p", "--performer", action="store_true",
help="Include performer information in output")
parser.add_argument("indexes", default="0", nargs='?', metavar="M[{..|-}N]",
help="(optional) Indexes of tracks to display. Either a single number or a range, indicated by a number followed by either '..' or '-' and another number. The most recent track is 0; a range whose start is higher than its end is not supported.")
# Switch to use cached file rather than getting data from the net.
# Due to its _optional_ capture of a filename, this must be the last flag in
# the command line.
parser.add_argument("--use-cached", nargs='?', dest="cache",
const="sample/allclassicalplaylist.txt",
help=argparse.SUPPRESS)
arguments = parser.parse_args()
start = end = None
try:
start = int(arguments.indexes)
# Not an integer? Could be a sequence specifier "n..x" or "n-x"
except ValueError:
match = re.match(r"(\d+)([.]{2}|-)(\d+)", arguments.indexes)
if match:
start = int(match.group(1))
end = int(match.group(3)) + 1
# Can't figure it out? Use defaults.
start = start or 0
end = end or start + 1
if arguments.cache:
with open(arguments.cache, 'r') as f:
playlist = f.read()
else:
playlist = urllib.urlopen("http://www.allclassical.org/assets/playlist/playlistFormat.php").read()
playsoup = BeautifulSoup(playlist)
# Some programs don't have track listings. Check age of last entry; if it's
# too old, warn that the info might not be accurate.
if not arguments.cache:
last_date = datetime.strptime(playsoup.find("span", "pl_time").string,
"%I:%M %p")
now = datetime.now()
last_date = datetime.combine(now, last_date.time())
if now - last_date > timedelta(minutes=30):
print "The last time associated with a track in the playlist is more than 30 minutes ago. This might not actually be the most recently played piece.\n"
get_span_list = (lambda tag_name:
[tag.string for tag in playsoup.find_all("span",
"pl_"+tag_name)[start:end]])
# Slicing already handles out-of-bounds indexes, so no need to adjust them
titles = get_span_list("title")
composers = get_span_list("composer")
performers = (get_span_list("ensemble") if arguments.performer else
["" for i in range(start, end)])
perf_by = ", performed by " if arguments.performer else ""
# Composer's name is last name first unless Anonymous
composers = [' '.join(reversed(composer.split(', '))) for composer
in composers if not composer.startswith("Anonymous")]
for title, composer, performer in zip(titles, composers, performers):
print u'"{0}" by {1}{2}{3}'.format(title, composer, perf_by, performer)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment