PageRenderTime 47ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Navi-X BOXEE/source/libs/tools.py

http://navi-x.googlecode.com/
Python | 428 lines | 417 code | 8 blank | 3 comment | 4 complexity | 9855e1184dbf3bd332bc66b6bf4f5e87 MD5 | raw file
Possible License(s): GPL-2.0
  1. from default import *
  2. #Module specific Imports
  3. import socket
  4. import urllib2
  5. import time
  6. import datetime
  7. import traceback
  8. import mimetypes
  9. import tempfile
  10. import bz2
  11. import binascii
  12. import stat
  13. try: import json
  14. except: import simplejson as json
  15. try: import cStringIO as StringIO
  16. except: import StringIO
  17. from operator import itemgetter, attrgetter
  18. try: from hashlib import md5
  19. except: from md5 import md5
  20. import marshal
  21. ### prints info to log if mode in debug
  22. def Log(app, string):
  23. if app.debug:
  24. print string
  25. ### function to retreive http data
  26. def urlopen(app, url, args={}):
  27. rdefaults={
  28. 'agent' : 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4',
  29. 'referer': '',
  30. 'cookie': '',
  31. 'action':'',
  32. 'method': 'get',
  33. 'postdata': '',
  34. 'headers': {},
  35. }
  36. for ke in rdefaults:
  37. try:
  38. args[ke]
  39. except KeyError:
  40. args[ke]=rdefaults[ke]
  41. socket.setdefaulttimeout(float(app.url_open_timeout))
  42. if url.find(app.url_navi_server) != -1:
  43. if args['cookie'] >'' and args['cookie'][-2:] != '; ':
  44. args['cookie'] = '%s; ' % args['cookie']
  45. args['cookie'] = args['cookie'] + 'platform=%s; nxid=%s' % (PLATFORM, app.api.user_id, )
  46. try:
  47. hdr = {'User-Agent':args['agent'], 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Referer':args['referer'], 'Cookie':args['cookie']}
  48. except:
  49. print "Unexpected error:", sys.exc_info()[0]
  50. for ke in args['headers']:
  51. try:
  52. hdr[ke] = args['headers'][ke]
  53. except:
  54. print "Unexpected error:", sys.exc_info()[0]
  55. result ={
  56. 'headers':'',
  57. 'geturl':url,
  58. 'cookies':'',
  59. 'content':''
  60. }
  61. try:
  62. cookieprocessor = urllib2.HTTPCookieProcessor()
  63. opener = urllib2.build_opener(cookieprocessor)
  64. urllib2.install_opener(opener)
  65. if args['method'] == 'get':
  66. req = urllib2.Request(url=url, headers = hdr)
  67. else:
  68. req = urllib2.Request(url, args['postdata'], hdr)
  69. response = urllib2.urlopen(req)
  70. cookies={}
  71. for c in cookieprocessor.cookiejar:
  72. cookies[c.name]=c.value
  73. result['headers'] = response.info()
  74. result['geturl'] = response.geturl()
  75. result['cookies'] = cookies
  76. except urllib2.URLError, e:
  77. app.gui.ShowDialogNotification('Error: %s' % e.reason)
  78. response = StringIO.StringIO('')
  79. except:
  80. Log(app, traceback.format_exc() )
  81. response = StringIO.StringIO('')
  82. if args['action'] == 'read':
  83. result['content'] = response.read()
  84. response.close()
  85. else:
  86. result['content'] = response
  87. return result
  88. ### Check if string is UTF-8 encoded
  89. def checkUTF8(string):
  90. try: return string.encode('utf-8')
  91. except: return str(string)
  92. ### Force string to be HEX
  93. def forceHEX(string):
  94. return binascii.hexlify(string)
  95. ### get warning tags from item to output to INFO DIALOG
  96. def checkStreamTags(app, item):
  97. path = item.path
  98. tags = []
  99. info = [key for key in app.navi_streaminfo.keys() if key in path]
  100. if len(info) > 0:
  101. tags.extend(app.navi_streaminfo[info[0]])
  102. if item.subtitle != '':
  103. tags.append('subtitle')
  104. return tags
  105. ### return unique values from list
  106. def unique(inlist):
  107. uniques = []
  108. for item in inlist:
  109. if item not in uniques:
  110. uniques.append(item)
  111. return uniques
  112. ### Get sublist from list of dicts based on keys
  113. def select_sublist(list_of_dicts, **kwargs):
  114. return [dict(d) for d in list_of_dicts
  115. if all(d.get(k)==kwargs[k] for k in kwargs)]
  116. ### Checks if playlist item is recently updated
  117. def process_date(datestring):
  118. if datestring == '' or len(datestring.split('-')) < 3:
  119. return ''
  120. try:
  121. item = datetime.datetime(*time.strptime(datestring,"%Y-%m-%d")[0:5])
  122. now = datetime.datetime.today()
  123. delta = now - item
  124. if delta.days < 2: return 'icons/new.png'
  125. else: return ''
  126. except: return ''
  127. ### Sort list of dicts based on key
  128. def sort_dict(list, key, arg=False):
  129. return sorted(list, key=itemgetter(key), reverse=arg)
  130. ### Sort list of instances based on attribute
  131. def sort_instance(list, key, arg=False):
  132. return sorted(list, key=attrgetter(key), reverse=arg)
  133. ### Load json file from hdd
  134. def json_loads(**kwargs):
  135. try:
  136. if kwargs.get('string', False):
  137. data = json.loads(kwargs['string'])
  138. else:
  139. file = open(kwargs['path'], 'r')
  140. data = json.load(file)
  141. file.close()
  142. return data
  143. except:
  144. msg = 'NAVI-X: JSON syntax error '
  145. if not kwargs.get('string', False): msg = msg + os.path.basename(kwargs['path'])
  146. print msg
  147. traceback.print_exc()
  148. return {}
  149. ### Write json file to hdd
  150. def json_dumps(data, path):
  151. try:
  152. file = open(path, 'w')
  153. json.dump(data, file, indent=3, sort_keys=True)
  154. file.close()
  155. except:
  156. traceback.print_exc()
  157. ### Check Ip for playable content
  158. def ipCheck(app, item):
  159. url = 'http://api.ipinfodb.com/v3/ip-country/?key=053eb7bd26454dfbe57060b35e120193340c688f536899a02047fc787b88b9fa&format=xml'
  160. data = urlopen(app, url, {'action':'read', 'cache':0})
  161. try: code = re.compile('<countryCode>(.*?)</countryCode>', re.DOTALL).search(data).group(1)
  162. except: code = None
  163. if code != 'item':
  164. return app.gui.ShowDialogConfirm("Navi-X", app.local['93'], app.local['100'], app.local['101'])
  165. else: return True
  166. ### Function to support python < 2.5
  167. def all(iterable):
  168. for element in iterable:
  169. if not element:
  170. return False
  171. return True
  172. ### converts url string to path string
  173. def slugify(string):
  174. string = string.strip().lower()
  175. return re.sub(r'[\s_-]+', '-', string)[:41]
  176. ### Try to find the filextension
  177. def getFileExtension(path):
  178. dict = {'http://www.youtube.com':'avi', 'flyupload.com':'mp4'}
  179. ext = [dict[source] for source in dict.keys() if source in path]
  180. if len(ext) > 0:
  181. ext = ext[0][:3]
  182. else:
  183. url_stripped = re.sub('\?.*$', '', path) # strip GET-method args
  184. re_ext = re.compile('(\.\w+)$') # find extension
  185. match = re_ext.search(url_stripped)
  186. if match is None:
  187. ext_pos = path.rfind('.') #find last '.' in the string
  188. if ext_pos != -1:
  189. ext_pos2 = path.rfind('?', ext_pos) #find last '.' in the string
  190. if ext_pos2 != -1:
  191. ext = path[ext_pos+1:ext_pos2][:3]
  192. else:
  193. ext = path[ext_pos+1:][:3]
  194. else:
  195. ext = ''
  196. if ext != '':
  197. ext = '.' + ext[:3]
  198. else:
  199. ext = None
  200. else:
  201. ext = match.group(1)
  202. return ext
  203. ### Try to find the mime type
  204. def getMIME(path):
  205. try:
  206. ext = getFileExtension(path)
  207. mime, encoding = mimetypes.guess_type(ext[1][:5])
  208. return mime
  209. except: return False
  210. ### Converst seconds to timestamp HH:MM
  211. def GetInHMS(seconds):
  212. return str(datetime.timedelta(seconds=int(seconds)))
  213. ### Check if on boxee
  214. def IsBoxee():
  215. if PLATFORM == 'boxee':
  216. return True
  217. else:
  218. return False
  219. ### Check if on xbmc
  220. def IsXBMC():
  221. if PLATFORM == 'xbmc':
  222. return True
  223. else:
  224. return False
  225. ### Check if var1 equals var2
  226. def IsEqual(var1, var2):
  227. if var1 == var2:
  228. return 'True'
  229. else:
  230. return ''
  231. ### Return folder/drive free space (in bytes)
  232. def get_free_space(app, folder):
  233. if app.os == 'windows':
  234. try:
  235. import ctypes
  236. free_bytes = ctypes.c_ulonglong(0)
  237. ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(folder), None, None, ctypes.pointer(free_bytes))
  238. return free_bytes.value
  239. except:
  240. return 0
  241. else:
  242. try:
  243. return os.statvfs(folder).f_bfree
  244. except:
  245. return 0
  246. def can_create_file(folder_path):
  247. try:
  248. f = tempfile.TemporaryFile(dir=folder_path)
  249. f.close()
  250. return True
  251. except OSError:
  252. return False
  253. def thumb_exists(url):
  254. try:
  255. urllib2.urlopen(urllib2.Request(url))
  256. return True
  257. except:
  258. return False
  259. class storage:
  260. """
  261. Saves data to disk or persistant storage
  262. """
  263. def __init__(self, app, eol = 86400):
  264. self.app = app
  265. self.path = self.construct()
  266. self.eol = eol
  267. self.clean()
  268. def construct(self):
  269. """sets cache dir in temp folder"""
  270. id = self.app.appid
  271. prefix = "cache_"
  272. tmp = self.app.tempDir
  273. path = os.path.join(tmp, prefix + id)
  274. if not os.path.exists(path):
  275. os.makedirs(path)
  276. return path
  277. def clean(self):
  278. """removes only data that has been expired (EOL)"""
  279. expire = time.time() - self.eol
  280. for item in os.listdir(self.path):
  281. pointer = os.path.join(self.path, item)
  282. if os.path.isfile(pointer):
  283. timestamp = os.path.getmtime(pointer)
  284. if timestamp <= expire:
  285. os.chmod(pointer, stat.S_IWUSR)
  286. os.remove(pointer)
  287. def empty(self, **kwargs):
  288. """
  289. removes all data from cache
  290. # persistent - boolean, if true empties all persistent data (optional)
  291. """
  292. for root, dirs, files in os.walk(self.path, topdown=False):
  293. for name in files:
  294. filename = os.path.join(root, name)
  295. os.chmod(filename, stat.S_IWUSR)
  296. os.remove(filename)
  297. for name in dirs:
  298. os.rmdir(os.path.join(root, name))
  299. if kwargs.get('persistent', False):
  300. mc.GetApp().GetLocalConfig().ResetAll()
  301. def md5(self, string):
  302. """returns md5 hash of string"""
  303. return md5(string).hexdigest()
  304. def get(self, id, **kwargs):
  305. """
  306. Gets data from storage
  307. # id - string, unique string to identify data
  308. # age - int, if set checks if data is not older then age in seconds (optional)
  309. # persistent - boolean, if true it saves the data persistent (optional)
  310. """
  311. if kwargs.get('age'):
  312. age = kwargs['age']
  313. else:
  314. age = 0
  315. if kwargs.get('persistent', False):
  316. pointer = self.md5(id)
  317. expire = time.time() - age
  318. try:
  319. raw = bz2.decompress(binascii.unhexlify(mc.GetApp().GetLocalConfig().GetValue(pointer)))
  320. timestamp = float(mc.GetApp().GetLocalConfig().GetValue(pointer+"_timestamp"))
  321. if timestamp >= expire:
  322. return marshal.loads(raw)
  323. except:
  324. print traceback.format_exc()
  325. else:
  326. pointer = os.path.join( self.path, self.md5(id) )
  327. expire = time.time() - age
  328. if os.path.isfile(pointer):
  329. timestamp = os.path.getmtime(pointer)
  330. if timestamp >= expire:
  331. try:
  332. fp = open( pointer)
  333. data = marshal.load(fp)
  334. fp.close()
  335. return data
  336. except:
  337. print traceback.format_exc()
  338. return False
  339. def set(self, id, data, **kwargs):
  340. """
  341. Saves data to storage
  342. # id - string, unique string to identify data
  343. # data - any type, data to cache (string, int, list, dict)
  344. # persistent - boolean, if true it saves the data persistent (optional)
  345. """
  346. if kwargs.get('persistent', False):
  347. pointer = self.md5(id)
  348. try:
  349. raw = marshal.dumps(data)
  350. mc.GetApp().GetLocalConfig().SetValue(pointer, binascii.hexlify(bz2.compress(raw)))
  351. mc.GetApp().GetLocalConfig().SetValue(pointer+"_timestamp", str(time.time()))
  352. del raw
  353. return True
  354. except:
  355. print traceback.format_exc()
  356. else:
  357. pointer = os.path.join( self.path, self.md5(id) )
  358. try:
  359. fp = open( pointer, "wb" )
  360. marshal.dump(data, fp)
  361. fp.close()
  362. return True
  363. except:
  364. print traceback.format_exc()
  365. return False