Revised AdultDVDEmpire plugin

I’m not sure how to get this back into github, so I’m posting it here. This updates the AdultDVDEmpire plugin to handle split scenes; if a file has a scene name embedded in it (like “movie movie - Scene 1 - actress” or “1 - scene name”), the plugin uses the parent directory’s name as the movie title and attempts to parse the scene name to standardize it.



Known issues:

  • Will probably be trouble if you have single files of scenes that aren’t in a directory with the name of the movie
  • Couldn’t get each file’s title to reflect Movie : Scene # : Description; apparently setting the title for one file in a directory sets it for all of them



<br />
<br />
# AdultDVDEmpire<br />
import re<br />
<br />
# URLS<br />
ADE_BASEURL = 'http://www.adultdvdempire.com/'<br />
ADE_SEARCH_MOVIES = ADE_BASEURL + 'SearchTitlesPage.aspx?SearchString=%s'<br />
ADE_MOVIE_INFO = ADE_BASEURL + '%s/'<br />
<br />
def Start():<br />
  HTTP.CacheTime = CACHE_1DAY<br />
  HTTP.SetHeader('User-agent', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)')<br />
<br />
class ADEAgent(Agent.Movies):<br />
  name = 'Adult DVD Empire'<br />
  languages = [Locale.Language.English]<br />
  primary_provider = True<br />
<br />
  def ParseScene(self,title,filename):<br />
    Log("ParseScene: checking " + title)<br />
    # Special case: if the filename has a number in brackets, that's the scene number, but Plex eats it<br />
    # so we have to check the filename rather than title<br />
    result = re.search(r"(\[\d{1,2}\])",filename)<br />
    if result:<br />
       sceneNumber = result.group(1)<br />
       return "Scene " + sceneNumber<br />
       <br />
    # If it's an intro, credits, trailer, etc, use that name<br />
    if re.search(r"(^intro$)",title,re.IGNORECASE):<br />
      return "Intro"<br />
<br />
    if re.search(r"(opening\scredits|open\scredits)",title,re.IGNORECASE):<br />
      return "Opening credits"<br />
<br />
    if re.search(r"(ending\scredits|end\scredits)",title,re.IGNORECASE):<br />
      return "End credits"<br />
<br />
    if re.search(r"^end$",title,re.IGNORECASE):<br />
      return "End"<br />
<br />
    if re.search(r"^credits$",title,re.IGNORECASE):<br />
      return "Credits"<br />
    <br />
    result = re.match(r"(s?\d{1,2}\s|scene\s?\d{1,2}|sc?\s?\d{1,2}\s|\[\d{1,2}\])(.*)",title,re.IGNORECASE)<br />
    if result:<br />
      Log("Got scene match: " + result.group(1))<br />
      scene = result.group(1)<br />
      extra = result.group(2)<br />
      # We have S01 or Scene1 or Sc1 or something, get the numbers<br />
      result = re.search(r"(\d+)",scene)<br />
      return "Scene " + scene.strip() + " : " + extra.strip()<br />
<br />
    # If the title is in the form "Movie name - Scene XX", get scene name<br />
    result = re.search(r"(.+)\s(scene\s?\d{1,2}|s\d{1,2}|sc\d{1,2})(?:\s|$|,)(.*)",title,re.IGNORECASE)<br />
    if result:<br />
        Log("Got embedded scene number" + result.group(2))<br />
        scene = result.group(2)<br />
        extra = result.group(3)<br />
        result = re.search(r"(\d+)",scene)<br />
        return "Scene " + scene.strip() + " : " + extra.strip()<br />
<br />
    return False<br />
<br />
<br />
  def search(self, results, media, lang):<br />
    title = media.name<br />
    Log("Processing " + title)<br />
    if media.primary_metadata is not None:<br />
      title = media.primary_metadata.title<br />
<br />
    if title.startswith('The '):<br />
      if title.count(':'):<br />
        title = title.split(':',1)[0].replace('The ','',1) + ', The:' + title.split(':',1)[1]<br />
      else:<br />
        title = title.replace('The ','',1) + ', The'<br />
    <br />
    sceneName = self.ParseScene(title,media.items[0].parts[0].file.decode('utf-8'))<br />
    if (sceneName):<br />
        Log("Got scene name '" + sceneName + "', using parent dir name")<br />
        file = media.items[0].parts[0].file.decode('utf-8')<br />
        pathList = file.split("/")<br />
        pathList.pop()<br />
        parentPath = pathList.pop()<br />
        Log("Parent path: " + parentPath)<br />
        # We don't want to pass in the year if it's there<br />
        title = re.sub(r'\(\d{4}\)','',parentPath)<br />
        # Replace dots and underscores with spaces<br />
        title = re.sub(r'[\s\.]',' ',title)<br />
        Log("Got title " + title)<br />
        <br />
        # If our title includes metadata, remove it<br />
        result = re.search(r"(.*?)(cheggit|bdrip|dvdrip|xxx\sdvdrip|720|split\s?scene|\(split|xvid)",title,re.IGNORECASE)<br />
        if result:<br />
          Log("Stripping scene info: " + result.group(2))<br />
          title = result.group(1)<br />
          Log("New title: " + title)<br />
