Files
aaPanel/mod/base/push_mod/ssl_push.py
T
Jack a24f2e23c6 Update to 7.25.0
1. Added Mail Marketing Automation trigger tasks
2. Added Mail Marketing Groups Import, Export, Merge
3. Added Mail Marketing Subscribers to support paste import
4. Added Mail Marketing Template Import Export Duplicate
5. Added Mail server add timed automatic reply
6. Added HTTPS Protection function for Website (disables automatic HTTP to HTTPS redirection when enabled)
7. Optimize Website Interface Button Integration
8. Optimize the response speed of WP Toolkit interface
2025-03-13 17:52:26 +08:00

348 lines
13 KiB
Python

import json
import time
from datetime import datetime
from typing import Tuple, Union, Optional
from .send_tool import WxAccountMsg
from .base_task import BaseTask
from .mods import PUSH_DATA_PATH, TaskConfig, PANEL_PATH
from .util import read_file, DB, write_file
from mod.base.web_conf import RealSSLManger
import public
class DomainEndTimeTask(BaseTask):
def __init__(self):
super().__init__()
self.source_name = "domain_endtime"
self.template_name = "Domain expiration"
# self.title = "Domain expiration"
self._tip_file = "{}/domain_endtime.tip".format(PUSH_DATA_PATH)
self._tip_data: Optional[dict] = None
self._task_config = TaskConfig()
# 每次任务使用
self.domain_list = []
self.push_keys = []
self.task_id = None
@property
def tips(self) -> dict:
if self._tip_data is not None:
return self._tip_data
try:
self._tip_data = json.loads(read_file(self._tip_file))
except:
self._tip_data = {}
return self._tip_data
def save_tip(self):
write_file(self._tip_file, json.dumps(self.tips))
def get_keyword(self, task_data: dict) -> str:
return task_data["project"]
def get_push_data(self, task_id: str, task_data: dict) -> Optional[dict]:
self.title = self.get_title(task_data)
# 过滤单独设置提醒的域名
not_push_web = [i["task_data"]["project"] for i in self._task_config.config if i["source"] == self.source_name]
sql = DB("ssl_domains")
total = self._task_config.get_by_id(task_id).get("number_rule", {}).get("total", 1)
if "all" in not_push_web:
not_push_web.remove("all")
# need_check_list = []
if task_data["project"] == "all":
# 所有域名
domain_list = sql.select()
for domain in domain_list:
if domain['domain'] in not_push_web:
continue
if self.tips.get(task_id, {}).get(domain['domain'], 0) > total:
continue
end_time = datetime.strptime(domain['endtime'], '%Y-%m-%d')
if int((end_time.timestamp() - time.time()) / 86400) <= task_data['cycle']:
self.push_keys.append(domain['domain'])
self.domain_list.append(domain)
# need_check_list.append(domain['domain'])
else:
find = sql.where('domain=?', (task_data['project'],)).find()
if not find:
return None
end_time = datetime.strptime(find['endtime'], '%Y-%m-%d')
if int((end_time.timestamp() - time.time()) / 86400) <= task_data['cycle']:
self.push_keys.append(find['domain'])
self.domain_list.append(find)
# need_check_list.append((find['domain']))
# for name, project_type in need_check_list:
# info = self._check_end_time(name, task_data['cycle'], project_type)
# if isinstance(info, dict): # 返回的是详情,说明需要推送了
# info['site_name'] = name
# self.push_keys.append(name)
# self.domain_list.append(info)
if len(self.domain_list) == 0:
return None
s_list = ['>About to expire: <font color=#ff0000>{} </font>'.format(len(self.domain_list))]
for x in self.domain_list:
s_list.append(">Domain: {} Expiration:{}".format(x['domain'], x['endtime']))
self.task_id = task_id
return {"msg_list": s_list}
@staticmethod
def _check_end_time(site_name, limit, prefix) -> Optional[dict]:
info = RealSSLManger(conf_prefix=prefix).get_site_ssl_info(site_name)
if info is not None:
end_time = datetime.strptime(info['notAfter'], '%Y-%m-%d')
if int((end_time.timestamp() - time.time()) / 86400) <= limit:
return info
return None
def get_title(self, task_data: dict) -> str:
if task_data["project"] == "all":
return "Domain expiration -- All"
return "Domain expiration -- [{}]".format(task_data["project"])
def to_sms_msg(self, push_data: dict, push_public_data: dict) -> Tuple[str, dict]:
return 'domain_end|Domain expiration reminders', {
"name": push_public_data["ip"],
"domain": self.domain_list[0]['domain'],
'time': self.domain_list[0]["endtime"],
'total': len(self.domain_list)
}
def to_wx_account_msg(self, push_data: dict, push_public_data: dict) -> WxAccountMsg:
msg = WxAccountMsg.new_msg()
msg.thing_type = "Domain expiration reminders"
msg.msg = "There are {} domain names that will expire and will affect access".format(len(self.domain_list))
return msg
def check_task_data(self, task_data: dict) -> Union[dict, str]:
task_data["interval"] = 60 * 60 * 24 # 默认检测间隔时间 1 天
if not (isinstance(task_data['cycle'], int) and task_data['cycle'] > 1):
return "The remaining time parameter is incorrect, at least 1 day"
return task_data
def filter_template(self, template) -> dict:
domain_list = DB("ssl_domains").select()
items = [{"title": i["domain"], "value": i["domain"]}for i in domain_list]
template["field"][0]["items"].extend(items)
return template
def check_num_rule(self, num_rule: dict) -> Union[dict, str]:
num_rule["get_by_func"] = "can_send_by_num_rule"
return num_rule
# 实际的次数检查已在 get_push_data 其他位置完成
def can_send_by_num_rule(self, task_id: str, task_data: dict, number_rule: dict, push_data: dict) -> Optional[str]:
return None
def task_run_end_hook(self, res) -> None:
if not res["do_send"]:
return
if self.task_id:
if self.task_id not in self.tips:
self.tips[self.task_id] = {}
for w in self.push_keys:
if w in self.tips[self.task_id]:
self.tips[self.task_id][w] += 1
else:
self.tips[self.task_id][w] = 1
self.save_tip()
def task_config_update_hook(self, task: dict) -> None:
if task["id"] in self.tips:
self.tips.pop(task["id"])
self.save_tip()
def task_config_remove_hook(self, task: dict) -> None:
if task["id"] in self.tips:
self.tips.pop(task["id"])
self.save_tip()
class CertEndTimeTask(BaseTask):
def __init__(self):
super().__init__()
self.source_name = "cert_endtime"
self.template_name = "Certificate expiration"
# self.title = "Certificate expiration"
self._tip_file = "{}/cert_endtime.tip".format(PUSH_DATA_PATH)
self._tip_data: Optional[dict] = None
self._task_config = TaskConfig()
# 每次任务使用
self.cert_list = []
self.push_keys = []
self.task_id = None
@property
def tips(self) -> dict:
if self._tip_data is not None:
return self._tip_data
try:
self._tip_data = json.loads(read_file(self._tip_file))
except:
self._tip_data = {}
return self._tip_data
def save_tip(self):
write_file(self._tip_file, json.dumps(self.tips))
def get_keyword(self, task_data: dict) -> str:
return task_data["project"]
def get_push_data(self, task_id: str, task_data: dict) -> Optional[dict]:
from .util import get_cert_list, to_dict_obj
exclude_ids = [i["task_data"]["project"] for i in self._task_config.config if i["source"] == self.source_name]
total = self._task_config.get_by_id(task_id).get("number_rule", {}).get("total", 1)
if "all" in exclude_ids:
exclude_ids.remove("all")
data = get_cert_list(to_dict_obj({"status_id": 1}))['data']
if task_data["project"] == "all":
for cert in data:
if cert["ssl_id"] in exclude_ids:
continue
if self.tips.get(task_id, {}).get(cert['ssl_id'], 0) > total:
continue
if not cert.get("endDay") and cert.get("endDay") != 0:
continue
if cert["endDay"] <= task_data["cycle"]:
self.cert_list.append(cert)
else:
for cert in data:
if cert["ssl_id"] != task_data["project"]:
continue
if not cert.get("endDay") and cert.get("endDay") != 0:
continue
if cert["endDay"] <= task_data["cycle"]:
self.cert_list.append(cert)
self.title = self.get_title(task_data)
if len(self.cert_list) == 0:
return None
s_list = ['>About to expire: <font color=#ff0000>{} </font>'.format(len(self.cert_list))]
for x in self.cert_list:
s_list.append(
">Certificates: {} [{}]expire in days Websites that may be affected:{}".format("{} | {}".format(x["title"],",".join(x.get("domainName", []) or "None")), x['endDay'], ','.join(x.get('use_site', [])) or "None")
)
self.task_id = task_id
return {"msg_list": s_list}
@staticmethod
def _check_end_time(site_name, limit, prefix) -> Optional[dict]:
info = RealSSLManger(conf_prefix=prefix).get_site_ssl_info(site_name)
if info is not None:
end_time = datetime.strptime(info['notAfter'], '%Y-%m-%d')
if int((end_time.timestamp() - time.time()) / 86400) <= limit:
return info
return None
def get_title(self, task_data: dict) -> str:
from .util import get_cert_list, to_dict_obj
if task_data["project"] == "all":
return "Certificate expiration -- All"
data = get_cert_list(to_dict_obj({}))['data']
for cert in data:
if cert["ssl_id"] == task_data["project"]:
return "Certificate expiration -- [{} | {}]".format(cert["title"],",".join(cert.get("domainName", []) or "None"))
return "Domain [{}] expiration reminder".format(task_data["project"])
def to_sms_msg(self, push_data: dict, push_public_data: dict) -> Tuple[str, dict]:
return 'cert_end|Certificate expiration reminders', {
"name": push_public_data["ip"],
"cert": self.cert_list[0]['domain'],
'time': self.cert_list[0]["endtime"],
'total': len(self.cert_list)
}
def to_wx_account_msg(self, push_data: dict, push_public_data: dict) -> WxAccountMsg:
msg = WxAccountMsg.new_msg()
msg.thing_type = "Certificate expiration reminders"
msg.msg = "There are {} certificates that will expire and will affect access".format(len(self.cert_list))
return msg
def check_task_data(self, task_data: dict) -> Union[dict, str]:
task_data["interval"] = 60 * 60 * 24 # 默认检测间隔时间 1 天
if not (isinstance(task_data['cycle'], int) and task_data['cycle'] > 1):
return "The remaining time parameter is incorrect, at least 1 day"
return task_data
def filter_template(self, template) -> dict:
from .util import get_cert_list, to_dict_obj
items = [
{"title": "{} | {}".format(i["title"],",".join(i.get("domainName", []) or "None")), "value": i["ssl_id"]}
for i in get_cert_list(to_dict_obj({}))['data']
if i.get("endDay")
]
template["field"][0]["items"].extend(items)
return template
def check_num_rule(self, num_rule: dict) -> Union[dict, str]:
num_rule["get_by_func"] = "can_send_by_num_rule"
return num_rule
# 实际的次数检查已在 get_push_data 其他位置完成
def can_send_by_num_rule(self, task_id: str, task_data: dict, number_rule: dict, push_data: dict) -> Optional[str]:
return None
def task_run_end_hook(self, res) -> None:
if not res["do_send"]:
return
if self.task_id:
if self.task_id not in self.tips:
self.tips[self.task_id] = {}
for w in self.push_keys:
if w in self.tips[self.task_id]:
self.tips[self.task_id][w] += 1
else:
self.tips[self.task_id][w] = 1
self.save_tip()
def task_config_update_hook(self, task: dict) -> None:
if task["id"] in self.tips:
self.tips.pop(task["id"])
self.save_tip()
def task_config_remove_hook(self, task: dict) -> None:
if task["id"] in self.tips:
self.tips.pop(task["id"])
self.save_tip()
class ViewMsgFormat(object):
_FORMAT = {
"1": (
lambda x: "<span>Time remaining less than {} days {}</span>".format(
x["task_data"].get("cycle"),
("(If it is not processed, it will be resent 1 time the next day for %d days)" % x.get("number_rule", {}).get("total", 0)) if x.get("number_rule", {}).get("total", 0) else ""
)
)
}
def get_msg(self, task: dict) -> Optional[str]:
if task["template_id"] in ["70", "71"]:
return self._FORMAT["1"](task)
if task["template_id"] in self._FORMAT:
return self._FORMAT[task["template_id"]](task)
return None