ipodderx-core/iPXClass.py

1334 lines
44 KiB
Python

#(c) 2004-2008 Thunderstone Media, LLC
#Creative Commons Attribution-Noncommercial 3.0 United States License
#
#Python Developyment By:
#
#Ray Slakinski
#August Trometer
import iPXSettings
from iPXTools import *
from iPXDownloader import *
from time import *
from datetime import *
class Feeds:
def __init__(self):
self.feedList = []
self.__getEnabledFeeds(iPXSettings.FeedListPrefs['iPodderXFeeds'])
def retrFeeds(self):
import re
for feed in self.feedList:
if feed.has_key('feedURL'):
if len(feed['feedURL']) > 0:
if not feed.has_key('feedID'):
logIt('Feeds file could not provide feedID, generating new one')
feed['feedID'] = genHash(feed['feedURL'])
if iPXSettings.ranFromUI == False and checkForUI() == True:
logIt('Shutting down script - UI has started...')
break
elif feed.has_key('feedURL'):
if re.search('opml$', feed['feedURL'], re.IGNORECASE):
opmlFeeds = getOpmlFeeds(feed['feedURL'])
for entry in opmlFeeds:
feed['feedURL'] = opmlFeeds[entry]
feed['feedTitle'] = entry
feedData = FeedData(feed, None, False)
else:
if feed.has_key('ttl') and feed.has_key('lastChecked'):
currTime = mktime(gmtime())
lastChecked = mktime(strptime(feed['lastChecked'], '%a, %d %b %Y %H:%M:%S GMT'))
if (lastChecked + (float(feed['ttl']) * 60)) - currTime <= 0:
FeedData(feed)
else:
logIt('Skipping feed(%s) for TTL reasons.' % feed['feedURL'])
logIt('TTL Value = %s' % str((lastChecked + (float(feed['ttl']) * 60)) - currTime) + ' seconds.')
else:
FeedData(feed)
def retrFeed(self, feedID, retrType):
import re
for feed in self.feedList:
if not feed.has_key('feedID'):
logIt('Feeds file could not provide feedID, generating new one')
feed['feedID'] = genHash(feed['feedURL'])
if retrType > 0:
if feed['feedID'] == feedID:
if re.search('opml$', feed['feedURL'], re.IGNORECASE):
opmlFeeds = getOpmlFeeds(feed['feedURL'])
for entry in opmlFeeds:
feed['feedURL'] = opmlFeeds[entry]
feed['feedTitle'] = entry
FeedData(feed, None, False)
else:
FeedData(feed, None, False)
else:
if feed['feedURL'] == feedID:
if re.search('opml$', feed['feedURL'], re.IGNORECASE):
opmlFeeds = getOpmlFeeds(feed['feedURL'])
for entry in opmlFeeds:
feed['feedURL'] = opmlFeeds[entry]
feed['feedTitle'] = entry
FeedData(feed, None, False)
else:
FeedData(feed, None, False)
def retrEnclosure(self, feedID, entryGUID, encURL, hasFile=False):
getEncURL = entryGUID + ';;' + encURL
#logIt('FeedID: %s, getEncURL: %s' % (feedID, getEncURL))
for feed in self.feedList:
if feed['feedID'] == feedID:
FeedData(feed, getEncURL, False, hasFile)
def getEnclosuresList(self):
import os
encList = []
for feed in self.feedList:
if feed.has_key('feedID'):
hashFile = iPXSettings.rssPath + 'feedData/' + feed['feedID'] + '.ipxd'
if os.path.isfile(hashFile):
try:
EntriesData = readplist(hashFile)
if EntriesData.has_key('entries'):
for entry in EntriesData['entries']:
if entry.has_key('read'):
if entry['read'] == True:
if entry.has_key('flagged'):
if entry['flagged'] == False:
if entry.has_key('enclosures'):
for enc in entry['enclosures']:
if enc.has_key('path'):
if len(enc['path']) > 0:
encList.append(enc)
else:
if entry.has_key('enclosures'):
for enc in entry['enclosures']:
if enc.has_key('path'):
if len(enc['path']) > 0:
encList.append(enc)
else:
if entry.has_key('enclosures'):
for enc in entry['enclosures']:
if enc.has_key('path'):
if len(enc['path']) > 0:
encList.append(enc)
except Exception, msg:
logIt('getEnclosuresList Faied: %s' % msg)
return encList
def createQMCacheBridge(self):
import iPXQuotaManager, os
for feed in self.feedList:
if feed.has_key('feedID'):
hashFile = iPXSettings.rssPath + 'feedData/' + feed['feedID'] + '.ipxd'
if os.path.isfile(hashFile):
try:
EntriesData = readplist(hashFile)
if Entries.has_key('entries'):
for entry in EntriesData['entries']:
if entry.has_key('enclosures'):
for enc in entry['enclosures']:
if enc.has_key('path'):
encFile = os.path.join(iPXSettings.downloadDirectory + '/' + enc['path'] + '/' + enc['file'])
if os.path.isfile(encFile):
iPXQuotaManager.writeQuotaCache(feed['feedID'], entry['guid'], enc['path'] + '/' + enc['file'], enc['length'])
except Exception, msg:
logIt('getEnclosuresList Faied: %s' % msg)
return #encList
def __getEnabledFeeds(self, feedList):
newFeedList = []
self.feedList = []
append = self.feedList.append
for feed in feedList:
if feed['enabled']:
append(feed)
class FeedData:
def __init__(self, feed, getEncURL=None, useEtag=True, hasFile=False):
import re
self.feed = feed
self.status = 0
self.explicit = False
self.entries = {}
self.parsedFeed = {}
self.entriesData = []
printMSG(' ')
try:
if feed.has_key('customFeedTitle'):
if len(feed['customFeedTitle']) > 0:
printMSG('%s;;%s' % (HTML2Text(feed['customFeedTitle']), feed['feedID']))
else:
printMSG('%s;;%s' % (HTML2Text(feed['feedTitle']), feed['feedID']))
else:
printMSG('%s;;%s' % (HTML2Text(feed['feedTitle']), feed['feedID']))
except:
printMSG('%s;;%s' % (HTML2Text(feed['feedURL']), feed['feedID']))
status = 0
if not getEncURL == None:
if hasFile:
self.__getEntryEnclosure(getEncURL, hasFile)
else:
self.__getEntryEnclosure(getEncURL)
elif feed.has_key('etag') and iPXSettings.DEBUG == 0 and useEtag == True:
status = self.__getFeed(feed['feedURL'], feed['etag'], feed['feedID'])
elif feed.has_key('etag') and useEtag == False:
status = self.__getFeed(feed['feedURL'], 'None', feed['feedID'])
else:
status = self.__getFeed(feed['feedURL'], 'None', feed['feedID'])
if status >= 0:
feed['error'] = False
if status == 200 or status == 301 or status == 302:
if self.parsedFeed.has_key('feed'):
#Check feed level, which overrides entry level
if self.parsedFeed.feed.has_key('itunes_explicit'):
if re.search('yes', self.parsedFeed.feed.itunes_explicit, re.IGNORECASE):
self.explicit = True
elif self.parsedFeed.feed.has_key('media_adult'):
if re.search('true', self.parsedFeed.feed.media_adult, re.IGNORECASE):
self.explicit = True
feed['explicit'] = self.explicit
self.__getEntries()
elif (status != 500) and (status != 304) and (status != 302) and (status != 301) and (status != 0):
feed['error'] = True
logIt('Feed recieved a status of %d, expected 200 or 304' % status)
self.__saveFeedData(feed)
def __getEntries(self):
from sets import Set
import sys, os, re
newEntriesList = []
encList = []
tempList = []
hashFile = ''
numDownloads = 0
numDFiles = 0
totalDSize = 0
maxDownloads = 10000000
totalDSize = 0
if self.feed.has_key('downloadBehavior'):
if int(self.feed['downloadBehavior']) == 3:
maxDownloads = 0
elif int(self.feed['downloadBehavior']) == 2:
maxDownloads = 3
elif int(self.feed['downloadBehavior']) == 1:
maxDownloads = 1
self.feed['downloadBehavior'] = 0
hashFile = iPXSettings.rssPath + 'feedData/' + self.feed['feedID'] + '.ipxd'
if os.path.isfile(hashFile):
try:
EntriesData = readplist(hashFile)
if EntriesData.has_key('entries'):
entryOrig = EntriesData['entries']
else:
logIt('Hash file seems to be currupt... resetting file')
entryOrig = {}
except:
import plistlib
logIt('Hash file seems to be currupt... resetting file')
EntriesData = plistlib.Plist()
entryOrig = {}
else:
if sys.platform == 'darwin':
EntriesData = NSMutableDictionary.dictionary()
else:
import plistlib
EntriesData = plistlib.Plist()
entryOrig = {}
append = newEntriesList.append
for entry in entryOrig:
if not entry.has_key('guid'):
entry['guid'] = ''
if not entry.has_key('read'):
entry['read'] = True
if not entry['guid'] in encList:
if len(entry['guid']) > 1:
encList.append(entry['guid'])
append(entry)
if self.parsedFeed.has_key('entries'):
for entry in self.parsedFeed.entries:
if entry.has_key('modified_parsed'):
if not entry.modified_parsed == None:
pubDate = entry.modified_parsed
else:
pubDate = gmtime()
else:
pubDate = gmtime()
strCat = ''
catList = []
if entry.has_key('categories'):
for dict in entry.categories:
append = catList.append
for cat in dict:
if not type(cat) is NoneType:
if not cat == 'None':
try:
append(cat.encode('utf-8'))
except:
pass
categories = Set(catList)
for category in categories:
if not re.search('http://', category, re.IGNORECASE) or re.search('https://', category, re.IGNORECASE):
strCat = strCat + category + ', '
if len(strCat) > 0:
if strCat[len(strCat)-2] == ',':
strCat = strCat[:-2]
strAuthor = ''
if entry.has_key('author'):
strAuthor = entry.author
strLink = self.feed['feedURL']
if entry.has_key('link'):
strLink = entry.link
strCommentsLink = ''
if entry.has_key('comments'):
strCommentsLink = entry.comments
strSourceLink = ''
strSourceName = ''
if entry.has_key('source'):
if entry.source.has_key('url'):
strSourceLink = entry.source.url
if entry.source.has_key('value'):
strSourceName = entry.source.value
explicit = False
#Check feed level, which overrides entry level
if self.parsedFeed.feed.has_key('itunes_explicit'):
if re.search('yes', self.parsedFeed.feed.itunes_explicit, re.IGNORECASE):
explicit = True
elif self.parsedFeed.feed.has_key('media_adult'):
if re.search('true', self.parsedFeed.feed.media_adult, re.IGNORECASE):
explicit = True
#Check entry level if not set by feed level
if explicit == False:
if entry.has_key('itunes_explicit'):
if re.search('yes', entry.itunes_explicit, re.IGNORECASE):
explicit = True
elif entry.has_key('media_adult'):
if re.search('true', entry.media_adult, re.IGNORECASE):
explicit = True
uniDescription = unicode('No Entry Text Found In Feed', 'utf-8')
if entry.has_key('content'):
uniDescription = entry.content[0].value
elif entry.has_key('summary_detail'):
uniDescription = entry.summary_detail.value
elif entry.has_key('description'):
uniDescription = entry.description
try:
if len(uniDescription) == 0:
uniDescription = unicode('No Entry Text Found In Feed', 'utf-8')
except:
uniDescription = unicode('No Entry Text Found In Feed', 'utf-8')
uniDescription = uniDescription.strip()
uniDescription = uniDescription.strip(chr(0))
uniDescription = uniDescription.replace('\x00', '')
uniDescription = uniDescription.replace('\r', '')
if type(uniDescription) == StringType:
uniDescription = HTML2Text(uniDescription)
uniSummary = unicode('', 'utf-8')
if entry.has_key('summary_detail'):
uniDescription = entry.summary_detail.value
uniSummary = uniSummary.strip()
uniSummary = uniSummary.strip(chr(0))
uniSummary = uniSummary.replace('\x00', '')
uniSummary = uniSummary.replace('\r', '')
if type(uniSummary) == StringType:
uniSummary = HTML2Text(uniSummary)
if entry.has_key('guid'):
strGUID = entry.guid
elif entry.has_key('title'):
if len(entry.title) > 20:
strGUID = genHash(entry.title)
else:
strGUID = genHash(uniDescription)
else:
strGUID = genHash(uniDescription)
uniTitle = unicode('', 'utf-8')
if entry.has_key('title'):
uniTitle = HTML2Text(entry.title)
try:
uniTitle = tmpTitle.encode('utf-8')
except Exception, msg:
pass
strLink = self.feed['feedURL']
if entry.has_key('link'):
strLink = entry.link
encArray = []
if entry.has_key('enclosures') or entry.has_key('links') or entry.has_key('apple-wallpapers_image'):
if iPXSettings.showExplicit == True:
if numDownloads < maxDownloads:
encArray, numDownloaded, sizeDownloaded = self.__getEntryEnclosures(entry, True, self.feed['baseHost'])
else:
encArray, numDownloaded, sizeDownloaded = self.__getEntryEnclosures(entry, False)
elif explicit == True:
encArray, numDownloaded, sizeDownloaded = self.__getEntryEnclosures(entry, False)
else:
if numDownloads < maxDownloads:
encArray, numDownloaded, sizeDownloaded = self.__getEntryEnclosures(entry, True, self.feed['baseHost'])
else:
encArray, numDownloaded, sizeDownloaded = self.__getEntryEnclosures(entry, False)
if numDownloaded > 0:
numDownloaded = 0
numDownloads = numDownloads + 1
numDFiles = numDFiles + numDownloads
totalDSize = totalDSize + long(sizeDownloaded)
if self.feed.has_key('textToAudio'):
if not strGUID in encList:
if self.feed['textToAudio']:
tempEnc = self.downloadTextAsAudio(uniTitle, strftime('%A %B %d %Y', pubDate), uniDescription, strGUID)
if not tempEnc == None:
encArray.append(tempEnc)
newEntry = {'description': uniDescription,
'summary': uniSummary,
'link': strLink,
'title': uniTitle,
'read': False,
'enclosures': encArray,
'pubDate': strftime('%a, %d %b %Y %H:%M:%S GMT', pubDate),
#'datePublished' : strftime('%Y-%b-%dT%H:%M:%SZ', pubDate),
'category': strCat,
'commentsLink': strCommentsLink,
'feedTitle': HTML2Text(self.feed['feedTitle']),
'sourceTitle': strSourceName,
'sourceLink': HTML2Text(strSourceLink),
'explicit': explicit,
'author': strAuthor,
'guid': strGUID
}
tempList.append(newEntry['guid'])
if strGUID in encList:
for entry in newEntriesList:
if entry.has_key('guid'):
if entry['guid'] == newEntry['guid']:
if entry.has_key('origDescription'):
if not genHash(entry['origDescription']) == genHash(newEntry['description']):
entry['bakDescription'] = entry['origDescription']
entry['origDescription'] = newEntry['description']
entry['description'] = textDiff(entry['origDescription'], newEntry['description'])
entry['title'] = newEntry['title']
if genHash(HTML2Text(newEntry['description'])) != genHash(HTML2Text(entry['origDescription'])):
entry['read'] = False
if len(entry['enclosures']) < len(newEntry['enclosures']):
entry['enclosures'] = newEntry['enclosures']
entry['read'] = False
elif genHash(entry['description']) != genHash(newEntry['description']):
entry['bakDescription'] = entry['description']
entry['origDescription'] = newEntry['description']
entry['description'] = textDiff(entry['description'], newEntry['description'])
entry['title'] = newEntry['title']
if genHash(HTML2Text(newEntry['description'])) != genHash(HTML2Text(entry['origDescription'])):
entry['read'] = False
if len(entry['enclosures']) < len(newEntry['enclosures']):
entry['enclosures'] = newEntry['enclosures']
entry['read'] = False
elif genHash(entry['title']) != genHash(newEntry['title']):
if len(newEntry['title']) > 0:
entry['title'] = newEntry['title']
if len(entry['enclosures']) < len(newEntry['enclosures']):
entry['enclosures'] = newEntry['enclosures']
entry['read'] = False
elif len(entry['enclosures']) < len(newEntry['enclosures']):
entry['enclosures'] = newEntry['enclosures']
entry['read'] = False
else:
encList.append(newEntry['guid'])
newEntriesList.append(newEntry)
if numDFiles > 0:
self.__saveHashFile(EntriesData, newEntriesList, tempList, numDFiles, totalDSize, hashFile)
numDFiles = 0
totalDSize = 0.0
self.__saveHashFile(EntriesData, newEntriesList, tempList, numDownloads, totalDSize, hashFile)
def __saveHashFile(self, EntriesData, newEntriesList, tempList, numDownloads, totalDSize, hashFile, skipDelOld=False):
import os
logIt('Saving to hashFile: %s' % hashFile)
dellist = []
if skipDelOld == False:
#Lets delete old entries...
for entry in newEntriesList:
if not entry['guid'] in tempList:
flagged = False
if entry.has_key('flagged'):
flagged = entry['flagged']
hasFile = False
if entry.has_key('enclosures'):
if len(entry['enclosures']) > 0:
for enclosure in entry['enclosures']:
path = enclosure['path']
fullPath = iPXSettings.downloadDirectory + '/' + path
fileName = enclosure['file']
if os.path.isfile(fullPath + '/' + fileName):
hasFile = True
break
if hasFile == False:
if entry['read'] == True:
if flagged == False:
if len(entry['enclosures']) == 0:
try:
tmpEntryDate = strptime(entry['pubDate'], '%a, %d %b %Y %H:%M:%S %Z')
entryDate = date(tmpEntryDate[0], tmpEntryDate[1], tmpEntryDate[2])
dateDelta = date.today() - entryDate
strDateDelta = str(dateDelta).split()
if len(strDateDelta) > 1:
if iPXSettings.maxEntryAge > 0:
if int(strDateDelta[0]) > iPXSettings.maxEntryAge:
dellist.append(entry)
except:
pass
if len(dellist) > 0:
remove = newEntriesList.remove
for entry in dellist:
remove(entry)
if EntriesData.has_key('statistics'):
stats = EntriesData['statistics']
numDFiles = numDownloads
if stats.has_key('numDFiles'):
numDFiles = numDFiles + long(stats['numDFiles'])
totalDSizeMB = float(totalDSize) / 1048576.0
if stats.has_key('totalDSize'):
totalDSizeMB = float(totalDSizeMB) + float(stats['totalDSize'])
strTotalDSizeMB = '%.2f' % totalDSizeMB
firstCheck = strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime())
if stats.has_key('firstCheck'):
firstCheck = stats['firstCheck']
stats = {'firstCheck': firstCheck,
'lastCheck': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'numDFiles': str(numDFiles),
'totalDSize': strTotalDSizeMB}
else:
totalDSizeMB = float(totalDSize) / 1048576.0
strTotalDSizeMB = '%.2f' % totalDSizeMB
numDFiles = numDownloads
stats = {'firstCheck': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'lastCheck': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'numDFiles': str(numDFiles),
'totalDSize': strTotalDSizeMB}
EntriesData['statistics'] = stats
EntriesData['entries'] = newEntriesList
writeplist(EntriesData, hashFile)
def __getEntryEnclosure(self, getEncURL, hasFile=False):
import sys, os, re
logIt('getEncURL')
origEntriesList = []
hashFile = ''
totalDSize = 0
numDFiles = 1
hashFile = iPXSettings.rssPath + 'feedData/' + self.feed['feedID'] + '.ipxd'
if iPXSettings.ranHistCheck == False:
iPXSettings.histGUIDs = getHistory()
iPXSettings.ranHistCheck = True
if os.path.isfile(hashFile):
try:
EntriesData = readplist(hashFile)
if EntriesData.has_key('entries'):
entryOrig = EntriesData['entries']
else:
logIt('Hash file seems to be currupt... resetting file')
entryOrig = {}
except:
import plistlib
logIt('Hash file seems to be currupt... resetting file')
EntriesData = plistlib.Plist()
entryOrig = {}
else:
if sys.platform == 'darwin':
EntriesData = NSMutableDictionary.dictionary()
else:
import plistlib
EntriesData = plistlib.Plist()
entryOrig = {}
append = origEntriesList.append
for entry in entryOrig:
append(entry)
getEncURLSplit = getEncURL.split(';;')
guid = getEncURLSplit[0]
encURL = getEncURLSplit[1]
for entry in origEntriesList:
if entry['guid'] == guid:
for enclosure in entry['enclosures']:
if enclosure['enclosureURL'] == encURL:
downloadError = False
url = encURL.strip()
length = '0'
if enclosure.has_key('length'):
if len(enclosure['length']) > 0:
length = enclosure['length']
totalDSize = totalDSize + long(length)
fileType = enclosure['type']
guid = enclosure['guid']
feedTitle = HTML2Text(self.feed['feedTitle'])
feedTitle = feedTitle.replace('/', ' ')
if iPXSettings.organizeDownloads == 1:
customFolder = strftime('%m-%d-%Y',localtime())
else:
customFolder = feedTitle
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = stringCleaning(customFolder)
if hasFile:
iPXID = ''
importProg = ''
fileType = ''
customGenre = ''
downloadStatus = enclosure['downloadStatus']
if self.feed.has_key('customGenre'):
customGenre = self.feed['customGenre']
path = enclosure['path']
fullPath = iPXSettings.downloadDirectory + '/' + path
fileName = enclosure['file']
if os.path.isfile(fullPath + '/' + fileName):
fileType = detectFileType(fullPath + '/' + fileName)
# Audio
if re.search('audio', fileType, re.IGNORECASE):
convertToAAC = False
if self.feed.has_key('convertToAAC'):
convertToAAC = self.feed['convertToAAC']
makeBookmarkable = False
if self.feed.has_key('makeBookmarkable'):
makeBookmarkable = self.feed['makeBookmarkable']
importProg = 'iTunes'
iPXID, importProg = updatePlaylist(fullPath, fileName, customFolder, customGenre, convertToAAC, makeBookmarkable)
# Image
elif re.search('image', fileType, re.IGNORECASE):
importProg = 'iPhoto'
iPXID, importProg = updateiPhoto(fullPath, fileName, customFolder, 0)
# Video Files
elif re.search('video/quicktime', fileType, re.IGNORECASE):
importProg = 'iTunes'
iPXID, importProg = updatePlaylist(fullPath, fileName, customFolder, '', False, False)
elif re.search('data', fileType, re.IGNORECASE):
if (re.search('mp3$', fileName, re.IGNORECASE)):
if (iPXSettings.moveAudio > 0):
importProg = 'iTunes'
iPXID, importProg = updatePlaylist(fullPath, fileName, customFolder, customGenre, convertToAAC, makeBookmarkable)
elif (re.search('mov$', fileName, re.IGNORECASE)):
if (iPXSettings.moveVideo > 0):
importProg = 'iTunes'
iPXID, importProg = updatePlaylist(fullPath, fileName, customFolder, customGenre, False, False)
elif (re.search('aa$', fileName, re.IGNORECASE)):
if (iPXSettings.moveVideo > 0):
importProg = 'iTunes'
iPXID, importProg = updatePlaylist(fullPath, fileName, customFolder, customGenre, False, False)
else:
fileNameSplit = url.split('/')
fileName = fileNameSplit[len(fileNameSplit) - 1]
fileName = latin1_to_ascii(fileName)
fileName = stringCleaning(fileName)
importProg = ''
fileLocation = ''
path = iPXSettings.downloadDirectory + '/' + customFolder
path = latin1_to_ascii(path)
downloadStatus = 0
fileName, iPXID, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName, length, fileType, True)
if downloadStatus == 1:
downloadError = False
if not guid in iPXSettings.histGUIDs:
saveHistory(guid)
iPXSettings.histGUIDs.append(guid)
else:
downloadError = True
totalDSize = long(length)
tempEnc = {'enclosureURL': url,
'length': length,
'type': fileType,
'file': fileName,
'path': latin1_to_ascii(customFolder),
'guid': guid,
'import': importProg,
'iPXID': iPXID,
'textToAudio': False,
'downloadStatus': downloadStatus,
'downloadDate': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'downloadError': downloadError}
enclosure.update(tempEnc)
tempList = []
self.__saveHashFile(EntriesData, origEntriesList, tempList, numDFiles, totalDSize, hashFile, True)
def __getEntryEnclosures(self, entry, doDownload, host=None):
from sets import Set
import re
returnEncList = []
numDownloaded = 0
sizeDownloaded = 0
keywords = []
if self.feed.has_key('keywords'):
keywords = self.feed['keywords'].split(',')
if iPXSettings.ranHistCheck == False:
iPXSettings.histGUIDs = getHistory()
iPXSettings.ranHistCheck = True
okDownload = True
if entry.has_key('guid'):
if not entry['guid'] == None:
if entry['guid'] in iPXSettings.histGUIDs:
okDownload = False
elif not host == None:
if host + entry['guid'] in iPXSettings.histGUIDs:
okDownload = False
else:
okDownload = True
else:
okDownload = True
else:
okDownload = True
strTitle = ''
uniDescription = unicode('', 'utf-8')
strCat = ''
if (len(keywords) > 0) and (doDownload == True):
if entry.has_key('title'):
strTitle = HTML2Text(entry.title)
if entry.has_key('summary_detail'):
uniDescription = entry.summary_detail.value
if len(uniDescription) == 0:
uniDescription = unicode('No Entry Text Found In Feed', 'utf-8')
if entry.has_key('content'):
uniDescription = entry.content[0].value
elif entry.has_key('content'):
uniDescription = entry.content[0].value
elif entry.has_key('description'):
uniDescription = entry.description
catList = []
if entry.has_key('categories'):
for dict in entry.categories:
for cat in dict:
try:
if not type(cat) is NoneType:
if not cat == 'None':
try:
catList.append(cat.encode('utf-8'))
except:
pass
except Exception, msg:
logIt('Type error: %s' % msg)
categories = Set(catList)
for category in categories:
if not re.search('http://', category, re.IGNORECASE) or re.search('https://', category, re.IGNORECASE):
strCat = strCat + category + ', '
if len(strCat) > 0:
if strCat[len(strCat)-2] == ',':
strCat = strCat[:-2]
if re.search('rss', self.parsedFeed.version, re.IGNORECASE):
if entry.has_key('enclosures'):
for enclosure in entry.enclosures:
if enclosure.has_key('url'):
if len(enclosure.url) > 0:
url = enclosure.url
url = url.strip()
url = prepURL(url)
fileNameSplit = url.split('/')
fileName = fileNameSplit[len(fileNameSplit) - 1]
fileName = latin1_to_ascii(fileName)
fileType = 'Unknown'
if enclosure.has_key('type'):
fileType = enclosure.type
length = '0'
if enclosure.has_key('length'):
if len(enclosure.length) > 0:
length = enclosure.length
try:
temp = long(length)
except:
length = '0'
if entry.has_key('guid'):
guid = entry.guid
else:
guid = enclosure.url
importProg = ''
fileLocation = ''
feedTitle = HTML2Text(self.feed['feedTitle'])
feedTitle = feedTitle.replace('/', '-')
if iPXSettings.organizeDownloads == 1:
customFolder = strftime('%m-%d-%Y',localtime())
else:
customFolder = feedTitle
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = stringCleaning(customFolder)
path = iPXSettings.downloadDirectory + '/' + customFolder
path = latin1_to_ascii(path)
downloadStatus = 0
autoDownload = True
if self.feed.has_key('autoDownload'):
autoDownload = self.feed['autoDownload']
downloadError = False
if autoDownload:
encArray = []
if entry.has_key('enclosures') or entry.has_key('links'):
didFind = True
if len(keywords) > 0:
for keyword in keywords:
keywordSplit = keyword.split(' ')
for word in keywordSplit:
if len(word) > 1:
if (re.search(word.strip(), url, re.IGNORECASE) or re.search(word.strip(), strTitle, re.IGNORECASE) or re.search(word.strip(), uniDescription, re.IGNORECASE)or re.search(word.strip(), strCat, re.IGNORECASE)):
didFind = True
else:
didFind = False
break
if url in iPXSettings.histGUIDs:
doDownload = False
if didFind and okDownload and doDownload:
fileName, fileLocation, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName, length, fileType, doDownload)
if downloadStatus == 1:
numDownloaded = numDownloaded + 1
sizeDownloaded = long(sizeDownloaded) + long(length)
elif downloadStatus == 0:
downloadError = True
elif didFind and okDownload and not doDownload:
fileName, fileLocation, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName, length, fileType, doDownload)
tempEnc = {'enclosureURL': url,
'length': length,
'type': fileType,
'file': fileName,
'path': latin1_to_ascii(customFolder),
'guid': guid,
'import': importProg,
'iPXID': fileLocation,
'textToAudio': False,
'downloadError': downloadError,
'downloadDate': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'downloadStatus': downloadStatus}
returnEncList.append(tempEnc)
elif entry.has_key('apple-wallpapers_image'):
if len(entry['apple-wallpapers_image']) > 0:
url = entry['apple-wallpapers_image']
url = url.strip()
url = prepURL(url)
fileNameSplit = url.split('/')
fileName = fileNameSplit[len(fileNameSplit) - 1]
fileName = latin1_to_ascii(fileName)
fileType = 'image'
length = '0'
if entry.has_key('guid'):
guid = entry.guid
else:
guid = url
importProg = ''
fileLocation = ''
feedTitle = HTML2Text(self.feed['feedTitle'])
feedTitle = feedTitle.replace('/', '-')
if iPXSettings.organizeDownloads == 1:
customFolder = strftime('%m-%d-%Y',localtime())
else:
customFolder = feedTitle
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = stringCleaning(customFolder)
path = iPXSettings.downloadDirectory + '/' + customFolder
path = latin1_to_ascii(path)
downloadStatus = 0
autoDownload = True
if self.feed.has_key('autoDownload'):
autoDownload = self.feed['autoDownload']
downloadError = False
if autoDownload:
encArray = []
if entry.has_key('enclosures') or entry.has_key('links') or entry.has_key('apple-wallpapers_image'):
didFind = True
if len(keywords) > 0:
for keyword in keywords:
keywordSplit = keyword.split(' ')
for word in keywordSplit:
if len(word) > 1:
if (re.search(word.strip(), url, re.IGNORECASE) or re.search(word.strip(), strTitle, re.IGNORECASE) or re.search(word.strip(), uniDescription, re.IGNORECASE)or re.search(word.strip(), strCat, re.IGNORECASE)):
didFind = True
else:
didFind = False
break
if url in iPXSettings.histGUIDs:
doDownload = False
if didFind and okDownload and doDownload:
fileName, fileLocation, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName, length, fileType, doDownload)
if downloadStatus == 1:
numDownloaded = numDownloaded + 1
sizeDownloaded = long(sizeDownloaded) + long(length)
elif downloadStatus == 0:
downloadError = True
elif didFind and okDownload and not doDownload:
fileName, fileLocation, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName, length, fileType, doDownload)
tempEnc = {'enclosureURL': url,
'length': length,
'type': fileType,
'file': fileName,
'path': latin1_to_ascii(customFolder),
'guid': guid,
'import': importProg,
'iPXID': fileLocation,
'textToAudio': False,
'downloadError': downloadError,
'downloadDate': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'downloadStatus': downloadStatus}
returnEncList.append(tempEnc)
elif re.search('atom', self.parsedFeed.version, re.IGNORECASE):
if entry.has_key('links'):
for link in entry.links:
if link.rel == 'enclosure':
if link.has_key('href'):
if len(link.href) > 0:
url = link.href
url = url.strip()
url = prepURL(url)
fileNameSplit = url.split('/')
fileName = fileNameSplit[len(fileNameSplit) - 1]
fileName = latin1_to_ascii(fileName)
fileType = ''
if link.has_key('type'):
fileType = link.type
length = '0'
if link.has_key('length'):
if len(link['length']) > 0:
length = link['length']
if entry.has_key('guid'):
guid = entry.guid
else:
guid = link.href
importProg = ''
fileLocation = ''
downloadError = False
feedTitle = HTML2Text(self.feed['feedTitle'])
feedTitle = feedTitle.replace('/', '-')
if iPXSettings.organizeDownloads == 1:
customFolder = strftime('%m-%d-%Y',localtime())
else:
customFolder = feedTitle
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = stringCleaning(customFolder)
path = iPXSettings.downloadDirectory + '/' + customFolder
path = latin1_to_ascii(path)
if self.feed.has_key('autoDownload'):
if self.feed['autoDownload'] == True:
didFind = True
if len(keywords) > 0:
for keyword in keywords:
keywordSplit = keyword.split(' ')
for word in keywordSplit:
if len(word) > 1:
if (re.search(word, url, re.IGNORECASE) or re.search(word, strTitle, re.IGNORECASE) or re.search(word, uniDescription, re.IGNORECASE) or re.search(word, strCat, re.IGNORECASE)):
didFind = True
break
else:
didFind = False
if url in iPXSettings.histGUIDs:
doDownload = False
if didFind and okDownload:
fileName, fileLocation, importProg, fileType, downloadStatus = self.iPXDownload(url, guid, path, fileName,length, fileType, doDownload)
if downloadStatus == 1:
numDownloaded = numDownloaded + 1
sizeDownloaded = long(sizeDownloaded) + long(length)
elif downloadStatus == 0:
downloadError = True
tempEnc = {'enclosureURL': url,
'length': length,
'type': fileType,
'file': fileName,
'path': latin1_to_ascii(customFolder),
'guid': guid,
'import': importProg,
'textToAudio': False,
'downloadError': downloadError,
'downloadDate': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'iPXID': fileLocation}
returnEncList.append(tempEnc)
return returnEncList, numDownloaded, sizeDownloaded
def __saveFeedData(self, newFeed):
import sys
logIt('Saving feeds.plist')
try:
FeedListPrefs = readplist(iPXSettings.feedFile)
feedDetails = FeedListPrefs['iPodderXFeeds']
for feed in feedDetails:
if feed.has_key('feedURL'):
if feed['feedURL'] == newFeed['feedURL']:
feed.update(newFeed)
FeedListPrefs['iPodderXFeeds'] = feedDetails
#FeedListPrefs.write(iPXSettings.feedFile)
writeplist(FeedListPrefs, iPXSettings.feedFile)
except Exception, msg:
logIt(msg)
sys.exit(5)
def __getFeed(self, url, etagInfo, feedID):
import feedparser, urllib, urllib2, urlparse
parsedFeed = {}
etag = ''
self.feed['lastChecked'] = strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime())
self.feed['baseHost'] = 'http:/'
for part in urlparse.urlparse(url):
if not part == urlparse.urlparse(url)[0]:
if len(part) > 0:
if '/' in part:
splitPart = part.split('/')
for newPart in splitPart:
if newPart == splitPart[len(splitPart)-1]:
break
if len(newPart) > 0:
self.feed['baseHost'] = self.feed['baseHost'] + '/' + newPart
else:
self.feed['baseHost'] = self.feed['baseHost'] + '/' + part
self.feed['baseHost'] = self.feed['baseHost'] + '/'
logIt('etagInfo: %s' % etagInfo)
userName = None
if self.feed.has_key('username'):
userName = self.feed['username']
password = ''
if self.feed.has_key('password'):
password = decrypt(self.feed['password'])
if iPXSettings.useProxyServer and userName != None:
status, url, x = getFileViaProxySSL(url, userName, password, True, False)
status, feedData, r = getFileViaProxySSL(url, userName, password, False, False)
if status == 200:
parsedFeed = feedparser.parse(feedData)
if parsedFeed.has_key('entries'):
if len(parsedFeed.entries) > 0:
self.parsedFeed = parsedFeed
self.feed['etag'] = ''
if parsedFeed.feed.has_key('ttl'):
self.feed['ttl'] = parsedFeed.feed.ttl
else:
self.feed['ttl']
self.feed['feedTitle'] = HTML2Text(parsedFeed.feed.title)
if self.feed.has_key('customFeedTitle'):
if len(self.feed['customFeedTitle']) > 0:
self.feed['feedTitle'] = self.feed['customFeedTitle']
self.feed['siteURL'] = parsedFeed.feed.link
return 200
else:
return 0
else:
req = urllib2.Request(url)
req.add_header('Accept-encoding', 'gzip')
if not etagInfo == 'None':
req.add_header('If-None-Match', etagInfo)
if not userName == None:
setOpener(url, userName, password)
else:
setOpener()
try:
h = urllib2.urlopen(req)
except urllib2.HTTPError, e:
logIt('Feed recieved a status of %s' % e.code)
if e.code == 401:
printMSG('AUTHENTICATION_FAILED;;%s' % feedID)
if e.code == 407:
printMSG('PROXY_AUTHENTICATION_FAILED')
return -1
except Exception, msg:
logIt('Feed failed to connect %s' % msg)
return -1
try:
etag = h.info()['etag']
except:
etag = ''
try:
if h.info().has_key('Content-Encoding'):
if h.info()['Content-Encoding'] == 'gzip':
import gzip
from StringIO import StringIO
tempData = h.read()
feedData = gzip.GzipFile(fileobj=StringIO(tempData)).read()
else:
try:
feedData = h.read()
except Exception, msg:
logIt('FeedData ERRMSG: %s' % msg)
feedData = ''
if iPXSettings.SUPERDEBUG:
print feedData
parsedFeed = feedparser.parse(feedData)
if parsedFeed.has_key('entries'):
if len(parsedFeed.entries) > 0:
self.parsedFeed = parsedFeed
self.feed['etag'] = etag
if parsedFeed.feed.has_key('ttl'):
self.feed['ttl'] = parsedFeed.feed.ttl
else:
self.feed['ttl'] = 0
self.feed['feedTitle'] = HTML2Text(parsedFeed.feed.title)
if self.feed.has_key('customFeedTitle'):
if len(self.feed['customFeedTitle']) > 0:
self.feed['feedTitle'] = self.feed['customFeedTitle']
self.feed['siteURL'] = parsedFeed.feed.link
parsedFeed.status = 200
return int(parsedFeed.status)
except:
return -1
def iPXDownload(self, encURL, encGUID, downloadPath, fileName, size, fileType, doDownload):
logIt('Downloading: %s' % encURL)
status = 1
fileLocation = ''
importProg = ''
head = None
userName = None
password = ''
if self.feed.has_key('username'):
userName = self.feed['username']
if self.feed.has_key('password'):
password = decrypt(self.feed['password'])
#head = HTTPHead(encURL, userName, password)
if head != None:
if len(head.getName()) > 0:
fileName = head.getName()
if head.getType() != None:
fileType = head.getType()
if head.getLength() != None:
size = long(head.getLength())
if iPXSettings.quotaEnabled > 0 and doDownload == True:
import iPXQuotaManager
if iPXSettings.ranQuotaTest == False:
printMSG('Compiling SmartSpace Information...')
iPXSettings.delList, iPXSettings.quotaSizeTaken = iPXQuotaManager.getAllowedDelList()
iPXSettings.ranQuotaTest = True
iPXQuotaManager.getToQuota(size)
convertToAAC = False
if self.feed.has_key('convertToAAC'):
convertToAAC = self.feed['convertToAAC']
makeBookmarkable = False
if self.feed.has_key('makeBookmarkable'):
makeBookmarkable = self.feed['makeBookmarkable']
if doDownload:
customGenre = ''
if self.feed.has_key('customGenre'):
customGenre = self.feed['customGenre']
if iPXSettings.organizeDownloads == 1:
customFolder = strftime('%m-%d-%Y',localtime())
else:
customFolder = self.feed['feedTitle']
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = latin1_to_ascii(customFolder)
fileName, fileLocation, importProg, fileType, status = downloadFile(encURL,fileType,downloadPath,fileName,customFolder,customGenre,convertToAAC,makeBookmarkable,userName,password)
if not encGUID in iPXSettings.histGUIDs and status == 1:
saveHistory(encGUID)
if iPXSettings.anonFeedback and status == 1:
doPing(encURL, self.feed['feedURL'])
elif not encGUID in iPXSettings.histGUIDs:
saveHistory(encGUID)
return fileName, fileLocation, importProg, fileType, status
def downloadTextAsAudio(self, strTitle, pubDate, text, strGUID):
import sys, os
customFolder = self.feed['feedTitle']
feedTitle = customFolder
if len(strTitle) == 0:
strTitle = customFolder + ': '
x = 0
textSplit = text.split(' ')
for word in textSplit:
tmpWord = word + ' '
strTitle = strTitle + tmpWord
if x == 5:
break
else:
x = x + 1
strTitle = strTitle.strip()
text = 'From ' + feedTitle + ', posted on ' + pubDate + '. '+ text
if self.feed.has_key('customFolder'):
if len(self.feed['customFolder']) > 0:
customFolder = self.feed['customFolder']
customFolder = stringCleaning(customFolder)
if sys.platform == 'darwin':
saveDir = iPXSettings.downloadDirectory + '/' + customFolder
elif sys.platform == 'win32':
saveDir = iPXSettings.downloadDirectory + '\\' + customFolder
checkDir(saveDir)
saveName = HTML2Text(strTitle)
saveName = pubDate + ' - ' + saveName
saveName = stringCleaning(saveName)
if sys.platform == 'darwin':
saveName = saveName + '.aiff'
elif sys.platform == 'win32':
saveName = saveName + '.wav'
if text2Audio(text, saveDir, saveName) == True:
length = 0
if os.path.isfile(saveDir + '/' + saveName):
length = os.path.getsize(saveDir + '/' + saveName)
if iPXSettings.quotaEnabled > 0:
import iPXQuotaManager
iPXQuotaManager.getToQuota(length)
importProg = ''
fileLocation = ''
if (iPXSettings.moveAudio > 0):
customGenre = 'iPodderX NewsCaster'
if self.feed.has_key('customGenre'):
customGenre = self.feed['customGenre']
convertToAAC = True
if self.feed.has_key('convertToAAC'):
convertToAAC = self.feed['convertToAAC']
makeBookmarkable = False
if self.feed.has_key('makeBookmarkable'):
makeBookmarkable = self.feed['makeBookmarkable']
fileLocation, importProg = updatePlaylist(saveDir, saveName, customFolder, customGenre, convertToAAC, makeBookmarkable)
tempEnc = {'length': str(length),
'type': 'audio',
'file': saveName,
'path': saveDir,
'guid': strGUID,
'import': importProg,
'iPXID': fileLocation,
'textToAudio': True,
'downloadError': False,
'downloadDate': strftime('%a, %d %b %Y %H:%M:%S GMT',gmtime()),
'downloadStatus': '1'}
return tempEnc
else:
return None