<br />
        # Special case: if our title has " 1" at the end, trim that<br />
        result = re.search(r"(.*)\s1",title)<br />
        if result:<br />
          Log("Removing trailing '1'")<br />
          title = result.group(1)<br />
          Log("New title: " + title)<br />
<br />
    query = String.URLEncode(String.StripDiacritics(title.replace('-','')))<br />
<br />
    for movie in HTML.ElementFromURL(ADE_SEARCH_MOVIES % query).xpath('//div[contains(@class,"ListItem_ItemTitle")]/a'):<br />
      curName = movie.text_content().strip()<br />
      curID = movie.get('href').split('/',2)[1]<br />
      score = 100 - Util.LevenshteinDistance(title.lower(), curName.lower())<br />
      if score >= 85:<br />
        if curName.count(', The'):<br />
          curName = 'The ' + curName.replace(', The','',1)<br />
        if curName.count(', A'):<br />
          curName = 'A ' + curName.replace(', A','',1)<br />
        if sceneName:<br />
          # ISSUE: If you set one file's title to hold the scene name, all files in that dir are <br />
          # affected (you end up with 5 files called "movie : scene 5") <br />
          #curName = curName + " : " + sceneName<br />
          Log("Setting full title to " + curName)<br />
<br />
        results.Append(MetadataSearchResult(id = curID, name = curName, score = score, lang = lang))<br />
    <br />
    results.Sort('score', descending=True)<br />
<br />
  def update(self, metadata, media, lang):<br />
    html = HTML.ElementFromURL(ADE_MOVIE_INFO % metadata.id)<br />
    Log("Current metadata title: " + metadata.title)<br />
    Log("Current media title: " + media.title)<br />
    metadata.title = media.title<br />
    <br />
    # Get Thumb and Poster<br />
    try:<br />
      img = html.xpath('//div[@id="ctl00_ContentPlaceHolder_ctl00_pnl_Default"]/a/img[contains(@src,"m.jpg")]')[0]<br />
      thumbUrl = img.get('src')<br />
      thumb = HTTP.Request(thumbUrl)<br />
      posterUrl = img.get('src').replace('m.jpg','h.jpg')<br />
      metadata.posters[posterUrl] = Proxy.Preview(thumb)<br />
    except:<br />
      pass<br />
<br />
    # Get tagline<br />
    try: metadata.tagline = html.xpath('//span[@class="Item_InfoTagLine"]')[0].text_content().strip()<br />
    except: pass<br />
<br />
    # Summary.<br />
    try:<br />
      metadata.summary = html.xpath('//div[@class="Item_InfoContainer"]')[0].text_content().replace('	','').strip()<br />
      if metadata.summary.find(metadata.tagline) != -1:<br />
        metadata.summary = metadata.summary.replace(metadata.tagline, '').strip()<br />
    except: pass<br />
<br />
    # Other data.<br />
    data = {}<br />
    for div in html.xpath('//div[@class="Item_ProductInfoSectionConatiner"]/div'):<br />
      name, value = div.text_content().split(':')<br />
      data[name.strip()] = value.strip()<br />
<br />
    if data.has_key('Rating'):<br />
      metadata.content_rating = data['Rating']<br />
<br />
    if data.has_key('Studio'):<br />
      metadata.studio = data['Studio']<br />
<br />
    if data.has_key('Release Date'):<br />
      try:<br />
        metadata.originally_available_at = Datetime.ParseDate(data['Release Date']).date()<br />
        metadata.year = metadata.originally_available_at.year<br />
      except: pass<br />


So how do I add this?

I put the .bundle in the appropriate folder in Library>Application support>Plex Media Server>plugins, made a new section in plex media manager, selected adultdvdempire as the metadata agent and added a folder of appropriate material and and it scanned almost everything first time.

So do I just copy the above in a text document and name the extension .bundle? I don’t know what to do with the code above?

