Exemple #1
0
    def selectImageFromAlbum(self,
                             destinationDir,
                             supportedMimeTypes,
                             displaySize,
                             randomize,
                             retry=1):
        result = BaseService.selectImageFromAlbum(self, destinationDir,
                                                  supportedMimeTypes,
                                                  displaySize, randomize)
        if result is None:
            return None
        # catch broken urls
        if result.error is not None and result.source is not None:
            logging.warning(
                "broken url detected. You should remove '.../%s' from keywords"
                % (self.getUrlFilename(result.source)))
        # catch unsupported mimetypes (can only be done after downloading the image)
        elif result.error is None and result.mimetype not in supportedMimeTypes:
            logging.warning(
                "unsupported mimetype '%s'. You should remove '.../%s' from keywords"
                % (result.mimetype, self.getUrlFilename(result.source)))
        else:
            return result

        # track broken urls / unsupported mimetypes and display warning message on web interface
        self.brokenUrls.append(result["source"])
        # retry (with another image)
        if retry > 0:
            return self.selectImageFromAlbum(destinationDir,
                                             supportedMimeTypes,
                                             displaySize,
                                             randomize,
                                             retry=retry - 1)
        return BaseService.createImageHolder(self).setError(
            '%s uses broken urls / unsupported images!' % self.SERVICE_NAME)
Exemple #2
0
 def __init__(self, configDir, id, name):
     BaseService.__init__(self,
                          configDir,
                          id,
                          name,
                          needConfig=False,
                          needOAuth=True)
Exemple #3
0
  def selectImageFromAlbum(self, destinationDir, supportedMimeTypes, displaySize, randomize):
    result = BaseService.selectImageFromAlbum(self, destinationDir, supportedMimeTypes, displaySize, randomize)
    if result is not None:
      return result

    if not self.isGooglePhotosEnabled():
      return BaseService.createImageHolder(self).setError('"Photos Library API" is not enabled on\nhttps://console.developers.google.com\n\nCheck the Photoframe Wiki for details')
    else:
      return BaseService.createImageHolder(self).setError('No (new) images could be found.\nCheck spelling or make sure you have added albums')
Exemple #4
0
    def __init__(self, configDir, id, name):
        BaseService.__init__(self,
                             configDir,
                             id,
                             name,
                             needConfig=False,
                             needOAuth=False)

        self.brokenUrls = []
Exemple #5
0
    def getAlbumInfo(self, path, files):
        images = []
        for filename in files:
            fullFilename = os.path.join(path, filename)
            dim = helper.getImageSize(fullFilename)
            readable = True
            if dim is None:
                try:
                    with open(fullFilename, 'rb') as f:
                        f.read(1)
                    logging.warning('File %s has unknown format, skipping',
                                    fullFilename)
                    continue
                except:
                    readable = False

            if os.path.exists(fullFilename) and readable:
                item = BaseService.createImageHolder(self)
                item.setId(self.hashString(fullFilename))
                item.setUrl(fullFilename).setSource(fullFilename)
                item.setMimetype(helper.getMimetype(fullFilename))
                item.setDimensions(dim['width'], dim['height'])
                item.setFilename(filename)
                images.append(item)
            else:
                logging.warning(
                    'File %s could not be read. Could be USB issue, try rebooting',
                    fullFilename)
        return images
Exemple #6
0
    def selectImageFromAlbum(self, destinationDir, supportedMimeTypes,
                             displaySize, randomize):
        result = BaseService.selectImageFromAlbum(self, destinationDir,
                                                  supportedMimeTypes,
                                                  displaySize, randomize)
        if result is not None:
            return result

        if os.path.exists(self.usbDir):
            return BaseService.createImageHolder(self).setError(
                'No images could be found on storage device "%s"!\n\nPlease place albums inside /photoframe/{album_name} directory and add each {album_name} as keyword.\n\nAlternatively, put images directly inside the "/photoframe/"-directory on your storage device.'
                % self.device.getName())
        else:
            return BaseService.createImageHolder(self).setError(
                'No external storage device detected! Please connect a USB-stick!\n\n Place albums inside /photoframe/{album_name} directory and add each {album_name} as keyword.\n\nAlternatively, put images directly inside the "/photoframe/"-directory on your storage device.'
            )
Exemple #7
0
 def getImagesFor(self, keyword):
     url = keyword
     if url in self.brokenUrls:
         return []
     image = BaseService.createImageHolder(self).setId(
         self.hashString(url)).setUrl(url).setSource(url).allowCache(True)
     return [image]
