try:
import httplib
except:
import http.client as httplib
try:
import urllib2
except:
import urllib.request as urllib2
import json
import os
import sys
import zipfile
import traceback
import io
import aqt
from aqt import mw
from aqt.qt import *
from aqt.utils import showInfo
from anki.hooks import addHook
from anki.utils import isMac, isWin
from ..context import APP_ICON
from .AnkiHub.updates import Ui_DialogUpdates
from .AnkiHub.markdown2 import markdown
__all__ = ['update']
# taken from Anki's aqt/profiles.py
def defaultBase():
path = mw.pm.addonFolder()
return os.path.dirname(os.path.abspath(path))
headers = {"User-Agent": "AnkiHub"}
dataPath = os.path.join(defaultBase(),'.fastwq_2.1.x_ankihub.json')
class DialogUpdates(QDialog, Ui_DialogUpdates):
def __init__(self, parent, data, oldData, callback):
parent = parent if parent else mw
QDialog.__init__(self, parent)
self.setModal(True)
self.setWindowFlags(
self.windowFlags() &
~Qt.WindowContextHelpButtonHint
)
self.setWindowIcon(APP_ICON)
self.setupUi(self)
totalSize = sum(map(lambda x:x['size'],data['assets']))
def answer():
self.update.setEnabled(False)
callback(self.appendHtml, self.finish)
self.html = u''
self.appendHtml(markdown(data['body']))
#if not automaticAnswer:
self.update.clicked.connect(lambda:answer())
fromVersion = ''
if 'tag_name' in oldData:
fromVersion = u'from {0} '.format(oldData['tag_name'])
self.labelUpdates.setText(
str(self.labelUpdates.text()).format(
data['name'],
fromVersion,
data['tag_name']))
def appendHtml(self,html='',temp=''):
self.html += html
self.textBrowser.setHtml(u'
{0}{1}{2}'.format(self.html, temp, u''))
self.textBrowser.scrollToAnchor('text_bottom')
def finish(self):
self.hide()
self.destroy()
showInfo('Updated. Please restart Anki.')
pass
def installZipFile(data, fname):
base = os.path.join(mw.pm.addonFolder(), 'fastwq')
if fname.endswith(".py"):
path = os.path.join(base, fname)
with open(path, "wb") as file:
file.write(data)
file.close()
return True
# .zip file
try:
z = zipfile.ZipFile(io.BytesIO(data))
except zipfile.BadZipfile:
return False
for n in z.namelist():
if n.endswith("/"):
# folder; ignore
continue
# write
z.extract(n, base)
return True
def asset(a):
return {
'url': a['browser_download_url'],
'size': a['size']
}
def updateSingle(repositories, path, data):
def callback(appendHtml, onReady):
for asset in data['assets']:
code = asset['url']
p, fname = os.path.split(code)
appendHtml(temp='
Downloading {1}: {0}%
'.format(0,fname))
try:
urlthread = UrlThread(code)
urlthread.start()
urlthread.join()
response = urlthread.response#urllib2.urlopen(code)
meta = response.info()
file_size = int(meta.get("Content-Length"))
except:
appendHtml('Downloading file error!
')
return
d = b''
dl = 0
i = 0
lastPercent = None
while True:
dkb = response.read(1024)
if not dkb:
break
dl += len(dkb)
d += dkb
if dl*100/file_size>i:
lastPercent = int(dl*100/file_size)
i = lastPercent+1
appendHtml(temp='
Downloading {1}: {0}%
'.format(lastPercent,fname))
QApplication.instance().processEvents()
appendHtml('
Downloading {1}: 100%
'.format(int(dl*100/file_size),fname))
appendHtml('Installing ...
')
if not installZipFile(d, fname):
appendHtml('Corrupt file
')
else:
repositories[path] = data
repositories[path]['update'] = 'ask'
with open(dataPath,'w') as f:
json.dump(repositories,f,indent=2)
f.close()
appendHtml('Done.
')
onReady() # close the AnkiHub update window
return callback
def update(add=[], VERSION='v0.0.0', background=False):
# progress win
if not background:
progresswin = QProgressDialog('Update Checking...', '', 0, 0, mw)
progresswin.setWindowModality(Qt.ApplicationModal)
progresswin.setCancelButton(None)
progresswin.setWindowFlags(
progresswin.windowFlags() &
~Qt.WindowContextHelpButtonHint
)
progresswin.setWindowTitle('FastWQ - Updater')
progresswin.setWindowIcon(APP_ICON)
progresswin.resize(280, 60)
progresswin.show()
else:
progresswin = None
#
conn = httplib.HTTPSConnection("api.github.com")
try:
with open(dataPath,'r') as f:
repositories = json.load(f)
f.close()
except:
repositories = {}
for a in add:
if a not in repositories:
repositories[a] = {
'id': 0,
'update': 'ask'
}
for path,repository in repositories.items():
username,repositoryName = path.split('/')
try:
urlthread = UrlThread("https://api.github.com/repos/{0}/releases/latest".format(path))
urlthread.start()
urlthread.join()
release = json.loads(urlthread.response.read())
except Exception as e:
release = {}
if 'id' in release:
if release['id'] != repository['id']:
data = {
'id': release['id'],
'name': repositoryName,
'tag_name': release['tag_name'],
'body': '### {0}\n'.format(release['name']) + release['body'],
'assets': [asset(release['assets'][1])],
'update': 'ask'
}
if 'tag_name' in repository:
oldVersion = map(int,repository['tag_name'][1:].split('.'))
oldVersion = [x for x in oldVersion]
while len(oldVersion)<3:
oldVersion.append(0)
else:
oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0]
oldVersion = [x for x in oldVersion]
newVersion = map(int,data['tag_name'][1:].split('.'))
newVersion = [x for x in newVersion]
isMinor = len(newVersion)>2 and newVersion[2]>0
while len(newVersion)<3:
newVersion.append(0)
i = oldVersion[2]+1
if oldVersion[0]