Skip to content

Commit

Permalink
2.023: auto update
Browse files Browse the repository at this point in the history
  • Loading branch information
fffonion committed Jul 22, 2020
1 parent 8f57160 commit f61362f
Show file tree
Hide file tree
Showing 17 changed files with 289 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2.023
- 自动更新
- 修复保存任务时logger无法序列化的bug (感谢 @9chu)

## 2.022
- 增加下载速度显示
- 增加低速自动重试 `low_speed_threshold`, 默认为`10KB/s`以下重试
Expand Down
9 changes: 8 additions & 1 deletion README.chs.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ xeH
- **download_timeout** 设置下载图片的超时,默认为`10`
- **low_speed_threshold** 设置最低下载速度,低于此值将换源重新下载,单位为KB/s,默认为`10`
- **ignored_errors** 设置忽略的错误码,默认为空,错误码可以从`const.py`中获得
- **auto_update** 自动检查更新,`check` 仅检查更新,`download` 下载更新,`off` 关闭检查;默认为`download`
- **update_beta_channel** 设置是否更新到测试版,默认为否
- **log_path** 日志路径,默认为`eh.log`
- **log_verbose** 日志等级,可选1-3,值越大输出越详细,默认为`2`
- **save_tasks** 是否保存任务到`h.json`,可用于断点续传,默认为否
Expand All @@ -67,7 +69,8 @@ xeH
[--rpc-interface ADDR] [--rpc-port PORT] [--rpc-secret ...]
[--rpc-open-browser BOOL] [--delete-task-files BOOL] [-a BOOL]
[--download-range a-b,c-d,e] [-t N] [--timeout N]
[--low-speed-threshold N] [-f] [-l /path/to/eh.log] [-v] [-h]
[--low-speed-threshold N] [-f] [--auto-update {check,download,off}]
[--update-beta-channel BOOL] [-l /path/to/eh.log] [-v] [-h]
[--version]
[url [url ...]]
Expand Down Expand Up @@ -112,6 +115,10 @@ xeH
-t N, --thread N 下载线程数 (默认: 5)
--timeout N 设置下载图片的超时 (默认: 10秒)
-f, --force 忽略配额判断, 继续下载 (默认: False)
--auto-update {check,download,off}
检查并自动下载更新
--update-beta-channel BOOL
是否更新到测试分支
-l /path/to/eh.log, --logpath /path/to/eh.log
保存日志的路径 (默认: eh.log)
-v, --verbose 设置日志装逼等级 (默认: 2)
Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Configuration keys:
- **download_timeout** Timeout of download images. Default to `10`s.
- **low_speed_threshold** Retry download if speed is lower than specified value. Default to `10` KB/s.
- **ignored_errors** Set the error codes to ignore and continue downloading. Default to *empty*. Error codes can be obtained from [const.py](xeHentai/const.py).
- **auto_update** turn on auto update of program `check` for check only and `download` for download; `off` to turn off. Default to `download`.
- **update_beta_channel** set to true to update to dev branch
- **log_path** Set log file path. Default to `eh.log`.
- **log_verbose** Set log level with integer from 1 to 3. Bigger value means more verbose output. Default to `2`.
- **save_tasks** Set to save uncompleted tasks in `h.json`. Default to `False`.
Expand All @@ -65,7 +67,8 @@ Usage: xeh [-u USERNAME] [-k KEY] [-c COOKIE] [-i] [--daemon] [-d DIR] [-o]
[--rpc-interface ADDR] [--rpc-port PORT] [--rpc-secret ...]
[--rpc-open-browser BOOL] [--delete-task-files BOOL] [-a BOOL]
[--download-range a-b,c-d,e] [-t N] [--timeout N]
[--low-speed-threshold N] [-f] [-l /path/to/eh.log] [-v] [-h]
[--low-speed-threshold N] [-f] [--auto-update {check,download,off}]
[--update-beta-channel BOOL] [-l /path/to/eh.log] [-v] [-h]
[--version]
[url [url ...]]
Expand Down Expand Up @@ -126,9 +129,14 @@ optional arguments:
(default: 10 KB/s)
-f, --force download regardless of quota exceeded warning
(default: False)
--auto-update {check,download,off}
check or download update automatically
(default: download)
--update-beta-channel BOOL
check update upon beta channel
(default: True)
-l /path/to/eh.log, --logpath /path/to/eh.log
define log path (current:
/Users/fffonion/Dev/Python/xeHentai/eh.log)
define log path (default: eh.log)
-v, --verbose show more detailed log (default: 3)
-h, --help show this help message and exit
--version show program's version number and exit
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'xeHentai',
'xeHentai.util',
'xeHentai.i18n',
'xeHentai.updater',
]
requires = ['requests']

Expand Down
48 changes: 46 additions & 2 deletions xeH
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
#!/usr/bin/env python

from xeHentai import cli
import os
import sys
import json
import zipfile
from threading import Thread
import xeHentai.const as const

cli.start()
SRC_UPDATE_FILE = const.SRC_UPDATE_FILE
if const.PY3K:
from importlib import reload

def load_update():
if os.path.exists(SRC_UPDATE_FILE):
try:
need_remove = False
update_id = ""
with zipfile.ZipFile(SRC_UPDATE_FILE, 'r') as z:
try:
r = json.loads(z.read("info.json"))
except:
need_remove = True
else:
if 'v' not in r and r['v'] != SRC_UPDATE_VERSION:
# ignoring legacy file
need_remove = True
else:
update_id = r["update_id"]
if need_remove:
os.remove(SRC_UPDATE_FILE)
return
v = const.__version__
sys.path.insert(0, SRC_UPDATE_FILE)
import xeHentai
reload(xeHentai)
xeHentai.const.VERSION_UPDATE = update_id
xeHentai.const.VERSION_UPDATE_LOADER = v
except:
if sys.path[0] == SRC_UPDATE_FILE:
sys.path.pop(0)
os.remove(SRC_UPDATE_FILE)


if __name__ == "__main__":
load_update()

from xeHentai import cli, i18n
cli.start()
44 changes: 42 additions & 2 deletions xeH.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
#!/usr/bin/env python

from xeHentai import cli
import sys
import json
import zipfile
from threading import Thread
from xeHentai.const import *

cli.start()
def load_update():
if os.path.exists(SRC_UPDATE_FILE):
try:
need_remove = False
update_id = ""
with zipfile.ZipFile(SRC_UPDATE_FILE, 'r') as z:
try:
r = json.loads(z.read("info.json"))
except:
need_remove = True
else:
if 'v' not in r and r['v'] != SRC_UPDATE_VERSION:
# ignoring legacy file
need_remove = True
else:
update_id = r["update_id"]
if need_remove:
os.remove(SRC_UPDATE_FILE)
return
sys.path.insert(0, SRC_UPDATE_FILE)
import xeHentai
reload(xeHentai)
xeHentai.const.VERSION_UPDATE = update_id
except ImportError:
if sys.path[0] == SRC_UPDATE_FILE:
sys.path.pop(0)
os.remove(SRC_UPDATE_FILE)
except:
pass
return { "v": SRC_UPDATE_VERSION }


if __name__ == "__main__":
load_update()

from xeHentai import cli, i18n
cli.start()
16 changes: 16 additions & 0 deletions xeHentai/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
def start():
opt = parse_opt()
xeH = xeHentai()
if opt.auto_update != "off":
check_update(xeH.logger, {
"auto_update": opt.auto_update,
"update_beta_channel": opt.update_beta_channel,
})
if opt.daemon:
if opt.interactive:
xeH.logger.warning(i18n.XEH_OPT_IGNORING_I)
Expand All @@ -44,6 +49,13 @@ def start():
else:
main(xeH, opt)

def check_update(l, cfg):
from .updater.updater import check_update
t = Thread(name="updater", target=check_update, args=(l, cfg))
t.setDaemon(True)
t.start()
return t

def main(xeH, opt):
xeH.update_config(**vars(opt))
log = xeH.logger
Expand Down Expand Up @@ -181,6 +193,10 @@ def parse_opt():
current = ERR_QUOTA_EXCEEDED in _def['ignored_errors'],
add_value = ERR_QUOTA_EXCEEDED, dest='ignored_errors',
help = i18n.XEH_OPT_f)
parser.add_argument('--auto-update', default = _def['auto_update'], choices = ("check", "download", "off"),
dest = 'auto_update', help = i18n.XEH_OPT_auto_update)
parser.add_argument('--update-beta-channel', type = bool, metavar = "BOOL", default = _def['update_beta_channel'],
dest = 'update_beta_channel', help = i18n.XEH_OPT_update_beta_channel)