Exemple #8
0
 def addKeywords(self, keywords):
     result = BaseService.addKeywords(self, keywords)
     if result['error'] is None and result['extras'] is not None:
         k = result['keywords']
         extras = self.getExtras()
         extras[k] = result['extras']
         self.setExtras(extras)
     return result
Exemple #9
0
    def validateKeywords(self, keyword):
        if keyword != 'ALLALBUMS' and keyword != '_PHOTOFRAME_':
            if keyword not in self.getAllAlbumNames():
                return {
                    'error': 'No such album "%s"' % keyword,
                    'keywords': keyword
                }

        return BaseService.validateKeywords(self, keyword)
Exemple #10
0
  def getImagesFor(self, keyword, rawReturn=False):
    filename = os.path.join(self.getStoragePath(), self.hashString(keyword) + '.json')
    result = []
    if not os.path.exists(filename):
      # First time, translate keyword into albumid
      params = self.getQueryForKeyword(keyword)
      if params is None:
        logging.error('Unable to create query the keyword "%s"', keyword)
        return [BaseService.createImageHolder(self).setError('Unable to get photos using keyword "%s"' % keyword)]

      url = 'https://photoslibrary.googleapis.com/v1/mediaItems:search'
      maxItems = 1000 # Should be configurable

      while len(result) < maxItems:
        data = self.requestUrl(url, data=params, usePost=True)
        if not data.isSuccess():
          logging.warning('Requesting photo failed with status code %d', data.httpcode)
          logging.warning('More details: ' + repr(data.content))
          break
        else:
          data = json.loads(data.content)
          if 'mediaItems' not in data:
            break
          logging.debug('Got %d entries, adding it to existing %d entries', len(data['mediaItems']), len(result))
          result += data['mediaItems']
          if 'nextPageToken' not in data:
            break
          params['pageToken'] = data['nextPageToken']
          logging.debug('Fetching another result-set for this keyword')

      if len(result) > 0:
        with open(filename, 'w') as f:
          json.dump(result, f)
      else:
        logging.error('No result returned for keyword "%s"!', keyword)
        return []

    # Now try loading
    if os.path.exists(filename):
      try:
        with open(filename, 'r') as f:
          albumdata = json.load(f)
      except:
        logging.exception('Failed to decode JSON file, maybe it was corrupted? Size is %d', os.path.getsize(filename))
        logging.error('Since file is corrupt, we try to save a copy for later analysis (%s.corrupt)', filename)
        try:
          if os.path.exists(filename + '.corrupt'):
            os.unlink(filename + '.corrupt')
          os.rename(filename, filename + '.corrupt')
        except:
          logging.exception('Failed to save copy of corrupt file, deleting instead')
          os.unlink(filename)
        albumdata = None
    if rawReturn:
      return albumdata
    return self.parseAlbumInfo(albumdata, keyword)
Exemple #11
0
 def getMessages(self):
     msgs = BaseService.getMessages(self)
     msgs.append({
         'level':
         'WARNING',
         'message':
         'This provider will cease to function January 1st, 2019. Please use GooglePhotos. For more details, see photoframe wiki',
         'link':
         'https://github.com/mrworf/photoframe/wiki/PicasaWeb-API-ceases-to-work-January-1st,-2019'
     })
     return msgs
Exemple #12
0
 def getMessages(self):
     msgs = BaseService.getMessages(self)
     msgs.append({
         'level':
         'ERROR',
         'message':
         'This provider is no longer supported by Google. Please use GooglePhotos. For more details, see photoframe wiki',
         'link':
         'https://github.com/mrworf/photoframe/wiki/PicasaWeb-API-ceases-to-work-January-1st,-2019'
     })
     return msgs
Exemple #13
0
  def updateState(self):
    self.subState = None
    if not os.path.exists(self.baseDir):
      if not self.mountStorageDevice():
        self._CURRENT_STATE = BaseService.STATE_NO_IMAGES
        self.subState = USB_Photos.SUBSTATE_NOT_CONNECTED
        return self._CURRENT_STATE
    if len(self.getAllAlbumNames()) == 0 and len(self.getBaseDirImages()) == 0:
      self._CURRENT_STATE = BaseService.STATE_NO_IMAGES
      return self._CURRENT_STATE

    return BaseService.updateState(self)
Exemple #14
0
 def parseAlbumInfo(self, data):
   # parse GooglePhoto specific keys into a format that the base service can understand
   if data is None:
     return None
   parsedImages = []
   for entry in data:
     item = BaseService.createImageHolder(self)
     item.setId(entry['id'])
     item.setSource(entry['productUrl']).setMimetype(entry['mimeType'])
     item.setDimensions(entry['mediaMetadata']['width'], entry['mediaMetadata']['height'])
     item.allowCache(True)
     parsedImages.append(item)
   return parsedImages
