Advertisement
Guest User

magu

a guest
Jan 30th, 2010
518
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.69 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. # Episode rename 0.8 - Copyright 2008 Stavros Korokithakis
  4. # Heavily modified by Rafael Fonseca
  5. # Released under the GNU GPL.
  6. # You can find the latest version at http://www.poromenos.org
  7.  
  8. import urllib
  9. import urllib2
  10. import optparse
  11. import re
  12. import os
  13. import sys
  14. import subprocess
  15. import random
  16. import shutil
  17. import htmlentitydefs
  18. import hashlib
  19. from datetime import date
  20.  
  21. class Show:
  22.     def __init__(self, title="", rating=0):
  23.         self.title = title
  24.         self.attributes = {}
  25.         self.episodes = {}
  26.  
  27. def search_show(name):
  28.     """Search Google for the page best matching the given show name."""
  29.     google_url = "http://www.google.com/search?q=site%%3Aepguides.com+%s" % urllib.quote(name)
  30.  
  31.     # Bastard Google...
  32.     request = urllib2.Request(google_url)
  33.     request.add_header("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4")
  34.     page = urllib2.urlopen(request).read()
  35.  
  36.     try:
  37.         show_id = re.search("epguides.com\/(.*?)\/", page).group(1)
  38.     except AttributeError:
  39.         try:
  40.             show_id = re.search("epguides.com\/(.*?)\/", page).group(0)
  41.         except AttributeError:
  42.             print "Could not find show title for %s, cannot continue." % name
  43.             sys.exit()
  44.  
  45.     return show_id
  46.  
  47. def parse_epguides(page):
  48.     """Parse an epguides page."""
  49.     page = page.replace("\n", "")
  50.     page = page.replace("'","'")
  51.     show = Show()
  52.     d = date.today()
  53.     try:
  54.         show.title = re.search("""<h1><a href="http://.*?">(.*?)</a></h1>""", page).groups()[0]
  55.     except AttributeError:
  56.         print "Could not find show title, cannot continue."
  57.         sys.exit()
  58.  
  59.     matches = re.search("""<td>aired from: <em>.* (\d+)</em><br />to: <em>.*</em></td>""", page)
  60.     try:
  61.         year = matches.group(1)
  62.         year = 2000 + int(year)
  63.         if year > d.year:
  64.             year = year - 100
  65.     except IndexError:
  66.         year = None
  67.  
  68.     show.attributes["year"] = year
  69.  
  70.     episodes = re.findall("\d+. +(?P<season>\d+) *\- *(?P<episode>\d+).*?(?P<day>\d+)(?:\/|\s)+(?P<month>[A-Za-z]+)(?:\/|\s)+(?P<year>\d+) +(?:<a [^>]+><img [^\r\n]+></a>)? ?<a [^>]*>(?P<name>.*?)</a>", page)
  71.  
  72.     month_dict = {"Jan": 1,
  73.                   "Feb": 2,
  74.                   "Mar": 3,
  75.                   "Apr": 4,
  76.                   "May": 5,
  77.                   "Jun": 6,
  78.                   "Jul": 7,
  79.                   "Aug": 8,
  80.                   "Sep": 9,
  81.                   "Oct": 10,
  82.                   "Nov": 11,
  83.                   "Dec": 12}
  84.  
  85.     for season, episode, day, month, year, name in episodes:
  86.         show.episodes[(int(season), int(episode))] = {"title": name}
  87.         #print "DEBUG: s%s e%s" % (season, episode)
  88.  
  89.         year = 2000 + int(year)
  90.         if year > d.year:
  91.             year = year - 100
  92.  
  93.         try:
  94.             release_date = "%s-%02d-%02dT12:00:00Z" % (int(year),month_dict[month],int(day))
  95.         except TypeError:
  96.             continue
  97.  
  98.         show.episodes[(int(season), int(episode))]["year"] = release_date
  99.  
  100.     return show
  101.  
  102. def rename_file(filename, show, file_mask, preview=False, use_ap=False, force=False):
  103.     series_parser = [
  104.         re.compile("^.*?s *(?P<series>\d+) *e *(?P<episode>\d+).*\.(?P<extension>.*?)$", re.IGNORECASE),
  105.         re.compile("^.*?(?P<series>\d+)x(?P<episode>\d+).*\.(?P<extension>.*?)$", re.IGNORECASE),
  106.         re.compile("^(?:.*?\D|)(?P<series>\d{1,2})(?P<episode>\d{2})(?:\D.*|)\.(?P<extension>.*?)$", re.IGNORECASE),
  107.         ]
  108.  
  109.     for parser in series_parser:
  110.         matches = parser.search(filename)
  111.         try:
  112.             match_dict = matches.groupdict()
  113.             break
  114.         except AttributeError:
  115.             continue
  116.     else:
  117.         return
  118.  
  119.     series = int(match_dict["series"])
  120.     episode = int(match_dict["episode"])
  121.     extension = match_dict["extension"]
  122.  
  123.     info_dictionary = {"show": show.title,
  124.                        "series_num": series,
  125.                        "episode_num": episode,
  126.                        "extension": extension}
  127.  
  128.     try:
  129.         info_dictionary.update(show.episodes[(series, episode)])
  130.         new_filename = file_mask % info_dictionary
  131.     except KeyError:
  132.         print 'Episode name for "%s" not found.' % filename
  133.         sys.exit()
  134.  
  135.     new_filename = re.sub("[\\\/\:\*\"\?\<\>\|]", "", new_filename)
  136.     if new_filename == filename:
  137.         if not force:
  138.             print 'No changes to "%s".' % filename
  139.             sys.exit()
  140.  
  141.     try:
  142.         print "Renaming \"%s\" to \"%s\"..." % (filename, new_filename.encode("ascii", "replace"))
  143.     except UnicodeDecodeError:
  144.         print "Renaming \"%s\" to \"%s\"..." % (filename, new_filename)    
  145.  
  146.     if not preview:
  147.         if use_ap:
  148.             # The temp_filename shenanigans are necessary because AP sometimes
  149.             # chokes if it's set to overwrite the file.
  150.             temp_filename = filename + str(random.randint(10000, 99999))
  151.             arguments = ["AtomicParsley",
  152.                          filename,
  153.                          "-o", temp_filename,
  154.                          "--TVShowName", show.title,
  155.                          "--stik", "TV Show",
  156.                          "--TVSeasonNum", str(series),
  157.                          "--TVEpisodeNum", str(episode),
  158.                          "--TVEpisode", show.episodes[(series, episode)]["title"],
  159.                          "--title", show.episodes[(series, episode)]["title"]]
  160.             if "year" in show.episodes[(series, episode)]:
  161.                 arguments.extend(["--year", show.episodes[(series, episode)]["year"]])
  162.             elif "year" in show.attributes:
  163.                 arguments.extend(["--year", show.attributes["year"]])
  164.  
  165.             artwork_file = None
  166.             if "artwork" in show.episodes[(series, episode)]:
  167.                 artwork_filename = hashlib.md5(str(random.randint(10000, 100000))).hexdigest()
  168.                 artwork_file = open(artwork_filename, "wb")
  169.                 artwork_file.write(show.episodes[(series, episode)]["artwork"])
  170.                 artwork_file.close()
  171.                 arguments.extend(["--artwork", "REMOVE_ALL", "--artwork", artwork_filename])
  172.             elif "artwork" in show.attributes:
  173.                 artwork_filename = hashlib.md5(str(random.randint(10000, 100000))).hexdigest()
  174.                 artwork_file = open(artwork_filename, "wb")
  175.                 artwork_file.write(show.attributes["artwork"])
  176.                 artwork_file.close()
  177.                 arguments.extend(["--artwork", "REMOVE_ALL", "--artwork", artwork_filename])
  178.  
  179.             proc = subprocess.Popen(tuple(arguments))
  180.             proc.wait()
  181.  
  182.             if artwork_file:
  183.                 os.remove(artwork_filename)
  184.  
  185.             try:
  186.                 os.rename(temp_filename, new_filename)
  187.             except:
  188.                 print "There was an error while renaming the file."
  189.                 sys.exit()
  190.  
  191.             if new_filename != filename:
  192.                 os.remove(filename)
  193.         else:
  194.             try:
  195.                 os.rename(filename, new_filename)
  196.             except:
  197.                 print "There was an error while renaming the file."
  198.                 sys.exit()
  199.  
  200. def analyze_file(filename,options):
  201. #    title_parser = re.compile("(?P<title>^.*)(s|\.|-)(?P<series>\d+)(e|x)(?P<episode>\d+).*\.(?P<extension>.*?)$", re.IGNORECASE)
  202.  
  203.     title_parser = [
  204.         re.compile("^(?P<title>.*?)s *(?P<series>\d+) *e *(?P<episode>\d+).*\.(?P<extension>.*?)$", re.IGNORECASE),
  205.         re.compile("^(?P<title>.*?)(?P<series>\d+)x(?P<episode>\d+).*\.(?P<extension>.*?)$", re.IGNORECASE),
  206.         re.compile("^(?P<title>.*?\D|)(?P<series>\d{1,2})(?P<episode>\d{2})(?:\D.*|)\.(?P<extension>.*?)$", re.IGNORECASE),
  207.         ]
  208.     for parser in title_parser:
  209.         matches = parser.search(filename)
  210.         try:
  211.             title_dict = matches.groupdict()
  212.             break
  213.         except AttributeError:
  214.             continue
  215.     else:
  216.         return
  217.  
  218.     title = title_dict["title"]
  219.     title = title.strip()
  220.     title = title.replace('-','.')
  221.     title = title.replace(' ','.')
  222.     if title.endswith('.'):
  223.         title = title.rstrip('.')
  224.     title = title.strip()
  225.     title = title.split('.')
  226.  
  227.     show_id = search_show("+".join(title))
  228.  
  229.     if not show_id:
  230.         return
  231.  
  232.     page_url = "http://epguides.com/%s/" % show_id
  233.     request = urllib2.Request(page_url)
  234.     if options.use_cookies:
  235.         request.add_header("Cookie","ListDisplay=tvrage.com")
  236.  
  237.     try:
  238.         page = urllib2.urlopen(request).read()
  239.     except urllib2.HTTPError, error:
  240.         print "An HTTP error occurred, HTTP code %s." % error.code
  241.         sys.exit()
  242.    
  243.     show = parse_epguides(page)
  244.    
  245.     if not show:
  246.         sys.exit()
  247.    
  248.     rename_file(filename, show, options.mask, options.preview, options.use_atomic_parsley, options.force)
  249.  
  250. def main():
  251.     parser = optparse.OptionParser(usage="%prog [options] <filename>", version="Episode rename 0.8\nThis program is released under the GNU GPL.")
  252.     parser.add_option("-p",
  253.                       "--preview",
  254.                       dest="preview",
  255.                       action="store_true",
  256.                       help="don't actually rename anything")
  257.     parser.add_option("-a",
  258.                       "--use-atomic-parsley",
  259.                       dest="use_atomic_parsley",
  260.                       action="store_true",
  261.                       help="use AtomicParsley to fill in the files' tags")
  262.     parser.add_option("-f",
  263.                       "--force",
  264.                       dest="force",
  265.                       action="store_true",
  266.                       help="force renaming even if filename doesn't change")
  267.     parser.add_option("-c",
  268.                       "--cookies",
  269.                       dest="use_cookies",
  270.                       action="store_true",
  271.                       help="use site cookies for TVRage")
  272.     parser.add_option("-m",
  273.                       "--mask",
  274.                       dest="mask",
  275.                       default="%(show)s - S%(series_num)02dE%(episode_num)02d - %(title)s.%(extension)s",
  276.                       metavar="MASK",
  277.                       action="store",
  278.                       type="string",
  279.                       help="the filename mask to use when renaming (default: \"%default\")")
  280.     parser.set_defaults(preview=False)
  281.     parser.set_defaults(force=False)
  282.     parser.set_defaults(use_cookies=False)
  283.     (options, arguments)=parser.parse_args()
  284.  
  285.     if len(arguments) != 1:
  286.         parser.print_help()
  287.         sys.exit(1)
  288.  
  289.     filename = arguments[0]
  290.     filename = filename.replace('./','')
  291.     analyze_file(filename,options)
  292.  
  293.     return sys.stdout
  294.  
  295. if __name__ == "__main__":
  296.     main()
  297.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement