Skip to content

Commit 5c10f52

Browse files
authored
Merge pull request #215 from RockChinQ/semantic-versions
[Feature] 使用语义化版本进行更新
2 parents 13e55e0 + f8abe90 commit 5c10f52

File tree

4 files changed

+159
-56
lines changed

4 files changed

+159
-56
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ plugins/
99
/revcfg.py
1010
prompts/
1111
logs/
12-
sensitive.json
12+
sensitive.json
13+
temp/
14+
current_tag

main.py

+24-20
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,18 @@ def reset_logging():
107107
def main(first_time_init=False):
108108
global known_exception_caught
109109

110-
# 检查并创建plugins、prompts目录
111-
check_path = ["plugins", "prompts"]
112-
for path in check_path:
113-
if not os.path.exists(path):
114-
os.mkdir(path)
110+
import config
111+
# 更新openai库到最新版本
112+
if not hasattr(config, 'upgrade_dependencies') or config.upgrade_dependencies:
113+
print("正在更新依赖库,请等待...")
114+
if not hasattr(config, 'upgrade_dependencies'):
115+
print("这个操作不是必须的,如果不想更新,请在config.py中添加upgrade_dependencies=False")
116+
else:
117+
print("这个操作不是必须的,如果不想更新,请在config.py中将upgrade_dependencies设置为False")
118+
try:
119+
ensure_dependencies()
120+
except Exception as e:
121+
print("更新openai库失败:{}, 请忽略或自行更新".format(e))
115122

116123
known_exception_caught = False
117124
try:
@@ -263,7 +270,7 @@ def run_bot_wrapper():
263270
import pkg.utils.updater
264271
try:
265272
if pkg.utils.updater.is_new_version_available():
266-
pkg.utils.context.get_qqbot_manager().notify_admin("新版本可用,请发送 !update 进行自动更新")
273+
pkg.utils.context.get_qqbot_manager().notify_admin("新版本可用,请发送 !update 进行自动更新\n更新日志:\n{}".format("\n".join(pkg.utils.updater.get_rls_notes())))
267274
else:
268275
logging.info("当前已是最新版本")
269276

@@ -314,10 +321,20 @@ def stop():
314321
if not os.path.exists('banlist.py'):
315322
shutil.copy('banlist-template.py', 'banlist.py')
316323

317-
# 检查是否有sensitive.json,
324+
# 检查是否有sensitive.json
318325
if not os.path.exists("sensitive.json"):
319326
shutil.copy("sensitive-template.json", "sensitive.json")
320327

328+
# 检查temp目录
329+
if not os.path.exists("temp/"):
330+
os.mkdir("temp/")
331+
332+
# 检查并创建plugins、prompts目录
333+
check_path = ["plugins", "prompts"]
334+
for path in check_path:
335+
if not os.path.exists(path):
336+
os.mkdir(path)
337+
321338
if len(sys.argv) > 1 and sys.argv[1] == 'init_db':
322339
init_db()
323340
sys.exit(0)
@@ -343,17 +360,4 @@ def stop():
343360
# pkg.utils.configmgr.set_config_and_reload("quote_origin", False)
344361
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
345362

346-
import config
347-
# 更新openai库到最新版本
348-
if not hasattr(config, 'upgrade_dependencies') or config.upgrade_dependencies:
349-
print("正在更新依赖库,请等待...")
350-
if not hasattr(config, 'upgrade_dependencies'):
351-
print("这个操作不是必须的,如果不想更新,请在config.py中添加upgrade_dependencies=False")
352-
else:
353-
print("这个操作不是必须的,如果不想更新,请在config.py中将upgrade_dependencies设置为False")
354-
try:
355-
ensure_dependencies()
356-
except Exception as e:
357-
print("更新openai库失败:{}, 请忽略或自行更新".format(e))
358-
359363
main(True)

pkg/utils/updater.py

+132-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import datetime
2+
import logging
3+
import os.path
4+
5+
import requests
6+
import json
27

38
import pkg.utils.context
49

@@ -28,34 +33,100 @@ def pull_latest(repo_path: str) -> bool:
2833
return True
2934

3035