Exemple #15
0
    def getAlbumInfo(self, path, files):
        images = []
        for filename in files:
            fullFilename = os.path.join(path, filename)
            item = BaseService.createImageHolder(self)
            item.setId(self.hashString(fullFilename))
            item.setUrl(fullFilename).setSource(fullFilename)
            item.setMimetype(helper.getMimetype(fullFilename))
            dim = helper.getImageSize(fullFilename)
            item.setDimensions(dim['width'], dim['height'])
            item.setFilename(filename)

            images.append(item)
        return images
Exemple #16
0
 def removeKeywords(self, index):
   # Override since we need to delete our private data
   keys = self.getKeywords()
   if index < 0 or index >= len(keys):
     return
   keywords = keys[index].upper().lower().strip()
   filename = os.path.join(self.getStoragePath(), self.hashString(keywords) + '.json')
   if os.path.exists(filename):
     os.unlink(filename)
   if BaseService.removeKeywords(self, index):
     # Remove any extras
     extras = self.getExtras()
     if keywords in extras:
       del extras[keywords]
       self.setExtras(extras)
     return True
   else:
     return False
Exemple #17
0
  def validateKeywords(self, keywords):
    tst = BaseService.validateKeywords(self, keywords)
    if tst["error"] is not None:
      return tst

    # Remove quotes around keyword
    if keywords[0] == '"' and keywords[-1] == '"':
      keywords = keywords[1:-1]
    keywords = keywords.upper().lower().strip()

    # No error in input, resolve album now and provide it as extra data
    albumId = None
    if keywords != 'latest':
      albumId = self.translateKeywordToId(keywords)
      if albumId is None:
        return {'error':'No such album "%s"' % keywords, 'keywords' : keywords}

    return {'error':None, 'keywords':keywords, 'extras' : albumId}
Exemple #18
0
 def getMessages(self):
   # display a message indicating which storage device is being used or an error messing if no suitable storage device could be found
   if os.path.exists(self.baseDir):
     msgs = [
         {
             'level': 'SUCCESS',
             'message': 'Storage device "%s" is mounted to "%s"' % (self.device if self.device is not None else "unknown", self.usbDir),
             'link': None
         }
     ]
     msgs.extend(BaseService.getMessages(self))
   else:
     msgs = [
         {
             'level': 'ERROR',
             'message': 'No storage device could be found that contains the "/photoframe/"-directory! Try to reboot or manually mount the desired storage device to "%s"' % self.usbDir,
             'link': None
         }
     ]
   return msgs
Exemple #19
0
    def parseAlbumInfo(self, data, keyword):
        # parse GooglePhoto specific keys into a format that the base service can understand
        if data is None:
            return None
        parsedImages = []
        for entry in data:
            if entry['mimeType'] not in helper.getSupportedTypes():
                continue
            try:
                item = BaseService.createImageHolder(self)
                item.setId(entry['id'])
                item.setSource(entry['productUrl']).setMimetype(
                    entry['mimeType'])
                item.setDimensions(entry['mediaMetadata']['width'],
                                   entry['mediaMetadata']['height'])
                item.allowCache(True)
                item.setContentProvider(self)
                item.setContentSource(keyword)
                parsedImages.append(item)
            except:
                logging.exception('Failed due to:')
                logging.debug('Entry: %s', repr(entry))

        return parsedImages
Exemple #20
0
 def memoryForget(self, keywords=None, forgetHistory=False):
     # give broken URLs another try (server may have been temporarily unavailable)
     self.brokenUrls = []
     return BaseService.memoryForget(self,
                                     keywords=keywords,
                                     forgetHistory=forgetHistory)
Exemple #21
0
 def removeKeywords(self, index):
     url = self.getKeywords()[index]
     result = BaseService.removeKeywords(self, index)
     if result and url in self.brokenUrls:
         self.brokenUrls.remove(url)
     return result
Exemple #22
0
    def validateKeywords(self, keywords):
        # Catches most invalid URLs
        if not helper.isValidUrl(keywords):
            return {'error': 'URL appears to be invalid', 'keywords': keywords}

        return BaseService.validateKeywords(self, keywords)
Exemple #23
0
 def getExtras(self):
     # Normalize
     result = BaseService.getExtras(self)
     if result is None:
         return {}
     return result