parser.add_argument('-l', '--logpath', metavar = '/path/to/eh.log',
default = os.path.abspath(_def['log_path']), help = i18n.XEH_OPT_l)
Expand Down
7 changes: 6 additions & 1 deletion xeHentai/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,9 @@
delete_task_files = False

# retry a connection if per thread speed is lower than this value, unit is KB per second
low_speed_threshold = 10
low_speed_threshold = 10

# turn on auto update of program "check" for check only and "download" for download
auto_update = "download"
# set to true to update to dev branch
update_beta_channel = False
11 changes: 9 additions & 2 deletions xeHentai/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
CODEPAGE = locale.getdefaultlocale()[1] or 'ascii'
ANDROID = 'ANDROID_ARGUMENT' in os.environ

__version__ = 2.022
DEVELOPMENT = False
__version__ = 2.023
VERSION_UPDATE = ""
DEVELOPMENT = True

SCRIPT_NAME = "xeHentai"

Expand All @@ -29,6 +30,9 @@
# The application is not frozen
# Change this bit to match where you store your data files:
FILEPATH = sys.path[0]
# if update is being injected
if FILEPATH.endswith(".zip"):
FILEPATH = sys.path[1]

DUMMY_FILENAME = "-dummy-"
RENAME_TMPDIR = "-xeh-conflict-"
Expand All @@ -37,6 +41,9 @@
STATIC_CACHE_TTL = 3600
STATIC_CACHE_VERSION = 1

SRC_UPDATE_FILE = os.path.join(FILEPATH, "src.zip")
SRC_UPDATE_VERSION = 1

RE_INDEX = re.compile('.+/(\d+)/([^\/]+)/*')
RE_GALLERY = re.compile('/([a-f0-9]{10})/[^\-]+\-(\d+)')
RE_IMGHASH = re.compile('/([a-f0-9]{40})-(\d+)-(\d+)-(\d+)-([a-z]{,4})')
Expand Down
2 changes: 2 additions & 0 deletions xeHentai/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
class xeHentai(object):
def __init__(self):
self.verstr = "%.3f%s" % (__version__, '-dev' if DEVELOPMENT else "")
if VERSION_UPDATE:
self.verstr = "%s-%s(%s)" % (self.verstr, VERSION_UPDATE[:7], VERSION_UPDATE_LOADER)
self.logger = logger.Logger()
self._exit = False
self.tasks = Queue() # for queueing, stores gid only
Expand Down
12 changes: 12 additions & 0 deletions xeHentai/i18n/en_us.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
XEH_OPT_h = "show this help message and exit"
XEH_OPT_version = "show program's version number and exit"
XEH_OPT_IGNORING_I = "ignoring -i option in daemon mode"
XEH_OPT_auto_update = "check or download update automatically"
XEH_OPT_update_beta_channel = "check update upon beta channel"

PS_LOGIN = "login to exhentai (y/n)? > "
PS_USERNAME = "Username > "
Expand Down Expand Up @@ -135,3 +137,13 @@
QUEUE = "queue"

PROXY_DISABLE_BANNED = "disable a banned proxy, expire in about %ss"

UPDATE_CHANNEL = "Update channel is: %s"
UPDATE_DEV_CHANNEL = "dev"
UPDATE_RELEASE_CHANNEL = "release"
UPDATE_FAILED = "Failure when updating program: %s"
UPDATE_COMPLETE = "Update is complete, it will take effect on next run"
UPDATE_NO_UPDATE = "Program is up-to-date"
UPDATE_AVAILABLE = "Update available: %s \"%s\" (%s)"
UPDATE_DOWNLOAD_MANUALLY = "You can download update from https://dl.yooooo.us/share/xeHentai/"

11 changes: 11 additions & 0 deletions xeHentai/i18n/zh_hans.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
XEH_OPT_h = "显示本帮助信息"
XEH_OPT_version = "显示版本信息"
XEH_OPT_IGNORING_I = "后台模式已忽略 -i 参数"
XEH_OPT_auto_update = "检查并自动下载更新"
XEH_OPT_update_beta_channel = "是否更新到测试分支"