Is it possible to add the cast/performers of the movie to the metadata? It would then be possible to watch the movies in Plex ‘By Starring Actor’.

flow, sorry for the late reply. Unfortunately, this doesn’t work for me :frowning: Using the script above it doesn’t even get the metadata for me.



I tried adding at the beginning:



<br />
ADE_CAST_INFO = ADE_BASEURL + 'castindex/%s/'<br />




and towards the end:


<br />
    metadata.roles.clear()<br />
    htmlcast = HTML.ElementFromURL(ADE_CAST_INFO % metadata.id)<br />
    for femcast in htmlcast.xpath('//a[@class="Item_CastListPrimaryName"]/a'):<br />
      role = metadata.roles.new()<br />
      role.actor = femcast.text_content().strip()<br />
<br />
    for malecast in htmlcast.xpath('//td[@class="Item_CastListSecondaryName"]/td'):<br />
      role = metadata.roles.new()<br />
      role.actor = malecast.text_content().strip()<br />




to the original script, and it does get the usual metadata for me, but still no cast info.

Those are the only things that's needed to get the actors metadata right?

Fantastic! Tested the second code you posted, and it works like a charm.



Now I wonder if there’s a way to get the actors photos so when you browse by Starring Actors, their photos show up. I know that this feature is broken even for other movies, so I guess we’ll just wait for it to be fixed. (see http://forums.plexapp.com/index.php/topic/18666-by-starring-actor-meant-to-have-pictures/)



Anyway, thanks so much for the above code!

How do I uninstall your metadata plugin? I’ve removed every trace of it and yet it’s still showing up in the Plex Media Manager’s Metadata Agent settings.



Yes, it makes no sense. It's almost as if there is an entry in an XML or plist file that needs to be edited out.

Also, there is a folder named "com.plexapp.agents.adultdvdempire" in Metadata Combination that gets recreated if I delete it. It's driving me nuts.

hi all,



i have encountered a problem with the plugin. I tried to scrape “Prom”, but it wasn’t found by the Scraper, although it was found by manually searching it on the adultdvdempire.com.



i noticed that the movie was registered two times in the database:



Prom

Prom (DVD & Blu-Ray Combo Pack)



My suggestion is that the scraper gets confused when duplicates are found, and as a result the movies are not presented in the search form.



Is there any hint for a solution?



hansepp

Somebody have the adultdvdempire plugin with extension .bundle? Thank you

Does this agent still work? I’m trying to get data for the movie titled “7 Minutes in Heaven” but it will not show up, even when I search on “Fix incorrect match”.



For some reason the (DVD + Blu-ray Combo Packs) are harder to find. Try putting that at the end of the title and then searching.

Also, try the ExcaliburFilms agent. It gets even more metadata.

This agent is not working. I think the website changed a bit. Can a dev take a look at this?

having trouble with this plugin. plex recognizes it, but i get no metadata. anything i’m doing wrong?

This should work with the new changes.



<br />
# AdultDVDEmpire<br />
<br />
# URLS<br />
ADE_BASEURL = 'http://www.adultdvdempire.com'<br />
ADE_SEARCH_MOVIES = ADE_BASEURL + '/dvd/search?q=%s'<br />
ADE_MOVIE_INFO = ADE_BASEURL + '/%s/'<br />
<br />
def Start():<br />
  HTTP.CacheTime = CACHE_1DAY<br />
  HTTP.SetHeader('User-agent', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)')<br />
<br />
class ADEAgent(Agent.Movies):<br />
  name = 'Adult DVD Empire'<br />
  languages = [Locale.Language.English]<br />
  primary_provider = True<br />
<br />
  def search(self, results, media, lang):<br />
    title = media.name<br />
    if media.primary_metadata is not None:<br />
      title = media.primary_metadata.title<br />
<br />
<br />
    query = String.URLEncode(String.StripDiacritics(title.replace('-','')))<br />
    # Finds div with class=item<br />
    for movie in HTML.ElementFromURL(ADE_SEARCH_MOVIES % query).xpath('//p[contains(@class,"title")]/a'):<br />
      # curName = The text in the 'title' p<br />
      curName = movie.text_content().strip()<br />
      if curName.count(', The'):<br />
        curName = 'The ' + curName.replace(', The','',1)<br />
<br />
      # curID = the ID portion of the href in 'movie'<br />
      curID = movie.get('href').split('/',2)[1]<br />
      score = 100 - Util.LevenshteinDistance(title.lower(), curName.lower())<br />
      if curName.lower().count(title.lower()):<br />
        results.Append(MetadataSearchResult(id = curID, name = curName, score = 100, lang = lang))<br />
      elif (score >= 95):<br />
        results.Append(MetadataSearchResult(id = curID, name = curName, score = score, lang = lang))<br />
<br />
    results.Sort('score', descending=True)<br />
<br />
  def update(self, metadata, media, lang):<br />
    html = HTML.ElementFromURL(ADE_MOVIE_INFO % metadata.id)<br />
    metadata.title = media.title<br />
<br />
    # Get Thumb and Poster<br />
    try:<br />
      img = html.xpath('//div[@id="Boxcover"]/a/img[contains(@src,"m.jpg")]')[0]<br />
      thumbUrl = img.get('src')<br />
      thumb = HTTP.Request(thumbUrl)<br />
      posterUrl = img.get('src').replace('m.jpg','h.jpg')<br />
      metadata.posters[posterUrl] = Proxy.Preview(thumb)<br />
    except:<br />
      pass<br />
<br />
    # Get tagline<br />
    try: metadata.tagline = html.xpath('//p[@class="Tagline"]')[0].text_content().strip()<br />
    except: pass<br />
<br />
    # Summary.<br />
    try:<br />
      metadata.summary = html.xpath('//div[@class="Section Synopsis"]')[0].text_content().replace('	','').strip()<br />
      if metadata.summary.find("Synopsis") != -1:<br />
        metadata.summary = metadata.summary.replace("Synopsis", '').strip()<br />
      if metadata.summary.find(metadata.tagline) != -1:<br />
        metadata.summary = metadata.summary.replace(metadata.tagline, '').strip()<br />
    except: pass<br />
<br />
    # Other data.<br />
<br />
    data = {}<br />
    productinfo = HTML.StringFromElement(html.xpath('//div[@class="Section ProductInfo"]')[0])<br />
    productinfo = productinfo.replace('<strong>', '|')<br />
    productinfo = productinfo.replace('</strong>', ':').split('<h2>Detail</h2>')<br />
    productinfo = HTML.ElementFromString(productinfo[1]).text_content()<br />
<br />
    for div in productinfo.split('|'):<br />
      if ':' in div:<br />
        name, value = div.split(':')<br />
        data[name.strip()] = value.strip()<br />
<br />
    if data.has_key('Rating'):<br />
      metadata.content_rating = data['Rating']<br />
      #Log.Debug(data['Rating'])<br />
<br />
    if data.has_key('Studio'):<br />
      metadata.studio = data['Studio']<br />
      #Log.Debug(data['Studio'])<br />
<br />
    if data.has_key('Released'):<br />
      #Log.Debug(data['Released'])<br />
      try:<br />
        metadata.originally_available_at = Datetime.ParseDate(data['Released']).date()<br />
        metadata.year = metadata.originally_available_at.year<br />
      except: pass<br />
<br />
    #Get Cast<br />
    try:<br />
      metadata.roles.clear()<br />
      htmlcast = html.xpath('//div[@class="Section Cast"]/ul/li/a[@class="PerformerName"]')<br />
      for cast in htmlcast:<br />
        cname = cast.text_content().strip()<br />
        if ((cname != "(bio)") and (cname != "(interview)") and (len(cname) > 0)):<br />
          #Log(cname)<br />
          cpage = HTML.ElementFromURL(ADE_BASEURL + cast.get('href')).xpath('//div[@id="Headshot"]/img')[0]<br />
          cimg = cpage.get('src')<br />
          #Log(cimg)<br />
          role = metadata.roles.new()<br />
          role.actor = cname<br />
          role.photo = cimg<br />
    except: pass<br />



Yes!! worked perfectly!

Hi,



Doesnt work anymore. Can someone fix?

Still broken ??

It would REALLY be helpful if someone could take 20 seconds to explain how to find the .bundle, or create the bundle, of this agent.  I suspect the experts/code writers assume this is such an obvious answer that they don't want to bother explaining it.  Unforunately, there is no wiki for this, no pinned entry in this forum, and nowhere else I could find that explains simple things like:

- a listing of all available agents

- where to copy them to (that's been explained in this thread so thanks for that)

- whether you can just copy the code in this thread and save it with some filename, and move it to the destination, and expect it to work

- whether the code displayed in this thread is an addition to, or modification of, some existing file that we need to modify, since it is implied at the start of this thread that this is a modification.

Many thanks

p.s.  If my posting annoys you, please add a comment so I know why it does, rather than simply ignore this posting along with the previous requests for basic information.