diff --git a/README.md b/README.md
index 5869ab8..44024bc 100644
--- a/README.md
+++ b/README.md
@@ -67,10 +67,10 @@ pip install -r requirements.txt
- 打开[Server酱](https://benjiah.gitee.io/redirect/serversauce)。
- 申请一个`sendkey`,并记录下来。
-### 4.2.填写[`config/config.ini`](config/config_example.ini)
+### 4.2.填写[`config/config.json`](config/config_example.json)
-- 重命名`config_example.ini`文件为`config.ini`。
-- 参照[`config.ini`文件](config/config_example.ini)内说明填写其余内容。
+- 重命名`config_example.json`文件为`config.json`。
+- 参照[`config.json`文件](config/config_example.json)内说明填写其余内容。
### 4.3.填写[`config/account.csv`](config/account_example.csv)(可选)
@@ -125,15 +125,12 @@ chmod 777 scripts/run.sh
│
├─config
│ account.csv <---多账户管理文件
-│ config.ini <---配置文件
+│ config.json <---配置文件
+│ email_tmpl.html <---Email模板文件
│
├─log
│ log.log <---日志文件
│
-├─res
-│ email_tmpl.html <---Email模板文件
-│ error.json <---错误码及错误信息文件
-│
└─scripts
run.bat <---Windows下运行文件
run.sh <---GNU/Linux下运行文件
diff --git a/common/account.py b/common/account.py
index 7d23ec4..d7ccc03 100644
--- a/common/account.py
+++ b/common/account.py
@@ -2,6 +2,7 @@
import csv
from common.logger import logger
+from common.config import global_config as gc
class Account:
@@ -18,7 +19,7 @@ def __init__(self, csv_file="../config/account.csv"):
@logger.catch
def _read_csv(self):
- self._csv_file = csv.reader(open(self._path, encoding='UTF-8-sig'))
+ self._csv_file = csv.reader(open(self._path, encoding='utf-8-sig'))
for row in self._csv_file:
if row == [] or "#" in row[0]:
logger.debug(f"Del:{row}")
@@ -60,4 +61,4 @@ def row(self):
return len(self._raw)
-global_account = Account("../config/account.csv")
+global_account = Account(gc.config['config']['path']['account_file'])
diff --git a/common/config.py b/common/config.py
index c7f6ae1..12b2969 100644
--- a/common/config.py
+++ b/common/config.py
@@ -1,34 +1,28 @@
import os
-import configparser
+import json
from common.logger import logger
class Config:
- def __init__(self, config_file=r"../config/config.ini"):
+ def __init__(self, config_file=r"../config/config.json"):
os.chdir(os.path.dirname(__file__))
self._path = os.path.abspath(config_file)
if not os.path.exists(self._path):
logger.error(f"No such file:{self._path}")
raise FileNotFoundError(f"No such file:{self._path}")
- self._config = configparser.ConfigParser()
- self._config.read(self._path, encoding='utf-8-sig')
- self._configRaw = configparser.RawConfigParser()
- self._configRaw.read(self._path, encoding='utf-8-sig')
+ self.config = {}
+ self._json_read()
+
+ @logger.catch
+ def _json_read(self):
+ with open(self._path, 'r', encoding='utf-8') as f:
+ self.config = json.load(f)
logger.debug(f"Loaded [{self._path}]")
@logger.catch
def refresh(self):
- self._config.read(self._path, encoding='utf-8-sig')
- self._configRaw.read(self._path, encoding='utf-8-sig')
+ self._json_read()
logger.debug(f"Refreshed [{self._path}]")
- @logger.catch
- def get(self, section, name):
- return self._config.get(section, name)
-
- @logger.catch
- def getRaw(self, section, name):
- return self._configRaw.get(section, name)
-
-global_config = Config(r"../config/config.ini")
+global_config = Config(r"../config/config.json")
diff --git a/common/logger.py b/common/logger.py
index 4a124d8..cf9f4ac 100644
--- a/common/logger.py
+++ b/common/logger.py
@@ -7,7 +7,7 @@
class Logger:
def __init__(self, log_file: str):
os.chdir(os.path.dirname(__file__))
- self._config_path = os.path.abspath(r"../config/config.ini")
+ self._config_path = os.path.abspath(r"../config/config.json")
self._log_fmt = "{time:YYYY-MM-DD HH:mm:ss.SSS} [{level:<5}] {file}.{line}: {message}"
self._debug_fmt = "{time:YYYY-MM-DD HH:mm:ss.SSS} [{level:<5}] {name}:{function}:{line}: {message}"
self._logger_conf(log_file)
@@ -28,13 +28,13 @@ def _logger_conf(self, log_file):
def _get_level(self):
level_raw = ""
try:
- with open(self._config_path, "r", encoding="UTF-8") as f:
+ with open(self._config_path, "r", encoding="utf-8") as f:
lines = f.readlines()
for i in lines:
if "level" in i and ";" != i[0]:
level_raw = i
except:
- level_raw = "level = INFO"
+ level_raw = '"level": "DEBUG",'
if "DEBUG" in level_raw:
self._level = "DEBUG"
else:
diff --git a/common/push.py b/common/push.py
index 80c0e72..630a00d 100644
--- a/common/push.py
+++ b/common/push.py
@@ -7,14 +7,14 @@
from urllib import parse
from datetime import datetime
from email.mime.text import MIMEText
-from common.config import global_config
+from common.config import global_config as gc
from common.logger import logger
class Email:
@logger.catch
def __init__(self, mail_user, mail_host, mail_pwd):
- if global_config.getRaw('config', 'email_enable') == "off":
+ if gc.config['setting']['push']['email']['enable'] == "off":
logger.debug("Email is disabled")
return
logger.debug("Email is enabled")
@@ -25,17 +25,18 @@ def __init__(self, mail_user, mail_host, mail_pwd):
self._is_login = False
self.smtp = 0
self._mail_payload = ""
+ self._email_tmpl_path = gc.config['config']['path']['email_tmpl']
@logger.catch
def _load_tmpl(self):
os.chdir(os.path.dirname(__file__))
- with open(r"../res/email_tmpl.html", "r", encoding="UTF-8") as f:
+ with open(self._email_tmpl_path, "r", encoding="utf-8") as f:
self._mail_payload = f.read()
logger.debug(f'Loaded [{os.path.abspath(r"../res/email_tmpl.html")}]')
@logger.catch
def login(self):
- if global_config.getRaw('config', 'email_enable') == "off":
+ if gc.config['setting']['push']['email']['enable'] == "off":
return
self._load_tmpl()
try:
@@ -75,18 +76,19 @@ def send(self, uid, title, msg, receiver: list):
class Push:
@logger.catch
def __init__(self):
- self._global_wechat = global_config.getRaw('config', 'wechat_enable')
- self._global_email = global_config.getRaw('config', 'email_enable')
- self._bot_email_user = global_config.getRaw('bot_email', 'email_user')
- self._bot_email_host = global_config.getRaw('bot_email', 'email_host')
- self._bot_email_pwd = global_config.getRaw('bot_email', 'email_pwd')
+ self._global_wechat = gc.config['setting']['push']['wechat']['enable']
+ self._global_email = gc.config['setting']['push']['email']['enable']
+ self._bot_email_user = gc.config['bot_email']['email_user']
+ self._bot_email_host = gc.config['bot_email']['email_host']
+ self._bot_email_pwd = gc.config['bot_email']['email_pwd']
self.bot_email = Email(self._bot_email_user, self._bot_email_host, self._bot_email_pwd)
- self._errno_msg_path = r"../res/error.json"
- self._errno_msg = self._load_errno()
+ self._errno_msg_path = gc.config['config']['path']['errno_msg']
+ # self._errno_msg = self._load_errno()
+ self._errno_msg = gc.config['config']['errmsg']
@logger.catch
def _load_errno(self):
- with open(self._errno_msg_path, "r", encoding="UTF-8") as f:
+ with open(self._errno_msg_path, "r", encoding="utf-8") as f:
self._raw = f.read()
logger.debug(f'Loaded [{os.path.abspath(self._errno_msg_path)}]')
return json.loads(self._raw)
@@ -95,7 +97,7 @@ def _load_errno(self):
@logger.catch
def sct_wechat(uid, title, message, sendkey):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- url = f'https://sctapi.ftqq.com/{sendkey}.send'
+ url = f"{gc.config['config']['url']['sct']}/{sendkey}.send"
ps = ""
msg = f'{" " * 10}{title}\n\n{uid}:\n{" " * 4}{message}\n{ps}\n\n{now}'
payload = {
@@ -162,7 +164,7 @@ def push(self, result, uid, wechat_push, email_push, wechat_type, api, userid, s
title = "[ERROR]"
message = "ERROR!"
if errno != 0:
- errmsg = [i["msg"] for i in self._errno_msg["content"] if errno == i["errno"]][0]
+ errmsg = [i["msg"] for i in self._errno_msg if errno == i["errno"]][0]
message = f'{message}[错误信息:"{errmsg}"]'
logger.debug(f"Title:{title}#Message:{message}#Error code:{errno}")
if self._global_wechat != "off":
diff --git a/common/report.py b/common/report.py
index a81ebc6..43115b8 100644
--- a/common/report.py
+++ b/common/report.py
@@ -6,6 +6,7 @@
from bs4 import BeautifulSoup
from common import security
from common.logger import logger
+from common.config import global_config as gc
class Report:
@@ -18,6 +19,8 @@ def __init__(self):
self._navigation_url = 0
self._date = ""
self._captcha_code = ""
+ self._success = gc.config['config']['response']['success']
+ self._existed = gc.config['config']['response']['existed']
@logger.catch
def update_date(self):
@@ -39,7 +42,7 @@ def _get_captcha_code(self):
logger.error(f"No available hosts.")
self._set_error(6, 1)
return
- url = f"{self._host}/weblogin.asp"
+ url = f"{self._host}/{gc.config['config']['url']['login']}"
res = self._session.get(url=url, headers=self._headers)
logger.debug(f"URL:{url}. Status code:{res.status_code}")
res.encoding = "utf-8"
@@ -59,7 +62,7 @@ def _login(self, uid, password):
if self._error == 1:
logger.debug(f"The error flag: {self._error}. Exit the function.")
return
- url = f"{self._host}/weblogin.asp"
+ url = f"{self._host}/{gc.config['config']['url']['login']}"
payload = {
"username": uid,
"userpwd": password,
@@ -88,7 +91,7 @@ def _get_navigation_url(self, target):
if self._error == 1:
logger.debug(f"The error flag: {self._error}. Exit the function.")
return
- url = f"{self._host}/left.asp"
+ url = f"{self._host}/{gc.config['config']['url']['left']}"
res = self._session.get(url=url, headers=self._headers)
logger.debug(f"URL:{url}. Status code:{res.status_code}")
if res.status_code != 200:
@@ -110,7 +113,7 @@ def _report_default_method(self):
return ""
logger.info("Try to report in the default method.")
param = parse.parse_qs(parse.urlparse(str(self._navigation_url)).query)
- url = f"{self._host}/projecthealth_addx.asp"
+ url = f"{self._host}/{gc.config['config']['url']['report_default']}"
payload = {
"id": param["id"][0],
"id2": self._date,
@@ -133,7 +136,7 @@ def _report(self, location):
logger.info("Try to report in the alternate method.")
[province, city, area] = location
param = parse.parse_qs(parse.urlparse(str(self._navigation_url)).query)
- url = f"{self._host}/projecthealth_add.asp"
+ url = f"{self._host}/{gc.config['config']['url']['report']}"
payload = {
"id": param["id"][0],
"id2": self._date,
@@ -189,27 +192,30 @@ def main(self, uid, password):
self._error = 0
self._errno = 0
self._session = requests.Session()
- self._host = f"https://xsswzx.cdu.edu.cn/{security.get_random_host()}/com_user"
+ _host_0 = gc.config['config']['url']['host_head']
+ _host_1 = security.get_random_host()
+ _host_2 = gc.config['config']['url']['host_foot']
+ self._host = f"{_host_0}/{_host_1}/{_host_2}"
self._headers = {
"User-Agent": security.get_random_useragent()
}
self._get_captcha_code()
self._login(uid, password)
- self._get_navigation_url("健康日报登记")
+ self._get_navigation_url(gc.config['config']['url']['navigation'])
ret = self._report_default_method()
- if "已存在" in ret:
+ if self._existed in ret:
logger.info(f"The report is already existed. ID:{uid}")
return 0, self._errno
- elif "提交成功" in ret:
+ elif self._success in ret:
logger.info(f"Successful to report. ID:{uid}")
return 1, self._errno
else:
logger.error("Failed to report in the default method.")
ret = self._report(self._fetch_location())
- if "已存在" in ret:
+ if self._existed in ret:
logger.info(f"The report is already existed. ID:{uid}")
return 0, self._errno
- elif "提交成功" in ret:
+ elif self._success in ret:
logger.info(f"Successful to report. ID:{uid}")
return 1, self._errno
else:
diff --git a/common/security.py b/common/security.py
index 5c591c7..cdb5658 100644
--- a/common/security.py
+++ b/common/security.py
@@ -2,29 +2,21 @@
import requests
from common.logger import logger
+from common.config import global_config as gc
from fake_useragent import UserAgent
-HOSTS = [
- "ispstu", # 富强
- "ispstu1-1", # 民主
- "ispstu1-2", # 文明
- "ispstu2", # 和谐
- "ispstu2-1", # 自由
- "ispstu2-2", # 平等
- "ispstu3", # 公正
- "ispstu3-1", # 法治
- "ispstu3-2", # 爱国
- "ispstu4", # 敬业
- "ispstu4-1", # 诚信
- "ispstu4-3" # 友善
-]
+HOSTS = list(gc.config['config']['all_hosts'].keys())
ua = UserAgent(verify_ssl=False)
available_host = []
@logger.catch
def check_host_status(host):
- url = f"https://xsswzx.cdu.edu.cn/{host}/com_user/weblogin.asp"
+ url_0 = gc.config['config']['url']['host_head']
+ url_1 = host
+ url_2 = gc.config['config']['url']['host_foot']
+ url_3 = gc.config['config']['url']['login']
+ url = f"{url_0}/{url_1}/{url_2}/{url_3}"
try:
res = requests.get(url=url, timeout=10)
logger.debug(f"URL:{url}. Status code:{res.status_code}")
diff --git a/common/service.py b/common/service.py
index 8f3a4f5..9fed61e 100644
--- a/common/service.py
+++ b/common/service.py
@@ -2,7 +2,7 @@
from time import sleep, time
from common import security
from common.logger import logger
-from common.config import global_config
+from common.config import global_config as gc
from common.account import global_account
from common.report import Report
from common.push import global_push
@@ -12,10 +12,10 @@ class ReportService:
@logger.catch
def __init__(self):
self._str_now_time = "0.1"
- self._wechat_push = global_config.getRaw('config', 'wechat_enable')
- self._email_push = global_config.getRaw('config', 'email_enable')
- self._wechat_type = global_config.getRaw('config', 'wechat_type')
- self._api = global_config.getRaw('config', 'api')
+ self._wechat_push = gc.config['setting']['push']['wechat']['enable']
+ self._wechat_type = gc.config['setting']['push']['wechat']['type']
+ self._api = gc.config['setting']['push']['wechat']['api']
+ self._email_push = gc.config['setting']['push']['email']['enable']
self._account_cnt = global_account.row
self._report = Report()
@@ -52,21 +52,21 @@ def _gen(self):
@logger.catch
def start(self):
- if global_config.getRaw('config', 'timer_enable') == "off":
+ if gc.config['setting']['timer']['enable'] == "off":
logger.info("Timer is disabled.")
logger.info("Start to report.")
self._gen()
else:
logger.info("Timer is enabled.")
while True:
- global_config.refresh()
- str_set_time = global_config.getRaw('config', 'set_time')
+ gc.refresh()
+ str_set_time = str(gc.config['setting']['timer']['set_time'])
str_now_time = self._get_now_time()
logger.info(f"Now time:{str_now_time}. Set time:{str_set_time}.")
while True:
- global_config.refresh()
- if str_set_time != global_config.getRaw('config', 'set_time'):
- str_set_time = global_config.getRaw('config', 'set_time')
+ gc.refresh()
+ if str_set_time != str(gc.config['setting']['timer']['set_time']):
+ str_set_time = str(gc.config['setting']['timer']['set_time'])
logger.info(f"New set time:{str_set_time}.")
str_now_time = self._get_now_time()
if str_now_time != str_set_time:
diff --git a/config/config_example.ini b/config/config_example.ini
deleted file mode 100644
index a0790a5..0000000
--- a/config/config_example.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-; ###########################
-; 使用时请修改文件名为 config.ini
-; 以下填写均不需要引号!
-; ###########################
-[config]
-; 如果想开启定时打卡,则将 timer_enable 设置为 on,默认为 off 不开启
-timer_enable = off
-
-; 开启定时打卡后必须设定打卡时间,如6点5分则输入06.05
-set_time = 06.05
-
-; ###########################################
-; 微信推送全局开关
-; 使用了Server酱的推送服务
-; 如果需要微信推送打卡结果,则将 wechat_enable 设置为 on,默认为 off 不开启
-wechat_enable = off
-
-;提供多种推送通道,目前仅支持sct企业微信和腾讯云自建企业微信(go-scf)
-;如果需选择企业微信通道,则将 wechat_type 设置为 1,否则为 2 。默认为 1 sct企业微信通道
-wechat_type = 1
-
-; 如果wechat_type = 2 ,必须填入 api (请求路径:https://xxxxxxxxxx)
-api =
-; ###########################################
-
-; 邮件推送全局开关
-; 如果需要邮件推送打卡结果,则将 email_enable 设置为 on,默认为 off 不开启
-email_enable = off
-
-[bot_email]
-; 负责推送服务的邮箱
-
-# 邮箱地址 xxxxxxxx@xx.com
-email_user =
-
-# 邮箱域名 smtp.xx.com
-email_host =
-
-# 邮箱授权码(并不一定是邮箱密码) xxxxxxxxxxxxxxxx
-email_pwd =
diff --git a/config/config_example.json b/config/config_example.json
new file mode 100644
index 0000000..97399b7
--- /dev/null
+++ b/config/config_example.json
@@ -0,0 +1,108 @@
+{
+ "setting": {
+ "timer": {
+ "//enable": "[必填]如果想开启定时打卡,则将 enable 设置为 on,默认为 off 不开启",
+ "enable": "off",
+ "//set_time": "[选填]开启定时打卡后必须设定打卡时间,如6点5分则输入06.05(用双引号包裹)",
+ "set_time": "06.05"
+ },
+ "push": {
+ "//email": "邮件推送配置",
+ "email": {
+ "//enable": "[必填]如果需要邮件推送打卡结果,则将 enable 设置为 on,默认为 off 不开启",
+ "enable": "off"
+ },
+ "//wechat": "微信推送配置,使用了Server酱的推送服务",
+ "wechat": {
+ "//enable": "[必填]微信推送全局开关。如果需要微信推送打卡结果,则将 enable 设置为 on,默认为 off 不开启",
+ "enable": "off",
+ "//type": "[选填]提供多种推送通道,目前仅支持sct企业微信和腾讯云自建企业微信(go-scf)。如果需选择企业微信通道,则将 type 设置为 1,否则为 2 。默认为 1 sct企业微信通道",
+ "type": 1,
+ "//api": "[选填]如果type = 2 ,必须填入 api (请求路径:https://xxxxxxxxxx)",
+ "api": "https://xxxxxxxxxx"
+ }
+ }
+ },
+ "//bot_email": "[选填]负责推送服务的邮箱",
+ "bot_email": {
+ "//email_user": "邮箱地址 xxxxxxxx@xx.com",
+ "email_user": "",
+ "//email_host": "邮箱域名 smtp.xx.com",
+ "email_host": "",
+ "//email_pwd": "邮箱授权码(并不一定是邮箱密码)",
+ "email_pwd": ""
+ },
+ "//config": "!!程序配置,请勿修改!!",
+ "config": {
+ "url": {
+ "host_head": "https://xsswzx.cdu.edu.cn",
+ "host_foot": "com_user",
+ "login": "weblogin.asp",
+ "left": "left.asp",
+ "navigation": "健康日报登记",
+ "report_default": "projecthealth_addx.asp",
+ "report": "projecthealth_add.asp",
+ "sct": "https://sctapi.ftqq.com"
+ },
+ "path": {
+ "account_file": "../config/account.csv",
+ "email_tmpl": "../config/email_tmpl.html"
+ },
+ "response": {
+ "success": "提交成功",
+ "existed": "已存在"
+ },
+ "all_hosts": {
+ "ispstu": "富强",
+ "ispstu1-1": "民主",
+ "ispstu1-2": "文明",
+ "ispstu2": "和谐",
+ "ispstu2-1": "自由",
+ "ispstu2-2": "平等",
+ "ispstu3": "公正",
+ "ispstu3-1": "法治",
+ "ispstu3-2": "爱国",
+ "ispstu4": "敬业",
+ "ispstu4-1": "诚信",
+ "ispstu4-3": "友善"
+ },
+ "errmsg": [
+ {
+ "errno": 0,
+ "msg": "OK"
+ },
+ {
+ "errno": -1,
+ "msg": "未知错误"
+ },
+ {
+ "errno": 1,
+ "msg": "提取验证码失败"
+ },
+ {
+ "errno": 2,
+ "msg": "登录ISP系统失败:学号、密码或验证码错误"
+ },
+ {
+ "errno": 3,
+ "msg": "解析『疫情信息登记』地址失败"
+ },
+ {
+ "errno": 4,
+ "msg": "解析『【一键登记:无变化】』地址失败"
+ },
+ {
+ "errno": 5,
+ "msg": "解析最近一次登记记录失败,已为您强制打卡"
+ },
+ {
+ "errno": 6,
+ "msg": "网络错误,与ISP系统建立连接失败"
+ },
+ {
+ "errno": 7,
+ "msg": "解析最新登记地点失败,请手动打卡"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/res/email_tmpl.html b/config/email_tmpl.html
similarity index 100%
rename from res/email_tmpl.html
rename to config/email_tmpl.html
diff --git a/main.py b/main.py
index c0e55ed..abe792e 100644
--- a/main.py
+++ b/main.py
@@ -12,6 +12,6 @@
|_|
"""
print(LOGO)
-log_version("beta", "1.3.1")
+log_version("beta", "1.4.0")
report_service = ReportService()
report_service.start()
diff --git a/res/error.json b/res/error.json
deleted file mode 100644
index 66a4c68..0000000
--- a/res/error.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "WARNING" : "DO NOT EDIT THIS FILE!",
- "content" : [
- {
- "errno" : 0,
- "msg" : "OK"
- },
- {
- "errno" : -1,
- "msg" : "未知错误"
- },
- {
- "errno" : 1,
- "msg" : "提取验证码失败"
- },
- {
- "errno" : 2,
- "msg" : "登录ISP系统失败:学号、密码或验证码错误"
- },
- {
- "errno" : 3,
- "msg" : "解析『疫情信息登记』地址失败"
- },
- {
- "errno" : 4,
- "msg" : "解析『【一键登记:无变化】』地址失败"
- },
- {
- "errno" : 5,
- "msg" : "解析最近一次登记记录失败,已为您强制打卡"
- },
- {
- "errno" : 6,
- "msg" : "网络错误,与ISP系统建立连接失败"
- },
- {
- "errno" : 7,
- "msg" : "解析最新登记地点失败,请手动打卡"
- }
- ]
-}