36+
def get_release_list() -> list:
37+
"""获取发行列表"""
38+
rls_list_resp = requests.get(
39+
url="https://api.github.com/repos/RockChinQ/QChatGPT/releases"
40+
)
41+
42+
rls_list = rls_list_resp.json()
43+
44+
return rls_list
45+
46+
47+
def get_current_tag() -> str:
48+
"""获取当前tag"""
49+
current_tag = "v0.1.0"
50+
if os.path.exists("current_tag"):
51+
with open("current_tag", "r") as f:
52+
current_tag = f.read()
53+
54+
return current_tag
55+
56+
3157
def update_all() -> bool:
32-
"""使用dulwich更新源码"""
33-
check_dulwich_closure()
34-
import dulwich
35-
try:
36-
before_commit_id = get_current_commit_id()
37-
from dulwich import porcelain
38-
repo = porcelain.open_repo('.')
39-
porcelain.pull(repo)
40-
41-
change_log = ""
42-
43-
for entry in repo.get_walker():
44-
if str(entry.commit.id)[2:-1] == before_commit_id:
45-
break
46-
tz = datetime.timezone(datetime.timedelta(hours=entry.commit.commit_timezone // 3600))
47-
dt = datetime.datetime.fromtimestamp(entry.commit.commit_time, tz)
48-
change_log += dt.strftime('%Y-%m-%d %H:%M:%S') + " [" + str(entry.commit.message, encoding="utf-8").strip()+"]\n"
49-
50-
if change_log != "":
51-
pkg.utils.context.get_qqbot_manager().notify_admin("代码拉取完成,更新内容如下:\n"+change_log)
52-
return True
53-
else:
54-
return False
55-
except ModuleNotFoundError:
56-
raise Exception("dulwich模块未安装,请查看 https://github.com/RockChinQ/QChatGPT/issues/77")
57-
except dulwich.porcelain.DivergedBranches:
58-
raise Exception("分支不一致,自动更新仅支持master分支,请手动更新(https://github.com/RockChinQ/QChatGPT/issues/76)")
58+
"""检查更新并下载源码"""
59+
current_tag = get_current_tag()
60+
61+
rls_list = get_release_list()
62+
63+
latest_rls = {}
64+
rls_notes = []
65+
for rls in rls_list:
66+
rls_notes.append(rls['name']) # 使用发行名称作为note
67+
if rls['tag_name'] == current_tag:
68+
break
69+
70+
if latest_rls == {}:
71+
latest_rls = rls
72+
logging.info("更新日志: {}".format(rls_notes))
73+
if latest_rls == {}: # 没有新版本
74+
return False
75+
76+
# 下载最新版本的zip到temp目录
77+
logging.info("开始下载最新版本: {}".format(latest_rls['zipball_url']))
78+
zip_url = latest_rls['zipball_url']
79+
zip_resp = requests.get(url=zip_url)
80+
zip_data = zip_resp.content
81+
82+
# 检查temp/updater目录
83+
if not os.path.exists("temp"):
84+
os.mkdir("temp")
85+
if not os.path.exists("temp/updater"):
86+
os.mkdir("temp/updater")
87+
with open("temp/updater/{}.zip".format(latest_rls['tag_name']), "wb") as f:
88+
f.write(zip_data)
89+
90+
logging.info("下载最新版本完成: {}".format("temp/updater/{}.zip".format(latest_rls['tag_name'])))
91+
92+
# 解压zip到temp/updater/<tag_name>/
93+
import zipfile
94+
# 检查目标文件夹
95+
if os.path.exists("temp/updater/{}".format(latest_rls['tag_name'])):
96+
import shutil
97+
shutil.rmtree("temp/updater/{}".format(latest_rls['tag_name']))
98+
os.mkdir("temp/updater/{}".format(latest_rls['tag_name']))
99+
with zipfile.ZipFile("temp/updater/{}.zip".format(latest_rls['tag_name']), 'r') as zip_ref:
100+
zip_ref.extractall("temp/updater/{}".format(latest_rls['tag_name']))
101+
102+
# 覆盖源码
103+
source_root = ""
104+
# 找到temp/updater/<tag_name>/中的第一个子目录路径
105+
for root, dirs, files in os.walk("temp/updater/{}".format(latest_rls['tag_name'])):
106+
if root != "temp/updater/{}".format(latest_rls['tag_name']):
107+
source_root = root
108+
break
109+
110+
# 覆盖源码
111+
import shutil
112+
for root, dirs, files in os.walk(source_root):
113+
# 覆盖所有子文件子目录
114+
for file in files:
115+
src = os.path.join(root, file)
116+
dst = src.replace(source_root, ".")
117+
if os.path.exists(dst):
118+
os.remove(dst)
119+
shutil.copy(src, dst)
120+
121+
# 把current_tag写入文件
122+
current_tag = latest_rls['tag_name']
123+
with open("current_tag", "w") as f:
124+
f.write(current_tag)
125+
126+
# 通知管理员
127+
import pkg.utils.context
128+
pkg.utils.context.get_qqbot_manager().notify_admin("已更新到最新版本: {}\n更新日志:\n{}\n新功能通常可以在config-template.py中看到,完整的更新日志请前往 https://github.com/RockChinQ/QChatGPT/releases 查看".format(current_tag, "\n".join(rls_notes)))
129+
return True
59130

60131

61132
def is_repo(path: str) -> bool:
@@ -132,15 +203,42 @@ def get_current_commit_id() -> str:
132203

133204
def is_new_version_available() -> bool:
134205
"""检查是否有新版本"""
135-
check_dulwich_closure()
206+
# 从github获取release列表
207+
rls_list = get_release_list()
208+
if rls_list is None:
209+
return False
136210

137-
from dulwich import porcelain
211+
# 获取当前版本
212+
current_tag = get_current_tag()
138213

139-
repo = porcelain.open_repo('.')
140-
fetch_res = porcelain.ls_remote(porcelain.get_remote_repo(repo, "origin")[1])
214+
# 检查是否有新版本
215+
for rls in rls_list:
216+
if rls['tag_name'] == current_tag:
217+
return False
218+
else:
219+
return True
220+
221+
222+
def get_rls_notes() -> list:
223+
"""获取更新日志"""
224+
# 从github获取release列表
225+
rls_list = get_release_list()
226+
if rls_list is None:
227+
return None
228+
229+
# 获取当前版本
230+
current_tag = get_current_tag()
231+
232+
# 检查是否有新版本
233+
rls_notes = []
234+
for rls in rls_list:
235+
if rls['tag_name'] == current_tag:
236+
break
237+
238+
rls_notes.append(rls['name'])
141239

142-
current_commit_id = get_current_commit_id()
240+
return rls_notes
143241

144-
latest_commit_id = str(fetch_res[b'HEAD'])[2:-1]
145242

146-
return current_commit_id != latest_commit_id
243+
if __name__ == "__main__":
244+
update_all()

requirements.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
requests~=2.28.1
22
openai~=0.27.0
3-
pip~=22.3.1
43
dulwich~=0.21.3
54
colorlog~=6.6.0
65
yiri-mirai~=0.2.6.1

0 commit comments

Comments
 (0)