-
Notifications
You must be signed in to change notification settings - Fork 203
/
updater.py
80 lines (71 loc) · 2.82 KB
/
updater.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import os
import time
import hashlib
import asyncio
from typing import List,Tuple
import httpx
from loguru import logger
from readme import Rule
# 上游规则更新
class Updater(object):
def __init__(self, ruleList:List[Rule]):
self.ruleList = ruleList
self.isNeedUpdate = False
def update(self, path:str) -> Tuple[bool,List[Rule]]:
# 启动异步循环
loop = asyncio.get_event_loop()
# 添加异步任务
taskList = []
for rule in self.ruleList:
logger.info("updating %s..."%(rule.name))
task = asyncio.ensure_future(self.__Download(rule, path))
taskList.append(task)
# 等待异步任务结束
loop.run_until_complete(asyncio.wait(taskList))
# 获取异步任务结果
for task in taskList:
new:Rule = task.result()
for rule in self.ruleList:
if new.name == rule.name:
rule.latest = new.latest
rule.update = new.update
if rule.update:
self.isNeedUpdate = rule.update
break
return self.isNeedUpdate, self.ruleList
def __CalcFileSha256(self, filename):
with open(filename, "rb") as f:
sha256obj = hashlib.sha256()
sha256obj.update(f.read())
hash_value = sha256obj.hexdigest()
return hash_value
async def __Download(self, rule:Rule, path:str) -> Rule:
fileName = path + "/" + rule.filename
fileName_download = fileName + '.download'
try:
if os.path.exists(fileName_download):
os.remove(fileName_download)
async with httpx.AsyncClient() as client:
response = await client.get(rule.url)
response.raise_for_status()
contentType = response.headers.get("Content-Type")
if contentType.find("text/plain") < 0:
raise Exception("Content-Type[%s] error"%(contentType))
with open(fileName_download,'wb') as f:
f.write(response.content)
if os.path.exists(fileName):
sha256Old = self.__CalcFileSha256(fileName)
sha256New = self.__CalcFileSha256(fileName_download)
if sha256New != sha256Old:
rule.update = True
os.remove(fileName)
else:
rule.update = True
os.rename(fileName_download, fileName)
except Exception as e:
logger.error(f'%s download failed: %s' % (rule.name, e))
finally:
if rule.update:
rule.latest = time.strftime("%Y/%m/%d", time.localtime())
logger.info("%s: latest=%s, update=%s"%(rule.name,rule.latest,rule.update))
return rule