PS_LOGIN = "当前没有登陆,要登陆吗 (y/n)? > "
Expand Down Expand Up @@ -133,3 +135,12 @@
QUEUE = "队列"

PROXY_DISABLE_BANNED = "禁用了一个被ban的代理,将在约%s秒后恢复"

UPDATE_CHANNEL = "更新渠道为: %s"
UPDATE_DEV_CHANNEL = "测试版"
UPDATE_RELEASE_CHANNEL = "正式版"
UPDATE_FAILED = "更新时遇到错误: %s"
UPDATE_COMPLETE = "更新完成,请重新启动程序应用更新"
UPDATE_NO_UPDATE = "没有可用更新"
UPDATE_AVAILABLE = "发现可用的更新: 发布于 %s \"%s\" (%s)"
UPDATE_DOWNLOAD_MANUALLY = "可以从 https://dl.yooooo.us/share/xeHentai/ 下载更新"
11 changes: 11 additions & 0 deletions xeHentai/i18n/zh_hant.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
XEH_OPT_h = "顯示本幫助信息"
XEH_OPT_version = "顯示版本信息"
XEH_OPT_IGNORING_I = "後台模式已忽略 -i 參數"
XEH_OPT_auto_update = "檢查並自動下載更新"
XEH_OPT_update_beta_channel = "是否更新到測試分支"


PS_LOGIN = "當前沒有登陸,要登陸嗎 (y/n)? > "
Expand Down Expand Up @@ -133,3 +135,12 @@
QUEUE = "隊列"

PROXY_DISABLE_BANNED = "禁用了一個被ban的代理,將在約%s秒後恢復"

UPDATE_CHANNEL = "更新渠道為: %s"
UPDATE_DEV_CHANNEL = "測試版"
UPDATE_RELEASE_CHANNEL = "正式版"
UPDATE_FAILED = "更新時遇到錯誤: %s"
UPDATE_COMPLETE = "更新完成,請重新啟動程序應用更新"
UPDATE_NO_UPDATE = "沒有可用更新"
UPDATE_AVAILABLE = "發現可用的更新: 發布於 %s \"%s\" (%s)"
UPDATE_DOWNLOAD_MANUALLY = "可以從 https://dl.yooooo.us/share/xeHentai/ 下載更新"
1 change: 0 additions & 1 deletion xeHentai/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
if PY3K:
from socketserver import ThreadingMixIn
from http.server import HTTPServer, BaseHTTPRequestHandler
from io import IOBase
from io import BytesIO as StringIO
from urllib.parse import urlparse
else:
Expand Down
18 changes: 18 additions & 0 deletions xeHentai/updater/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# coding:utf-8
# Contributor:
# fffonion <[email protected]>

class Updater(object):
def get_latest_release(self, dev=False):
raise NotImplementedError("get_latest_release not implemented")

def get_src_path_in_archive(self, info):
raise NotImplementedError("get_src_path_in_archive not implemented")

class UpdateInfo(object):
def __init__(self, update_id, download_link, ts, message):
self.update_id = update_id
self.download_link = download_link
self.message = message
self.ts = ts

29 changes: 29 additions & 0 deletions xeHentai/updater/github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# coding:utf-8
# Contributor:
# fffonion <[email protected]>

import requests
import time

from . import Updater, UpdateInfo

class GithubUpdater(Updater):
def __init__(self, session):
self.session = session

def get_latest_release(self, dev=False):
param = dev and "dev" or "master"
r = self.session.get("https://api.github.com/repos/fffonion/xeHentai/commits?sha=%s" % param)
commit = r.json()[0]
sha = commit["sha"]
url = "https://github.com/fffonion/xeHentai/archive/%s.zip" % sha

return UpdateInfo(
sha,
url,
commit["commit"]["author"]["date"],
commit["commit"]["message"].replace("\r", " ").replace("\n", " "),
)

def get_src_path_in_archive(self, info):
return "xeHentai-%s/xeHentai" % info.update_id
Loading

0 comments on commit f61362f

Please sign in to comment.