TITLE: Updating pypodd to run .opml files
DATE: 2018-04-07
AUTHOR: John L. Godlee
====================================================================


Pypodd

OPML (Outline Processor Markup Language) is a type of .xml which is
often used to hold information for RSS feeds. Lots of podcast
aggregators use the OPML format to allow exporting of your list of
podcasts, including the one that I use on my phone, PocketCasts. So
I wanted to extend the functionality of my pypodd program so that
it would be able to use an OPML list of subscriptions instead of
the .csv that I put together in a quite ad hoc manner when I was
writing the program.

 [PocketCasts]: https://play.pocketcasts.com

Here is a sample of what an OPML file looks like:

   <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
   <opml version="1.0">
     <head>
       <title>Pocket Casts Feeds</title>
     </head>
     <body>
       <outline text="feeds">
         <outline type="rss" text="Hospital Records Podcast"
xmlUrl="http://podcast.hospitalrecords.com/HospitalRecordsPodcast.xm
l" />
         <outline type="rss" text="Slow Radio"
xmlUrl="https://podcasts.files.bbci.co.uk/p05k5bq0.rss" />
         <outline type="rss" text="The Heart"
xmlUrl="http://feeds.theheartradio.org/TheHeartRadio" />
         <outline type="rss" text="Gardeners' Question Time"
xmlUrl="https://podcasts.files.bbci.co.uk/b006qp2f.rss" />
       </outline>
     </body>
   </opml>

I found that actually, thanks to a package that has already been
written called listparser, adding this feature was REALLY REALLY
EASY!

 [listparser]: https://pythonhosted.org/listparser/

I wrapped the existing .csv import method in an if else statement,
saying that if the file extension was csv proceed with the .csv
import method, but if the file extension was .xml, use the other
import method. The code looks like this:

   if subsLoc.endswith("csv"):
     with open(subsLoc) as f:
       subs = csv.reader(f)
       subs = list(subs)
     # Split subs into URLs and titles
     urlList = [x[0] for x in subs]
     subList = [x[1] for x in subs]
   elif subsLoc.endswith("xml"):
     with open(subsLoc) as f:
       subs = listparser.parse(f)
     urlList = [x.url for x in subs.feeds]
     subList = [x.title for x in subs.feeds]
   else:
     raw_input("Subscriptions list is not `.csv` or OPML `.xml`,
exiting ...")
     sys.exit(0)

Also note the "quit" if the designated file doesn't include either
of the two specified extensions. Maybe to be super bulletproof I
should do a check to see if the .xml file includes <opml
version="">, as I suppose there are lots of different .xml formats.