plugin.video.torrenter/functions.py

1548 lines
55 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- coding: utf-8 -*-
import urllib2
import re
import socket
import datetime
import time
import sys
import os
import json
import urllib
import hashlib
import xbmcplugin
import xbmcgui
import xbmc
import xbmcaddon
import xbmcvfs
import Localization
from resources.scrapers.scrapers import Scrapers
try:
from hashlib import md5
except ImportError:
from md5 import md5
try:
from sqlite3 import dbapi2 as sqlite
except:
from pysqlite2 import dbapi2 as sqlite
__settings__ = xbmcaddon.Addon(id='plugin.video.torrenter')
__language__ = __settings__.getLocalizedString
ROOT = __settings__.getAddonInfo('path') # .decode('utf-8').encode(sys.getfilesystemencoding())
userStorageDirectory = __settings__.getSetting("storage")
USERAGENT = "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0"
torrentFilesDirectory = 'torrents'
__addonpath__ = __settings__.getAddonInfo('path')
icon = __addonpath__ + '/icon.png'
debug = __settings__.getSetting("debug")
def clearStorage(userStorageDirectory):
try:
userStorageDirectory = userStorageDirectory.decode('utf-8')
except:
pass
if xbmcvfs.exists(userStorageDirectory + os.sep):
import shutil
temp = userStorageDirectory.rstrip('Torrenter').rstrip('/\\')
shutil.move(os.path.join(userStorageDirectory, 'torrents'), os.path.join(temp, 'torrents'))
shutil.rmtree(userStorageDirectory, ignore_errors=True)
xbmcvfs.mkdir(userStorageDirectory)
shutil.move(os.path.join(temp, 'torrents'), os.path.join(userStorageDirectory, 'torrents'))
DownloadDB().clear()
showMessage(Localization.localize('Storage'), Localization.localize('Storage was cleared'), forced=True)
def sortcomma(dict, json):
for x in dict:
y = dict[x].split(',')
dict[x] = ''
for i in y:
if i not in json:
dict[x] = dict[x] + ',' + i
if len(dict[x]) > 0: dict[x] = dict[x][1:len(dict[x])]
return dict
def md5(string):
hasher = hashlib.md5()
try:
hasher.update(string)
except:
hasher.update(string.encode('utf-8', 'ignore'))
return hasher.hexdigest()
def Debug(msg, force=False):
if (1==1 or debug == 'true' or force):
try:
print "[Torrenter v2] " + msg
except UnicodeEncodeError:
print "[Torrenter v2] " + msg.encode("utf-8", "ignore")
def showMessage(heading, message, times=10000, forced=False):
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s, "%s")' % (
heading.replace('"', "'"), message.replace('"', "'"), times, icon))
def magnet_alert():
showMessage('Ace Stream', Localization.localize('Does not support magnet links!'))
def dates_diff(fdate, ldate):
try:
if ldate == 'today':
x = datetime.datetime.now()
else:
x = datetime.datetime.strptime(ldate, '%d.%m.%Y')
y = datetime.datetime.strptime(fdate, '%d.%m.%Y')
z = x - y
except TypeError:
if ldate == 'today':
x = datetime.datetime.now()
else:
x = datetime.datetime(*(time.strptime(ldate, '%d.%m.%Y')[0:6]))
y = datetime.datetime(*(time.strptime(fdate, '%d.%m.%Y')[0:6]))
z = x - y
return str(z.days)
def today_str():
try:
x = datetime.datetime.now().strftime('%d.%m.%Y')
except TypeError:
x = datetime.datetime(*(time.strptime(datetime.datetime.now().strftime('%d.%m.%Y'), '%d.%m.%Y')[0:6]))
x = datetime.datetime.strftime(x, '%d.%m.%Y')
return str(x)
def get_params():
param = []
paramstring = sys.argv[2]
if len(paramstring) >= 2:
params = sys.argv[2]
cleanedparams = params.replace('?', '')
if (params[len(params) - 1] == '/'):
params = params[0:len(params) - 2]
pairsofparams = cleanedparams.split('&')
param = {}
for i in range(len(pairsofparams)):
splitparams = {}
splitparams = pairsofparams[i].split('=')
if (len(splitparams)) == 2:
param[splitparams[0]] = splitparams[1]
return param
def get_apps(paramstring=None):
if not paramstring: paramstring = sys.argv[2]
if len(paramstring) >= 2:
try:
apps = json.loads(urllib.unquote_plus(paramstring))
except:
cleanapps = str(paramstring).replace('?', '', 1)
apps = json.loads(urllib.unquote_plus(cleanapps))
return apps
def int_xx(intxx):
if intxx and intxx != 'None':
return '%02d' % (int(intxx))
else:
return '00'
def StripName(name, list, replace=' '):
lname = name.lower().split(' ')
name = ''
for n in lname:
if n not in list: name += ' ' + n
return name.strip()
def tempdir():
dirname = xbmc.translatePath('special://temp')
for subdir in ('xbmcup', 'plugin.video.torrenter'):
dirname = os.path.join(dirname, subdir)
if not os.path.exists(dirname):
os.mkdir(dirname)
return dirname
def makeapp(s):
return urllib.quote_plus(json.dumps(s))
def get_url(cookie, url):
headers = {'User-Agent': 'XBMC',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': cookie}
try:
conn = urllib2.urlopen(urllib2.Request(url, urllib.urlencode({}), headers))
array = conn.read()
# Debug('[get_url]: arr"'+str(array)+'"')
if array == '':
# Debug('[get_url][2]: arr=""')
array = True
return array
except urllib2.HTTPError as e:
# Debug('[get_url]: HTTPError, e.code='+str(e.code))
if e.code == 401:
Debug('[get_url]: Denied! Wrong login or api is broken!')
return
elif e.code in [503]:
Debug('[get_url]: Denied, HTTP Error, e.code=' + str(e.code))
return
else:
showMessage('HTTP Error', str(e.code))
Debug('[get_url]: HTTP Error, e.code=' + str(e.code))
xbmc.sleep(2000)
return
except:
return False
def post_url_json(cookie, url, post):
headers = {'User-Agent': 'XBMC',
'Connection': 'keep-alive',
'Cookie': cookie}
conn = urllib2.urlopen(urllib2.Request(url, post, headers))
array = conn.read()
conn.close()
return array
def creat_db(dbfilename):
db = sqlite.connect(dbfilename)
cur = db.cursor()
cur.execute('pragma auto_vacuum=1')
cur.execute(
'create table sources(addtime integer, filename varchar(32) PRIMARY KEY, showId integer, seasonId integer, episodeId integer, id integer, stype varchar(32))')
cur.execute('create table cache(addtime integer, url varchar(32))')
cur.execute('create table scan(addtime integer, filename varchar(32) PRIMARY KEY)')
cur.execute('create table watched(addtime integer, rating integer, id varchar(32) PRIMARY KEY)')
db.commit()
cur.close()
db.close()
def invert_bool(var):
if bool(var):
var = False
else:
var = True
return var
def getSettingAsBool(setting):
return __settings__.getSetting(setting).lower() == "true"
def calculate(full):
consts = [(100, 20), (300, 15), (500, 10), (2000, 7), (4000, 5)]
max_const = 150
repl_const = 0
for size, const in consts:
if (size * 1024 * 1024) > full:
repl_const = int(float(const) / 100 * (full / (1024 * 1024))) # MB of first
break
if repl_const == 0:
repl_const = max_const
return repl_const
def getDirList(path, newl=None):
l = []
try:
if not newl: dirs, newl = xbmcvfs.listdir(path)
except:
try:
if not newl: dirs, newl = xbmcvfs.listdir(path.decode('utf-8').encode('cp1251'))
except:
showMessage(__language__(30206), __language__(30280), forced=True)
return l
for fl in newl:
match = re.match('.avi|.mp4|.mkV|.flv|.mov|.vob|.wmv|.ogm|.asx|.mpg|mpeg|.avc|.vp3|.fli|.flc|.m4v',
fl[int(len(fl)) - 4:len(fl)], re.I)
if match:
l.append(fl)
return l
def cutFileNames(l):
from difflib import Differ
d = Differ()
text = sortext(l)
newl = []
for li in l: newl.append(cutStr(li[0:len(li) - 1 - len(li.split('.')[-1])]))
l = newl
text1 = cutStr(text[0][0:len(text[0]) - 1 - len(text[0].split('.')[-1])])
text2 = cutStr(text[1][0:len(text[1]) - 1 - len(text[1].split('.')[-1])])
sep_file = " "
result = list(d.compare(text1.split(sep_file), text2.split(sep_file)))
Debug('[cutFileNames] ' + unicode(result))
start = ''
end = ''
for res in result:
if str(res).startswith('-') or str(res).startswith('+') or str(res).startswith('.?'):
break
start = start + str(res).strip() + sep_file
result.reverse()
for res in result:
if str(res).startswith('-') or str(res).startswith('+') or str(res).startswith('?'):
break
end = sep_file + str(res).strip() + end
newl = l
l = []
Debug('[cutFileNames] [start] ' + start)
Debug('[cutFileNames] [end] ' + end)
for fl in newl:
if cutStr(fl[0:len(start)]) == cutStr(start): fl = fl[len(start):]
if cutStr(fl[len(fl) - len(end):]) == cutStr(end): fl = fl[0:len(fl) - len(end)]
try:
isinstance(int(fl.split(sep_file)[0]), int)
fl = fl.split(sep_file)[0]
except:
pass
l.append(fl)
Debug('[cutFileNames] [sorted l] ' + unicode(sorted(l, key=lambda x: x)), True)
return l
def cutStr(s):
return s.replace('.', ' ').replace('_', ' ').replace('[', ' ').replace(']', ' ').lower().strip()
def sortext(filelist):
result = {}
for name in filelist:
ext = name.split('.')[-1]
try:
result[ext] = result[ext] + 1
except:
result[ext] = 1
lol = result.iteritems()
lol = sorted(lol, key=lambda x: x[1])
Debug('[sortext]: lol:' + str(lol))
popext = lol[-1][0]
result, i = [], 0
for name in filelist:
if name.split('.')[-1] == popext:
result.append(name)
i = i + 1
result = sweetpair(result)
Debug('[sortext]: result:' + str(result))
return result
def cutFolder(contentList, tdir=None):
dirList, contentListNew = [], []
if len(contentList) > 1:
common_folder = contentList[0][0]
if '\\' in common_folder:
common_folder = common_folder.split('\\')[0]
elif '/' in common_folder:
common_folder = common_folder.split('/')[0]
common = True
for fileTitle, contentId in contentList:
if common_folder not in fileTitle:
print 'no common'
common = False
break
#print common_folder
for fileTitle, contentId in contentList:
dir = None
if common:
fileTitle = fileTitle[len(common_folder) + 1:]
#print fileTitle
if '\\' in fileTitle:
dir = fileTitle.split('\\')[0]
elif '/' in fileTitle:
dir = fileTitle.split('/')[0]
elif not tdir:
contentListNew.append((fileTitle, contentId))
if tdir and dir == tdir:
contentListNew.append((fileTitle[len(dir) + 1:], contentId))
if not tdir and dir and dir not in dirList:
dirList.append(dir)
return dirList, contentListNew
else:
return dirList, contentList
def sweetpair(l):
from difflib import SequenceMatcher
s = SequenceMatcher()
ratio = []
for i in range(0, len(l)): ratio.append(0)
for i in range(0, len(l)):
for p in range(0, len(l)):
s.set_seqs(l[i], l[p])
ratio[i] = ratio[i] + s.quick_ratio()
id1, id2 = 0, 0
for i in range(0, len(l)):
if ratio[id1] <= ratio[i] and i != id2 or id2 == id1 and ratio[id1] == ratio[i]:
id2 = id1
id1 = i
# Debug('1 - %d %d' % (id1, id2))
elif (ratio[id2] <= ratio[i] or id1 == id2) and i != id1:
id2 = i
# Debug('2 - %d %d' % (id1, id2))
Debug('[sweetpair]: id1 ' + l[id1] + ':' + str(ratio[id1]))
Debug('[sweetpair]: id2 ' + l[id2] + ':' + str(ratio[id2]))
return [l[id1], l[id2]]
def FileNamesPrepare(filename):
my_season = None
my_episode = None
try:
if int(filename):
my_episode = int(filename)
Debug('[FileNamesPrepare] ' + str([my_season, my_episode, filename]))
return [my_season, my_episode, filename]
except:
pass
urls = ['s(\d+)e(\d+)', '(\d+)[x|-](\d+)', 'E(\d+)', 'Ep(\d+)', '\((\d+)\)']
for file in urls:
match = re.compile(file, re.DOTALL | re.I | re.IGNORECASE).findall(filename)
if match:
try:
my_episode = int(match[1])
my_season = int(match[0])
except:
try:
my_episode = int(match[0])
except:
try:
my_episode = int(match[0][1])
my_season = int(match[0][0])
except:
try:
my_episode = int(match[0][0])
except:
break
if my_season and my_season > 100: my_season = None
if my_episode and my_episode > 365: my_episode = None
Debug('[FileNamesPrepare] ' + str([my_season, my_episode, filename]))
return [my_season, my_episode, filename]
def filename2match(filename, no_date=False):
results = {'label': filename}
urls = ['(.+|.?)s(\d+)e(\d+)', '(.+|.?)s(\d+)\.e(\d+)', '(.+|.?) [\[|\(](\d+)[x|-](\d+)[\]|\)]',
'(.+|.?) (\d+)[x|-](\d+)'] # same in service
for file in urls:
match = re.compile(file, re.I | re.IGNORECASE).findall(filename)
# print str(results)
if match:
results['showtitle'], results['season'], results['episode'] = match[0]
results['showtitle'] = results['showtitle'].replace('.', ' ').replace('_', ' ').strip().replace(
'The Daily Show', 'The Daily Show With Jon Stewart')
results['season'], results['episode'] = int(results['season']), int(results['episode'])
# Debug('[filename2match] '+str(results))
return results
if no_date: return
urls = ['(.+)(\d{4})\.(\d{2,4})\.(\d{2,4})', '(.+)(\d{4}) (\d{2}) (\d{2})'] # same in service
for file in urls:
match = re.compile(file, re.I | re.IGNORECASE).findall(filename)
if match:
results['showtitle'] = match[0][0].replace('.', ' ').strip().replace('The Daily Show',
'The Daily Show With Jon Stewart')
results['date'] = '%s.%s.%s' % (match[0][3], match[0][2], match[0][1])
Debug('[filename2match] ' + str(results))
return results
def TextBB(string, action=None, color=None):
if action == 'b':
string = '[B]' + string + '[/B]'
return string
def jstr(s):
if not s:
s = 'null'
elif not unicode(s).isnumeric():
s = '"%s"' % (s)
return str(s)
def view_style(func):
styles = {}
num_skin, style = 0, 'info'
view_style = int(__settings__.getSetting("skin_optimization"))
if view_style in [3, 2]:
styles['searchOption'] = styles['History'] = styles['List'] = 'info'
styles['drawContent'] = styles['drawtrackerList'] = styles['drawcontentList'] = 'info'
styles['sectionMenu'] = styles['Seasons'] = 'list'
styles['uTorrentBrowser'] = styles['torrentPlayer'] = styles['openTorrent'] = 'wide'
styles['showFilesList'] = styles['DownloadStatus'] = 'wide'
elif view_style in [1, 4]:
styles['searchOption'] = 'info'
styles['drawContent'] = styles['torrentPlayer'] = styles['openTorrent'] = styles['drawtrackerList'] = 'info'
styles['uTorrentBrowser'] = styles['History'] = styles['DownloadStatus'] = 'wide'
styles['showFilesList'] = styles['sectionMenu'] = 'wide'
styles['List'] = styles['drawcontentList'] = 'info3'
if view_style == 1:
styles['uTorrentBrowser'] = styles['torrentPlayer'] = 'wide'
styles['openTorrent'] = styles['History'] = styles['DownloadStatus'] = 'wide'
styles['sectionMenu'] = 'icons'
if view_style in [1, 3, 4]:
num_skin = 0
elif view_style == 2:
num_skin = 1
style = styles.get(func)
# Debug('[view_style]: lock '+str(style))
lockView(style, num_skin)
def lockView(viewId='info', num_skin=0):
xbmcplugin.setContent(int(sys.argv[1]), 'movies')
skinOptimizations = (
{'list': 50, 'info': 50, 'wide': 51, 'icons': 500, 'info3': 515, }, # Confluence
{'list': 50, 'info': 51, 'wide': 52, 'icons': 53, } # Transperency!
)
try:
xbmc.executebuiltin("Container.SetViewMode(%s)" % str(skinOptimizations[num_skin][viewId]))
except:
return
'''
<include>PosterWrapView2_Fanart</include> <!-- view id = 508 -->
<include>MediaListView3</include> <!-- view id = 503 -->
<include>MediaListView2</include> <!-- view id = 504 -->
<include>MediaListView4</include> <!-- view id = 515 -->
<include>WideIconView</include> <!-- view id = 505 -->
<include>MusicVideoInfoListView</include> <!-- view id = 511 -->
<include>AddonInfoListView1</include> <!-- view id = 550 -->
<include>AddonInfoThumbView1</include> <!-- view id = 551 -->
<include>LiveTVView1</include> <!-- view id = 560 -->
'''
def torrent_dir():
from resources.utorrent.net import Download
socket.setdefaulttimeout(3)
list = Download().list()
ret = 0
if list and len(list) > 0:
dirs = ["Keyboard"]
for dl in list:
if dl['dir'] not in dirs:
dirs.append(dl['dir'])
basename = os.path.dirname(dl['dir'])
if basename not in dirs:
dirs.append(basename)
else:
dirs.remove(basename)
dirs.insert(1, basename)
dialog = xbmcgui.Dialog()
ret = dialog.select(Localization.localize('Manual Torrent-client Path Edit'), dirs)
else:
ret = 0
if ret == 0:
KB = xbmc.Keyboard()
KB.setHeading(Localization.localize('Manual Torrent-client Path Edit'))
KB.setDefault(__settings__.getSetting("torrent_dir"))
KB.doModal()
if (KB.isConfirmed()):
__settings__.setSetting("torrent_dir", KB.getText())
elif ret > 0:
__settings__.setSetting("torrent_dir", dirs[ret])
def saveCheckPoint():
__settings__.setSetting("checkpoint", str(sys.argv[2]))
def gotoCheckPoint():
xbmc.executebuiltin(
'XBMC.ActivateWindow(Videos,plugin://plugin.video.myshows/%s)' % (__settings__.getSetting("checkpoint")))
def smbtopath(path):
x = path.split('@')
if len(x) > 1:
path = x[1]
else:
path = path.replace('smb://', '')
Debug('[smbtopath]:' + '\\\\' + path.replace('/', '\\'))
return '\\\\' + path.replace('/', '\\')
def PrepareFilename(filename):
badsymb = [':', '"', '\\', '/', '\'', '!', ['&', 'and'], '*', '?', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ',
' ', ' ']
for b in badsymb:
if not isinstance(b, list):
filename = filename.replace(b, ' ')
else:
filename = filename.replace(b[0], b[1])
return filename.rstrip('. ')
def PrepareSearch(filename):
titles = [filename]
rstr = '. -'
badsymb = [':', '"', r'\\', '/', r'\'', '!', '&', '*', '_', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ' ']
for b in badsymb:
filename = filename.replace(b, ' ')
filename = re.sub("\([^)]*\)([^(]*)", "\\1", filename)
filename = re.sub("\[[^\]]*\]([^\[]*)", "\\1", filename)
filename = filename.strip().rstrip(rstr)
if titles[0] != filename and filename != '': titles.insert(0, filename)
title_array = [(u'(.+?)(Cезон|cезон|Сезон|сезон|Season|season|СЕЗОН|SEASON)', titles[0], 0),
(u'(.+?)[sS](\d{1,2})', titles[0].replace('.', ' '), 0),
]
for regex, title, i in title_array:
recomp = re.compile(regex)
match = recomp.findall(title)
if match:
titles.insert(0, match[0][i].rstrip(rstr))
return titles
def kinorate(title, year, titleAlt=None, kinopoiskId=None):
if kinopoiskId:
match = {'title': title.replace('"', ''), 'year': str(year), 'kinopoiskId': str(kinopoiskId)}
else:
match = {'title': title.replace('"', ''), 'year': str(year)}
if titleAlt:
match['titleAlt'] = titleAlt.replace('"', '')
try:
xbmc.executebuiltin(
'xbmc.RunScript(' + xbmcaddon.Addon("script.myshows").getAddonInfo("path") + os.sep +
'sync_exec.py,' + json.dumps(match).replace(',', '|:|') + ')')
except:
return False
class RateShow():
def __init__(self, showId, watched_jdata=None):
self.dialog = xbmcgui.Dialog()
self.showId = showId
self.list = {}
if watched_jdata:
self.watched_jdata = watched_jdata
else:
watched_data = Data(cookie_auth, __baseurl__ + '/profile/shows/' + str(showId) + '/',
__baseurl__ + '/profile/shows/' + str(showId) + '/')
try:
self.watched_jdata = json.loads(watched_data.get())
except:
Debug('[RateShow] no watched_jdata1')
return
if not self.watched_jdata:
Debug('[RateShow] no watched_jdata2')
return
def seasonrates(self):
jload = Data(cookie_auth, __baseurl__ + '/profile/shows/').get()
jshowdata = json.loads(jload)
if str(self.showId) in jshowdata:
self.list, seasonNumber = self.listSE(jshowdata[str(self.showId)]['totalEpisodes'])
ratedict = {}
for i in self.list:
for j in self.list[i]:
if self.watched_jdata.has_key(j):
if self.watched_jdata[j]['rating']:
if ratedict.has_key(i):
ratedict[i].append(self.watched_jdata[j]['rating'])
else:
ratedict[i] = [self.watched_jdata[j]['rating']]
# Debug('[ratedict]:'+str(ratedict))
for i in ratedict:
ratedict[i] = (round(float(sum(ratedict[i])) / len(ratedict[i]), 2), len(ratedict[i]))
Debug('[ratedict]:' + str(ratedict))
else:
ratedict = {}
return ratedict
def count(self):
ratings, seasonratings = [], []
showId = str(self.showId)
jload = Data(cookie_auth, __baseurl__ + '/profile/shows/').get()
jshowdata = json.loads(jload)
self.list, seasonNumber = self.listSE(jshowdata[showId]['totalEpisodes'])
old_rating = jshowdata[showId]['rating']
for id in self.watched_jdata:
if self.watched_jdata[id]['rating']:
ratings.append(self.watched_jdata[id]['rating'])
if id in self.list[str(seasonNumber)]:
seasonratings.append(self.watched_jdata[id]['rating'])
# Debug('ratings:'+str(ratings)+'; seasonratings:'+str(seasonratings))
if len(ratings) > 0:
rating = round(float(sum(ratings)) / len(ratings), 2)
else:
rating = 0
if len(seasonratings) > 0:
seasonrating = round(float(sum(seasonratings)) / len(seasonratings), 2)
else:
seasonrating = 0
return rating, seasonNumber, seasonrating, old_rating
def listSE(self, maxep):
listSE, seasonNumber = {}, 0
data = Data(cookie_auth, __baseurl__ + '/shows/' + str(self.showId))
jdata = json.loads(data.get())
for id in jdata['episodes']:
if maxep >= jdata['episodes'][id]['sequenceNumber']:
if listSE.has_key(str(jdata['episodes'][id]['seasonNumber'])):
listSE[str(jdata['episodes'][id]['seasonNumber'])].append(id)
else:
listSE[str(jdata['episodes'][id]['seasonNumber'])] = [id]
if jdata['episodes'][id]['seasonNumber'] > seasonNumber:
seasonNumber = jdata['episodes'][id]['seasonNumber']
# Debug('[listSE] '+str(listSE)+str(seasonNumber))
return listSE, seasonNumber
def isRemoteTorr():
localhost = ['127.0.0.1', '0.0.0.0', 'localhost']
if __settings__.getSetting("torrent") == '0':
if __settings__.getSetting("torrent_utorrent_host") not in localhost:
Debug('[isRemoteTorr]: uTorrent is Remote!')
return True
elif __settings__.getSetting("torrent") == '1':
if __settings__.getSetting("torrent_transmission_host") not in localhost:
Debug('[isRemoteTorr]: Transmission is Remote!')
return True
def changeDBTitle(showId):
from utilities import xbmcJsonRequest
shows = xbmcJsonRequest(
{'jsonrpc': '2.0', 'method': 'VideoLibrary.GetTVShows', 'params': {'properties': ['title']}, 'id': 0})
if not shows:
Debug('[changeDBTitle]: XBMC JSON Result was empty.')
return
if 'tvshows' in shows:
shows = shows['tvshows']
Debug("[changeDBTitle]: XBMC JSON Result: '%s'" % str(shows))
else:
Debug("[changeDBTitle]: Key 'tvshows' not found")
return
if len(shows) > 0:
newtitle = id2title(showId, None, True)[0].decode('utf-8', 'ignore')
dialog = xbmcgui.Dialog()
dialog_items, dialog_ids = [__language__(30205)], [-1]
shows = sorted(shows, key=lambda x: x['tvshowid'], reverse=True)
for show in shows:
dialog_ids.append(show['tvshowid'])
dialog_items.append(show['title'])
ret = dialog.select(newtitle, dialog_items)
if ret > 0:
ok = dialog.yesno(__language__(30322), __language__(30534),
__language__(30535) % (dialog_items[ret], newtitle))
if ok:
result = xbmcJsonRequest({'jsonrpc': '2.0', 'method': 'VideoLibrary.SetTVShowDetails',
'params': {'tvshowid': int(dialog_ids[ret]), 'title': unicode(newtitle)},
'id': 1})
if result in [newtitle, 'OK']:
showMessage(__language__(30208), __language__(30536) % (newtitle), forced=True)
else:
Debug("[changeDBTitle]: XBMC JSON Result: '%s'" % str(result))
return
class TimeOut():
def __init__(self):
self.scan = CacheDB('web_timeout')
self.gone_online = CacheDB('go_online')
self.get = self.scan.get()
self.online = 30
self.offline = 1
def go_offline(self, manual=False):
gone_online = self.gone_online.get()
if gone_online:
gone_online = int(gone_online)
else:
gone_online = 0
if not manual:
if gone_online and gone_online + self.online >= int(round(time.time())):
Debug('[TimeOut]: too soon to go back offline! %d s' % (
(gone_online + self.online * 4) - int(round(time.time()))))
return
if self.timeout() == self.online:
Debug('[TimeOut]: Gone offline! %d s' % ((gone_online + self.online * 4) - int(round(time.time()))))
showMessage(__language__(30520), __language__(30545) % (self.offline))
if self.get: self.scan.delete()
self.scan.add()
def go_online(self):
if self.get:
self.scan.delete()
Debug('[TimeOut]: Gone online!')
showMessage(__language__(30521), __language__(30545) % (self.online))
if self.gone_online.get():
self.gone_online.delete()
self.gone_online.add()
def timeout(self):
if self.get and int(time.time()) - self.get < refresh_period * 3600:
to = self.offline
else:
to = self.online
# Debug('[TimeOut]: '+str(to))
return to
class ListDB:
def __init__(self, version=1.0):
self.dbname = 'list' + '.db3'
dirname = xbmc.translatePath('special://temp')
self.dbfilename = os.path.join(dirname, 'xbmcup',
__settings__.getAddonInfo('id').replace('plugin://', '').replace('/', ''),
self.dbname)
self.version = version
if not xbmcvfs.exists(self.dbfilename):
self.creat_db()
def creat_db(self):
self._connect()
self.cur.execute('pragma auto_vacuum=1')
self.cur.execute('create table db_ver(version real)')
# self.cur.execute('create table list(addtime integer PRIMARY KEY, title varchar(32), originaltitle varchar(32)'
# ', year integer, category varchar(32), subcategory varchar(32))')
self.cur.execute('create table list(addtime integer PRIMARY KEY, info varchar(32))')
self.cur.execute('insert into db_ver(version) values(?)', (self.version, ))
self.db.commit()
self._close()
def get(self, addtime):
self._connect()
self.cur.execute('select info from list where addtime="' + addtime + '"')
x = self.cur.fetchone()
self._close()
return x[0] if x else None
def get_all(self):
self._connect()
# self.cur.execute('select addtime,title,originaltitle,year,category,subcategory from list')
self.cur.execute('select addtime,info from list')
x = self.cur.fetchall()
self._close()
return x if x else None
def add(self, url):
self._connect()
self.cur.execute('insert into list(addtime,info)'
' values(?,?)', (int(time.time()), url))
self.db.commit()
self._close()
def delete(self, addtime):
self._connect()
self.cur.execute('delete from list where addtime="' + addtime + '"')
self.db.commit()
self._close()
def _connect(self):
self.db = sqlite.connect(self.dbfilename)
self.cur = self.db.cursor()
def _close(self):
self.cur.close()
self.db.close()
class HistoryDB:
def __init__(self, version=1.1):
self.name = 'history.db3'
self.version = version
def get_all(self):
self._connect()
self.cur.execute('select addtime,string,fav from history order by addtime DESC')
x = self.cur.fetchall()
self._close()
return x if x else None
def get(self, url):
self._connect()
self.cur.execute('select string from history where string="' + url + '"')
x = self.cur.fetchone()
self._close()
return x[0] if x else None
def get_providers(self, addtime):
self._connect()
self.cur.execute('select providers from history where addtime="' + addtime + '"')
x = self.cur.fetchone()
self._close()
#print 'get_providers: '+str(x[0].split(',') if x and x[0]!='' else None)
return x[0].split(',') if x and x[0]!='' else None
def set_providers(self, addtime, providers):
self._connect()
if isinstance(providers, dict):
temp=[]
for i in providers.keys():
if providers.get(i):
temp.append(i)
providers=temp
str_p=','.join(providers)
self.cur.execute('UPDATE history SET providers = "' + str_p + '" where addtime=' + addtime)
self.db.commit()
self._close()
def change_providers(self, addtime, searcher):
self._connect()
providers=self.get_providers(addtime)
keys=Searchers().dic().keys()
if providers and len(providers)>0:
if searcher in providers:
providers.remove(searcher)
else:
providers.append(searcher)
for i in providers:
if i not in keys:
providers.remove(i)
self.set_providers(addtime, providers)
self.db.commit()
self._close()
def add(self, url):
if not self.get(url):
self._connect()
self.cur.execute('insert into history(addtime,string,fav,providers)'
' values(?,?,?,?)', (int(time.time()), decode(url), 0, ""))
self.db.commit()
self._close()
def update(self, addtime, fav):
self._connect()
self.cur.execute('UPDATE history SET fav = ' + str(fav) + ' where addtime=' + addtime)
self.db.commit()
self._close()
def fav(self, addtime):
self.update(addtime, fav=1)
def unfav(self, addtime):
self.update(addtime, fav=0)
def delete(self, addtime):
self._connect()
self.cur.execute('delete from history where addtime="' + addtime + '"')
self.db.commit()
self._close()
def clear(self):
self._connect()
self.cur.execute('delete from history where fav=0')
self.db.commit()
self._close()
def _connect(self):
dirname = xbmc.translatePath('special://temp')
for subdir in ('xbmcup', 'plugin.video.torrenter'):
dirname = os.path.join(dirname, subdir)
if not xbmcvfs.exists(dirname):
xbmcvfs.mkdir(dirname)
self.filename = os.path.join(dirname, self.name)
first = False
if not xbmcvfs.exists(self.filename):
first = True
self.db = sqlite.connect(self.filename, check_same_thread=False)
if not first:
self.cur = self.db.cursor()
try:
self.cur.execute('select version from db_ver')
row = self.cur.fetchone()
if not row or float(row[0]) != self.version:
self.cur.execute('drop table history')
self.cur.execute('drop table if exists db_ver')
first = True
self.db.commit()
self.cur.close()
except:
self.cur.execute('drop table history')
first = True
self.db.commit()
self.cur.close()
if first:
cur = self.db.cursor()
cur.execute('pragma auto_vacuum=1')
cur.execute('create table db_ver(version real)')
cur.execute(
'create table history(addtime integer PRIMARY KEY, string varchar(32), providers varchar(32), fav integer)')
cur.execute('insert into db_ver(version) values(?)', (self.version, ))
self.db.commit()
cur.close()
self.cur = self.db.cursor()
def _close(self):
self.cur.close()
self.db.close()
class Searchers():
def __init__(self):
pass
def getBoolSetting(self, setting):
return __settings__.getSetting(setting).lower() == "true"
def setBoolSetting(self, setting, bool=True):
__settings__.setSetting(setting, "true" if bool else "false")
def list(self):
searchersList = []
dirList = os.listdir(ROOT + os.sep + 'resources' + os.sep + 'searchers')
for searcherFile in dirList:
if re.match('^(\w+)\.py$', searcherFile):
searchersList.append(searcherFile.replace('.py', ''))
return searchersList
def dic(self, providers=[]):
dic = {}
for searcher in self.list():
if not providers:
dic[searcher] = self.old(searcher)
else:
dic[searcher] = searcher in providers
return dic
def old(self, searcher):
if not self.getBoolSetting('old_' + searcher):
self.setBoolSetting('old_' + searcher)
self.setBoolSetting(searcher)
return self.getBoolSetting(searcher)
def get_active(self):
get_active = []
for searcher in self.list():
if self.old(searcher): get_active.append(searcher + '.py')
print 'Active Searchers: '+str(get_active)
return get_active
class Contenters():
def __init__(self):
pass
def first_time(self, scrapperDB_ver, language='ru'):
searcher = 'metadata'
redl = False
scrapperDB_ver=scrapperDB_ver[language]
if scrapperDB_ver != __settings__.getSetting('scrapperDB_ver'+language) and self.getBoolSetting(searcher):
__settings__.setSetting('scrapperDB_ver'+language, scrapperDB_ver)
ok = xbmcgui.Dialog().yesno('< %s >' % Localization.localize('Content Lists'),
Localization.localize('Your preloaded databases are outdated!'),
Localization.localize('Do you want to download new ones right now?'))
if ok:
dirname = xbmc.translatePath('special://temp')
dirname = os.path.join(dirname, 'xbmcup', 'plugin.video.torrenter')
scrapers = {'tvdb': 'TheTVDB.com', 'tmdb': 'TheMovieDB.org', 'kinopoisk': 'KinoPoisk.ru'}
for i in scrapers.keys():
xbmcvfs.delete(os.path.join(dirname, i+'.'+language + '.db'))
showMessage(Localization.localize('Reset All Cache DBs'), Localization.localize('Deleted!'))
redl = True
else:
xbmcgui.Dialog().ok('< %s >' % Localization.localize('Content Lists'),
Localization.localize(
'You can always restart this by deleting DBs via Context Menu'), )
if not self.getBoolSetting('oldc_' + searcher + language):
self.setBoolSetting('oldc_' + searcher+ language, True)
__settings__.setSetting('scrapperDB_ver'+language, scrapperDB_ver)
ok = xbmcgui.Dialog().yesno('< %s >' % Localization.localize('Content Lists'),
Localization.localize('Do you want to search and cache full metadata + arts?'),
Localization.localize(
'This vastly decreases load speed, but you will be asked to download premade bases!'))
if ok:
self.setBoolSetting(searcher, True)
redl = True
else:
self.setBoolSetting(searcher, False)
if redl:
self.Scraper = Scrapers()
scrapers = {'tvdb': 'TheTVDB.com', 'tmdb': 'TheMovieDB.org', 'kinopoisk': 'KinoPoisk.ru'}
for scraper in scrapers.keys():
if scraper!='kinopoisk' or language=='ru':
self.Scraper.scraper(scraper, {'label': 'Мстители', 'search': [u'Мстители', u'The Avengers'],
'year': 2012}, language)
def getBoolSetting(self, setting):
return __settings__.getSetting(setting).lower() == "true"
def setBoolSetting(self, setting, bool=True):
__settings__.setSetting(setting, "true" if bool else "false")
def list(self):
searchersList = []
dirList = os.listdir(ROOT + os.sep + 'resources' + os.sep + 'contenters')
for searcherFile in dirList:
if re.match('^(\w+)\.py$', searcherFile):
searchersList.append(searcherFile.replace('.py', ''))
return searchersList
def dic(self):
dic = {}
for searcher in self.list():
dic[searcher] = self.old(searcher)
return dic
def get_activedic(self):
dic = {}
# for searcher in self.list():
# if self.old(searcher): dic[searcher]=(searcher,)
for searcher in self.list():
dic[searcher] = (searcher,)
return dic
def old(self, searcher):
if not self.getBoolSetting('oldc_' + searcher):
self.setBoolSetting('oldc_' + searcher)
self.setBoolSetting(searcher)
return self.getBoolSetting(searcher)
def get_active(self):
get_active = []
for searcher in self.list():
if self.old(searcher): get_active.append(searcher)
return get_active
class WatchedDB:
def __init__(self):
dirname = xbmc.translatePath('special://temp')
for subdir in ('xbmcup', __settings__.getAddonInfo('id').replace('plugin://', '').replace('/', '')):
dirname = os.path.join(dirname, subdir)
if not xbmcvfs.exists(dirname):
xbmcvfs.mkdir(dirname)
self.dbfilename = os.path.join(dirname, 'data.db3')
if not xbmcvfs.exists(self.dbfilename):
creat_db(self.dbfilename)
self.dialog = xbmcgui.Dialog()
def _get(self, id):
self._connect()
Debug('[WatchedDB][_get]: Checking ' + id)
id = id.replace("'", "<&amp>").decode('utf-8', 'ignore')
self.where = " where id='%s'" % (id)
try:
self.cur.execute('select rating from watched' + self.where)
except:
self.cur.execute('create table watched(addtime integer, rating integer, id varchar(32) PRIMARY KEY)')
self.cur.execute('select rating from watched' + self.where)
res = self.cur.fetchone()
self._close()
return res[0] if res else None
def _get_all(self):
self._connect()
self.cur.execute('select id, rating from watched order by addtime desc')
res = [[unicode(x[0]).replace("<&amp>", "'").encode('utf-8', 'ignore'), x[1]] for x in self.cur.fetchall()]
self._close()
return res
def check(self, id, rating=0):
ok1, ok3 = None, None
db_rating = self._get(id)
title = titlesync(id)
TimeOut().go_offline()
if getSettingAsBool("silentoffline"):
if db_rating == None and rating >= 0:
showMessage(__language__(30520), __language__(30522) % (str(rating)))
ok1 = True
elif db_rating >= 0 and rating != db_rating and rating > 0:
showMessage(__language__(30520), __language__(30523) % (str(rating)))
ok3 = True
elif db_rating != None and rating == db_rating:
showMessage(__language__(30520), __language__(30524) % (str(rating)))
else:
if db_rating == None and rating >= 0:
if title:
title = title.encode('utf-8', 'ignore')
ok1 = self.dialog.yesno(__language__(30520), __language__(30525) % (str(rating)), title)
else:
ok1 = True
elif db_rating and rating != db_rating:
if title:
title = title.encode('utf-8', 'ignore')
ok3 = self.dialog.yesno(__language__(30520), __language__(30526) % (str(db_rating), str(rating)),
title)
else:
ok3 = True
elif db_rating == 0 and rating != db_rating:
ok3 = True
elif db_rating != None and rating == db_rating:
showMessage(__language__(30520), __language__(30527) % (str(rating)))
Debug('[WatchedDB][check]: rating: %s DB: %s, ok1: %s, ok3: %s' % (
str(rating), str(db_rating), str(ok1), str(ok3)))
if ok1:
self._add(id, rating)
return True
if ok3:
self._delete(id)
self._add(id, rating)
return True
def onaccess(self):
# Debug('[WatchedDB][onaccess]: Start')
TimeOut().go_online()
self._connect()
try:
self.cur.execute('select count(id) from watched')
except:
self.cur.execute('create table watched(addtime integer, rating integer, id varchar(32) PRIMARY KEY)')
self.cur.execute('select count(id) from watched')
x = self.cur.fetchone()
res = int(x[0])
self._close()
i = 0
if res > 0:
# Debug('[WatchedDB][onaccess]: Found %s' % (str(res)))
silentofflinesend = getSettingAsBool('silentofflinesend')
if not silentofflinesend:
ok2 = self.dialog.yesno(__language__(30521), __language__(30528) % (str(res)), __language__(30529))
else:
ok2 = True
if ok2:
for id, rating in self._get_all():
from addon import SyncXBMC
j = SyncXBMC(id, int(rating)).doaction()
if j:
i = i + int(j)
self._delete(id)
showMessage(__language__(30521), __language__(30530) % (i))
__settings__.setSetting("duo_last_id", '')
else:
ok2 = self.dialog.yesno(__language__(30521), __language__(30531) % (str(res)))
if ok2:
for id, rating in self._get_all():
self._delete(id)
return res
def _add(self, id, rating=0):
__settings__.setSetting("duo_last_id", '')
self._connect()
id = id.replace("'", "<&amp>").decode('utf-8', 'ignore')
Debug('[WatchedDB][_add]: Adding %s with rate %d' % (id, rating))
self.cur.execute('insert into watched(addtime, rating, id) values(?,?,?)', (int(time.time()), int(rating), id))
self.db.commit()
self._close()
def _delete(self, id):
self._connect()
id = id.replace("'", "<&amp>").decode('utf-8', 'ignore')
self.cur.execute("delete from watched where id=('" + id + "')")
self.db.commit()
self._close()
def count(self):
return len(self._get_all())
def _connect(self):
self.db = sqlite.connect(self.dbfilename)
self.cur = self.db.cursor()
def _close(self):
self.cur.close()
self.db.close()
def countSeasons(jdata):
seasons, epdict = [], {}
for id in jdata['episodes']:
seasonNumber = jdata['episodes'][id]['seasonNumber']
if seasonNumber not in seasons:
seasons.append(seasonNumber)
if jdata['episodes'][id]['episodeNumber']:
if str(jdata['episodes'][id]['seasonNumber']) not in epdict:
epdict[str(jdata['episodes'][id]['seasonNumber'])] = str(jdata['episodes'][id]['id'])
else:
epdict[str(jdata['episodes'][id]['seasonNumber'])] = epdict[str(
jdata['episodes'][id]['seasonNumber'])] + ',' + str(jdata['episodes'][id]['id'])
seasons.sort()
return seasons, epdict
def fetchData(url, referer=None):
request = urllib2.Request(url)
if referer != None:
request.add_header('Referer', referer)
request.add_header('User-Agent', USERAGENT)
if __settings__.getSetting("auth"):
authString = '; ' + __settings__.getSetting("auth")
else:
authString = ''
request.add_header('Cookie', authString)
try:
connection = urllib2.urlopen(request)
result = connection.read()
connection.close()
return (result)
except (urllib2.HTTPError, urllib2.URLError) as e:
print " fetchData(" + url + ") exception: " + str(e)
return
def file_decode(filename):
if not __settings__.getSetting('delete_russian')=='true':
if sys.getfilesystemencoding()=='mbcs':
try:
filename=filename.decode('utf-8')#,'ignore')
except:
pass
return filename
def file_encode(filename):
if not __settings__.getSetting('delete_russian')=='true':
if sys.getfilesystemencoding()=='mbcs' and isAsciiString(filename):
filename=filename.decode('cp1251').encode('utf-8')
return filename
def isAsciiString(mediaName):
for index, char in enumerate(mediaName):
if ord(char) >= 128:
return False
return True
def getParameters(parameterString):
commands = {}
splitCommands = parameterString[parameterString.find('?') + 1:].split('&')
for command in splitCommands:
if (len(command) > 0):
splitCommand = command.split('=')
if (len(splitCommand) > 1):
name = splitCommand[0]
value = splitCommand[1]
commands[name] = value
return commands
def isSubtitle(filename, filename2):
filename_if = filename[:len(filename) - len(filename.split('.')[-1]) - 1]
filename_if = filename_if.split('/')[-1].split('\\')[-1]
filename_if2 = filename2.split('/')[-1].split('\\')[-1][:len(filename_if)]
#Debug('Compare ' + filename_if.lower() + ' and ' + filename_if2.lower() + ' and ' + filename2.lower().split('.')[-1])
ext = ['ass', 'mpsub', 'rum', 'sbt', 'sbv', 'srt', 'ssa', 'sub', 'sup', 'w32']
if filename2.lower().split('.')[-1] in ext and \
filename_if.lower() == filename_if2.lower():
return True
return False
def delete_russian(ok=False, action='delete'):
i=0
if not ok:
ok = xbmcgui.Dialog().yesno('< %s >' % Localization.localize('International Check - First Run'),
'Delete Russian stuff?',
Localization.localize('Delete Russian stuff?'))
if ok:
fileList={
'contenters':['CXZ.py','FastTorrent.py','KinoPoisk.py','RiperAM.py'],
'searchers':['NNMClubRu.py','OpenSharing.py','RiperAM.py','RuTorOrg.py','RuTrackerOrg.py','TFileME.py']
}
for path in fileList.keys():
for filename in fileList[path]:
if action=='delete':
filepath=os.path.join(ROOT,'resources', path,filename)
if xbmcvfs.exists(filepath):
newfilepath=os.path.join(ROOT,'resources', path,'unused',filename)
xbmcvfs.copy(filepath, newfilepath)
xbmcvfs.delete(filepath)
elif action=='return':
filepath=os.path.join(ROOT,'resources', path,'unused',filename)
if xbmcvfs.exists(filepath):
newfilepath=os.path.join(ROOT,'resources',path,filename)
xbmcvfs.copy(filepath, newfilepath)
xbmcvfs.delete(filepath)
i=i+1
if action=='return':
return i
return True
else:
return False
class DownloadDB:
def __init__(self, version=1.41):
self.name = 'download.db3'
self.version = version
def get_all(self):
self._connect()
self.cur.execute('select addtime, title, path, type, jsoninfo, status, torrent, ind, lastupdate, storage from downloads order by addtime DESC')
x = self.cur.fetchall()
self._close()
return x if x else None
def get(self, title):
self._connect()
self.cur.execute('select addtime, title, path, type, jsoninfo, status, torrent, ind, lastupdate, storage from downloads where title="' + decode(title) + '"')
x = self.cur.fetchone()
self._close()
return x if x else None
def get_byaddtime(self, addtime):
self._connect()
self.cur.execute('select addtime, title, path, type, jsoninfo, status, torrent, ind, lastupdate, storage from downloads where addtime="' + str(addtime) + '"')
x = self.cur.fetchone()
self._close()
return x if x else None
def get_status(self, title):
self._connect()
self.cur.execute('select status from downloads where title="' + decode(title) + '"')
x = self.cur.fetchone()
self._close()
return x[0] if x else None
def add(self, title, path, type, info, status, torrent, ind, storage):
if not self.get(title):
self._connect()
self.cur.execute('insert into downloads(addtime, title, path, type, jsoninfo, status, torrent, ind, lastupdate, storage)'
' values(?,?,?,?,?,?,?,?,?,?)', (int(time.time()), decode(title), decode(path), type, json.dumps(info), status, decode(torrent), ind, int(time.time()), decode(storage)))
self.db.commit()
self._close()
return True
else:
return False
def update(self, title, info={}):
try:
title = title.decode('utf-8')
except:
pass
self._connect()
self.cur.execute('UPDATE downloads SET jsoninfo = "' + urllib.quote_plus(json.dumps(info)) + '", lastupdate='+str(int(time.time()))+' where title="' + title+'"')
self.db.commit()
self._close()
def update_status(self, addtime, status):
self._connect()
self.cur.execute('UPDATE downloads SET status = "' + status + '" where addtime="' + str(addtime)+'"')
self.db.commit()
self._close()
def delete(self, addtime):
self._connect()
self.cur.execute('delete from downloads where addtime="' + str(addtime) + '"')
self.db.commit()
self._close()
def clear(self):
self._connect()
self.cur.execute('delete from downloads')
self.db.commit()
self._close()
def _connect(self):
dirname = xbmc.translatePath('special://temp')
for subdir in ('xbmcup', 'plugin.video.torrenter'):
dirname = os.path.join(dirname, subdir)
if not xbmcvfs.exists(dirname):
xbmcvfs.mkdir(dirname)
self.filename = os.path.join(dirname, self.name)
first = False
if not xbmcvfs.exists(self.filename):
first = True
self.db = sqlite.connect(self.filename, check_same_thread=False)
if not first:
self.cur = self.db.cursor()
try:
self.cur.execute('select version from db_ver')
row = self.cur.fetchone()
if not row or float(row[0]) != self.version:
self.cur.execute('drop table downloads')
self.cur.execute('drop table if exists db_ver')
first = True
self.db.commit()
self.cur.close()
except:
self.cur.execute('drop table downloads')
first = True
self.db.commit()
self.cur.close()
if first:
cur = self.db.cursor()
cur.execute('pragma auto_vacuum=1')
cur.execute('create table db_ver(version real)')
cur.execute(
'create table downloads(addtime integer PRIMARY KEY, title varchar(32), path varchar(32), type varchar(32), jsoninfo varchar(32), status varchar(32), torrent varchar(32), ind integer, lastupdate integer, storage varchar(32))')
cur.execute('insert into db_ver(version) values(?)', (self.version, ))
self.db.commit()
cur.close()
self.cur = self.db.cursor()
def _close(self):
self.cur.close()
self.db.close()
def decode(string, ret=None):
try:
string = string.decode('utf-8')
return string
except:
if ret:
return ret
else:
return string
def unquote(string, ret=None):
try:
return urllib.unquote_plus(string)
except:
if ret:
return ret
else:
return string