text: # -*- coding: utf-8 -*-
  
  # Copyright 2011 Fanficdownloader team
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  
  # Software: eFiction
  import time
  import logging
  logger = logging.getLogger(__name__)
  import re
  import urllib
  import urllib2
  
  from .. import BeautifulSoup as bs
  from ..htmlcleanup import stripHTML
  from .. import exceptions as exceptions
  
  from base_adapter import BaseSiteAdapter,  makeDate
  
  class PotionsAndSnitchesOrgSiteAdapter(BaseSiteAdapter):
  
      def __init__(self, config, url):
          BaseSiteAdapter.__init__(self, config, url)
          self.story.setMetadata('siteabbrev','pns')
          self.decode = ["Windows-1252",
                         "utf8"] # 1252 is a superset of iso-8859-1.
                                 # Most sites that claim to be
                                 # iso-8859-1 (and some that claim to be
                                 # utf8) are really windows-1252.
          
          # get storyId from url--url validation guarantees query is only sid=1234
          self.story.setMetadata('storyId',self.parsedUrl.query.split('=',)[1])
          
          
          # normalized story URL.
          self._setURL('http://' + self.getSiteDomain() + '/fanfiction/viewstory.php?sid='+self.story.getMetadata('storyId'))
  
              
      @staticmethod
      def getSiteDomain():
          return 'www.potionsandsnitches.org'
  
      @classmethod
      def getAcceptDomains(cls):
          return ['potionsandsnitches.org','potionsandsnitches.net']
  
      @classmethod
      def getSiteExampleURLs(cls):
          return "http://www.potionsandsnitches.org/fanfiction/viewstory.php?sid=1234"
  
      def getSiteURLPattern(self):
          return re.escape("http://")+r"(www\.)?potionsandsnitches\.(net|org)/fanfiction/viewstory\.php\?sid=\d+$"
  
      def extractChapterUrlsAndMetadata(self):
  
          url = self.url+'&index=1'
          logger.debug("URL: "+url)
  
          try:
              data = self._fetchUrl(url)
          except urllib2.HTTPError, e:
              if e.code == 404:
                  raise exceptions.StoryDoesNotExist(self.url)
              else:
                  raise e
  
          if "Access denied. This story has not been validated by the adminstrators of this site." in data:
              raise exceptions.FailedToDownload(self.getSiteDomain() +" says: Access denied. This story has not been validated by the adminstrators of this site.")
              
          # use BeautifulSoup HTML parser to make everything easier to find.
          soup = bs.BeautifulSoup(data)
  
          ## Title
          a = soup.find('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"$"))
          self.story.setMetadata('title',stripHTML(a))
          
          # Find authorid and URL from... author url.
          a = soup.find('a', href=re.compile(r"viewuser.php\?uid=\d+"))
          self.story.setMetadata('authorId',a['href'].split('=')[1])
          self.story.setMetadata('authorUrl','http://'+self.host+'/fanfiction/'+a['href'])
          self.story.setMetadata('author',a.string)
  
          # Find the chapters:
          for chapter in soup.findAll('a', href=re.compile(r'viewstory.php\?sid='+self.story.getMetadata('storyId')+"&chapter=\d+$")):
              # just in case there's tags, like <i> in chapter titles.
              self.chapterUrls.append((stripHTML(chapter),'http://'+self.host+'/fanfiction/'+chapter['href']))
  
          self.story.setMetadata('numChapters',len(self.chapterUrls))
  
          ## <meta name='description' content='&lt;p&gt;Description&lt;/p&gt; ...' >
          ## Summary, strangely, is in the content attr of a <meta name='description'> tag
          ## which is escaped HTML.  Unfortunately, we can't use it because they don't
          ## escape (') chars in the desc, breakin the tag.
          #meta_desc = soup.find('meta',{'name':'description'})
          #metasoup = bs.BeautifulStoneSoup(meta_desc['content'])
          #self.story.setMetadata('description',stripHTML(metasoup))
  
          def defaultGetattr(d,k):
              try:
                  return d[k]
              except:
                  return ""
          
          # <span class="label">Rated:</span> NC-17<br /> etc
          labels = soup.findAll('span',{'class':'label'})
          for labelspan in labels:
              value = labelspan.nextSibling
              label = labelspan.string
  
              if 'Summary' in label:
                  ## Everything until the next div class='listbox'
                  svalue = ""
                  while not defaultGetattr(value,'class') == 'listbox':
                      svalue += str(value)
                      value = value.nextSibling
                  self.setDescription(url,svalue)
                  #self.story.setMetadata('description',stripHTML(svalue))
  
              if 'Rated' in label:
                  self.story.setMetadata('rating', value)
  
              if 'Word count' in label:
                  self.story.setMetadata('numWords', value)
  
              if 'Categories' in label:
                  cats = labelspan.parent.findAll('a',href=re.compile(r'browse.php\?type=categories'))
                  catstext = [cat.string for cat in cats]
                  for cat in catstext:
                      self.story.addToList('category',cat.string)
  
              if 'Characters' in label:
                  chars = labelspan.parent.findAll('a',href=re.compile(r'browse.php\?type=characters'))
                  charstext = [char.string for char in chars]
                  for char in charstext:
                      if "Snape and Harry (required)" in char:
                          self.story.addToList('characters',"Snape")
                          self.story.addToList('characters',"Harry")
                      else:
                          self.story.addToList('characters',char.string)
  
              if 'Genre' in label:
                  genres = labelspan.parent.findAll('a',href=re.compile(r'browse.php\?type=class'))
                  genrestext = [genre.string for genre in genres]
                  self.genre = ', '.join(genrestext)
                  for genre in genrestext:
                      self.story.addToList('genre',genre.string)
  
              if 'Completed' in label:
                  if 'Yes' in value:
                      self.story.setMetadata('status', 'Completed')
                  else:
                      self.story.setMetadata('status', 'In-Progress')
  
              if 'Published' in label:
                  # limit date values, there's some extra chars.
                  self.story.setMetadata('datePublished', makeDate(stripHTML(value[:12]), "%d %b %Y"))
              
              if 'Updated' in label:
                  self.story.setMetadata('dateUpdated', makeDate(stripHTML(value[:12]), "%d %b %Y"))
  
          try:
              # Find Series name from series URL.
              a = soup.find('a', href=re.compile(r"viewseries.php\?seriesid=\d+"))
              series_name = a.string
              series_url = 'http://'+self.host+'/fanfiction/'+a['href']
  
              # use BeautifulSoup HTML parser to make everything easier to find.
              seriessoup = bs.BeautifulSoup(self._fetchUrl(series_url))
              storyas = seriessoup.findAll('a', href=re.compile(r'^viewstory.php\?sid=\d+$'))
              i=1
              for a in storyas:
                  if a['href'] == ('viewstory.php?sid='+self.story.getMetadata('storyId')):
                      self.setSeries(series_name, i)
                      self.story.setMetadata('seriesUrl',series_url)
                      break
                  i+=1
              
          except:
              # I find it hard to care if the series parsing fails
              pass
              
          
      def getChapterText(self, url):
  
          logger.debug('Getting chapter text from: %s' % url)
  
          soup = bs.BeautifulStoneSoup(self._fetchUrl(url),
                                       selfClosingTags=('br','hr')) # otherwise soup eats the br/hr tags.
          
          div = soup.find('div', {'id' : 'story'})
  
          if None == div:
              raise exceptions.FailedToDownload("Error downloading Chapter: %s!  Missing required element!" % url)
      
          return self.utf8FromSoup(url,div)
  
  def getClass():
      return PotionsAndSnitchesOrgSiteAdapter
  
  