feat: 重构定时任务系统并增强配置管理
- 将硬编码的时间配置改为从CONFIG读取 - 支持多接收人配置,修改open_id为数组类型 - 增加发送时间等待功能,确保消息在指定时间发送 - 改进停止定时任务的进程查找逻辑 - 更新配置项,增加checking_time、sending_time和message字段
This commit is contained in:
parent
546ca9dfe2
commit
7233700539
11
config.py
11
config.py
@ -1,7 +1,10 @@
|
|||||||
CONFIG = {
|
CONFIG = {
|
||||||
"app_id": "cli_a8de57f7e95f100c",
|
"app_id": "cli_a8d64a7be63a500e",
|
||||||
"app_secret": "jm2nkFnnSNVS3n076VOPfh8k7q0hEKVp",
|
"app_secret": "mcK8aTiq0CLtkzGs2aTZpcnom5J4o6yB",
|
||||||
"open_id": "ou_bd33a5f75dd2ccb005a21e4dd01f930c",
|
"open_id": ["ou_c6466a45623096cf7a34d94fe30c6c73", "ou_3b94d0caf83dbced8b0e26af4852a281"],
|
||||||
"file_path": "C:\\Users\\22251\\OneDrive\\桌面\\picture\\",
|
"file_path": "C:\\Users\\22251\\OneDrive\\桌面\\picture\\",
|
||||||
"messages_reciever": "File Transfer"
|
"messages_reciever": "文件传输",
|
||||||
|
"checking_time": "17:15",
|
||||||
|
"sending_time": "17:17",
|
||||||
|
"message": "新的一天,从华智长盈每日AI新闻开始!让我们一起看看今天AI圈有啥新鲜事!"
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from config import CONFIG
|
||||||
|
|
||||||
def run_sendmsg():
|
def run_sendmsg():
|
||||||
"""执行sendmsg.py脚本"""
|
"""执行sendmsg.py脚本"""
|
||||||
@ -22,7 +23,7 @@ def run_sendmsg():
|
|||||||
def main():
|
def main():
|
||||||
"""主函数 - 设置定时任务"""
|
"""主函数 - 设置定时任务"""
|
||||||
# 每天17:30执行任务
|
# 每天17:30执行任务
|
||||||
schedule.every().day.at("17:40").do(run_sendmsg)
|
schedule.every().day.at(CONFIG['checking_time']).do(run_sendmsg)
|
||||||
|
|
||||||
print(f"[{datetime.now()}] 定时任务已启动,将在每天17:30执行sendmsg.py")
|
print(f"[{datetime.now()}] 定时任务已启动,将在每天17:30执行sendmsg.py")
|
||||||
print("按Ctrl+C停止程序")
|
print("按Ctrl+C停止程序")
|
||||||
|
|||||||
@ -5,30 +5,34 @@ from lark_oapi.api.im.v1 import *
|
|||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
Local_openid = CONFIG['open_id']
|
||||||
|
|
||||||
client = lark.Client.builder() \
|
client = lark.Client.builder() \
|
||||||
.app_id(CONFIG['app_id']) \
|
.app_id(CONFIG['app_id']) \
|
||||||
.app_secret(CONFIG['app_secret']) \
|
.app_secret(CONFIG['app_secret']) \
|
||||||
.log_level(lark.LogLevel.DEBUG) \
|
.log_level(lark.LogLevel.DEBUG) \
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
for local_openid in Local_openid:
|
||||||
# 构造请求对象
|
# 构造请求对象
|
||||||
request: CreateMessageRequest = CreateMessageRequest.builder() \
|
request: CreateMessageRequest = CreateMessageRequest.builder() \
|
||||||
.receive_id_type("open_id") \
|
.receive_id_type("open_id") \
|
||||||
.request_body(CreateMessageRequestBody.builder()
|
.request_body(CreateMessageRequestBody.builder()
|
||||||
.receive_id(CONFIG['open_id'])
|
.receive_id(local_openid)
|
||||||
.msg_type("text")
|
.msg_type("text")
|
||||||
.content("{\"text\":\"未找到指定图片\"}")
|
.content("{\"text\":\"未找到指定图片,请手动发送\"}")
|
||||||
.build()) \
|
.build()) \
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
# 发起请求
|
# 发起请求
|
||||||
response: CreateMessageResponse = client.im.v1.message.create(request)
|
response: CreateMessageResponse = client.im.v1.message.create(request)
|
||||||
|
|
||||||
# 处理失败返回
|
# 处理失败返回
|
||||||
if not response.success():
|
if not response.success():
|
||||||
lark.logger.error(
|
lark.logger.error(
|
||||||
f"client.im.v1.message.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
f"client.im.v1.message.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 处理业务结果
|
# 处理业务结果
|
||||||
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
|
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
|
||||||
|
|||||||
@ -5,6 +5,8 @@ from lark_oapi.api.im.v1 import *
|
|||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
Local_openid = CONFIG['open_id']
|
||||||
# 创建client
|
# 创建client
|
||||||
client = lark.Client.builder() \
|
client = lark.Client.builder() \
|
||||||
.app_id(CONFIG['app_id']) \
|
.app_id(CONFIG['app_id']) \
|
||||||
@ -13,26 +15,27 @@ def main():
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
# 构造请求对象
|
# 构造请求对象
|
||||||
request: CreateMessageRequest = CreateMessageRequest.builder() \
|
for local_openid in Local_openid:
|
||||||
.receive_id_type("open_id") \
|
request: CreateMessageRequest = CreateMessageRequest.builder() \
|
||||||
.request_body(CreateMessageRequestBody.builder()
|
.receive_id_type("open_id") \
|
||||||
.receive_id(CONFIG['open_id'])
|
.request_body(CreateMessageRequestBody.builder()
|
||||||
.msg_type("text")
|
.receive_id(local_openid)
|
||||||
.content("{\"text\":\"请打开微信或者登录微信\"}")
|
.msg_type("text")
|
||||||
.build()) \
|
.content("{\"text\":\"请打开微信或者登录微信\"}")
|
||||||
.build()
|
.build()) \
|
||||||
|
.build()
|
||||||
|
|
||||||
# 发起请求
|
# 发起请求
|
||||||
response: CreateMessageResponse = client.im.v1.message.create(request)
|
response: CreateMessageResponse = client.im.v1.message.create(request)
|
||||||
|
|
||||||
# 处理失败返回
|
# 处理失败返回
|
||||||
if not response.success():
|
if not response.success():
|
||||||
lark.logger.error(
|
lark.logger.error(
|
||||||
f"client.im.v1.message.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
f"client.im.v1.message.create failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 处理业务结果
|
# 处理业务结果
|
||||||
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
|
lark.logger.info(lark.JSON.marshal(response.data, indent=4))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
33
sendmsg.py
33
sendmsg.py
@ -1,5 +1,5 @@
|
|||||||
from wxauto import WeChat
|
from wxauto import WeChat
|
||||||
from datetime import date
|
from datetime import date, datetime, time as dt_time
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
@ -7,6 +7,27 @@ import json
|
|||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
def wait_until_time():
|
||||||
|
"""等待到配置的发送时间"""
|
||||||
|
now = datetime.now()
|
||||||
|
|
||||||
|
# 从配置文件中读取发送时间
|
||||||
|
send_time_str = CONFIG['sending_time'] # "17:10"
|
||||||
|
hour, minute = map(int, send_time_str.split(':'))
|
||||||
|
|
||||||
|
target_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
|
||||||
|
|
||||||
|
# 如果当前时间已经过了今天的发送时间,则设置为明天的发送时间
|
||||||
|
if now >= target_time:
|
||||||
|
target_time = target_time.replace(day=target_time.day + 1)
|
||||||
|
|
||||||
|
wait_seconds = (target_time - now).total_seconds()
|
||||||
|
print(f"当前时间: {now.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f"将在 {target_time.strftime('%Y-%m-%d %H:%M:%S')} 执行发送操作")
|
||||||
|
print(f"等待时间: {wait_seconds/3600:.2f} 小时")
|
||||||
|
|
||||||
|
time.sleep(wait_seconds)
|
||||||
|
|
||||||
def send_daily_message():
|
def send_daily_message():
|
||||||
"""发送每日消息的主函数"""
|
"""发送每日消息的主函数"""
|
||||||
today = date.today()
|
today = date.today()
|
||||||
@ -20,13 +41,19 @@ def send_daily_message():
|
|||||||
subprocess.run([sys.executable, 'send_openmsg.py'])
|
subprocess.run([sys.executable, 'send_openmsg.py'])
|
||||||
return False
|
return False
|
||||||
|
|
||||||
msg = 'hello, wxauto!'
|
msg = CONFIG['message']
|
||||||
who = CONFIG['messages_reciever']
|
who = CONFIG['messages_reciever']
|
||||||
|
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
print("找到了指定文件!")
|
print("找到了指定文件!")
|
||||||
wx.SendFiles(filepath=file_path, who="File Transfer")
|
|
||||||
|
# 等待到配置的时间再执行发送操作
|
||||||
|
wait_until_time()
|
||||||
|
|
||||||
|
print("开始发送文件和消息...")
|
||||||
|
wx.SendFiles(filepath=file_path, who=who)
|
||||||
wx.SendMsg(msg=msg, who=who)
|
wx.SendMsg(msg=msg, who=who)
|
||||||
|
print("发送完成!")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("没找到指定文件")
|
print("没找到指定文件")
|
||||||
|
|||||||
@ -1,25 +1,90 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import psutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
def stop_scheduler():
|
def stop_scheduler():
|
||||||
"""停止定时任务进程"""
|
"""停止定时任务进程"""
|
||||||
|
stopped_count = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 查找并结束scheduler.py进程
|
# 方法1: 使用psutil精确查找进程
|
||||||
result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq pythonw.exe', '/FO', 'CSV'],
|
current_dir = str(Path(__file__).parent)
|
||||||
capture_output=True, text=True)
|
|
||||||
|
|
||||||
if 'scheduler.py' in result.stdout:
|
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
||||||
# 结束包含scheduler.py的pythonw进程
|
try:
|
||||||
subprocess.run(['taskkill', '/F', '/IM', 'pythonw.exe'], check=True)
|
if proc.info['name'] in ['python.exe', 'pythonw.exe']:
|
||||||
print("定时任务已停止")
|
cmdline = proc.info['cmdline']
|
||||||
else:
|
if cmdline and len(cmdline) > 1:
|
||||||
print("未找到运行中的定时任务")
|
# 检查是否是我们的scheduler.py进程
|
||||||
|
if 'scheduler.py' in ' '.join(cmdline) and current_dir in ' '.join(cmdline):
|
||||||
|
print(f"找到进程: PID={proc.info['pid']}, 命令行={' '.join(cmdline)}")
|
||||||
|
proc.terminate()
|
||||||
|
proc.wait(timeout=5) # 等待进程正常结束
|
||||||
|
print(f"已终止进程 PID={proc.info['pid']}")
|
||||||
|
stopped_count += 1
|
||||||
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||||
|
continue
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
print("psutil模块未安装,使用备用方法...")
|
||||||
|
# 方法2: 备用方法 - 改进的tasklist方式
|
||||||
|
try:
|
||||||
|
# 获取详细的进程信息
|
||||||
|
result = subprocess.run(['wmic', 'process', 'where', 'name="pythonw.exe"', 'get', 'ProcessId,CommandLine', '/format:csv'],
|
||||||
|
capture_output=True, text=True, encoding='gbk')
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
lines = result.stdout.strip().split('\n')
|
||||||
print(f"停止进程时出错: {e}")
|
current_dir = str(Path(__file__).parent)
|
||||||
except Exception as e:
|
|
||||||
print(f"发生错误: {e}")
|
for line in lines[1:]: # 跳过标题行
|
||||||
|
if line.strip() and 'scheduler.py' in line and current_dir in line:
|
||||||
|
# 提取PID
|
||||||
|
parts = line.split(',')
|
||||||
|
if len(parts) >= 2:
|
||||||
|
pid = parts[-1].strip()
|
||||||
|
if pid.isdigit():
|
||||||
|
subprocess.run(['taskkill', '/F', '/PID', pid], check=True)
|
||||||
|
print(f"已终止进程 PID={pid}")
|
||||||
|
stopped_count += 1
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"备用方法执行失败: {e}")
|
||||||
|
|
||||||
|
# 方法3: 最后的备用方案
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq pythonw.exe', '/FO', 'CSV'],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
|
||||||
|
if 'pythonw.exe' in result.stdout:
|
||||||
|
print("警告: 找到pythonw.exe进程,但无法确定是否为目标进程")
|
||||||
|
response = input("是否强制结束所有pythonw.exe进程?(y/N): ")
|
||||||
|
if response.lower() == 'y':
|
||||||
|
subprocess.run(['taskkill', '/F', '/IM', 'pythonw.exe'], check=True)
|
||||||
|
print("已强制结束所有pythonw.exe进程")
|
||||||
|
stopped_count += 1
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"最后备用方案失败: {e}")
|
||||||
|
|
||||||
|
if stopped_count > 0:
|
||||||
|
print(f"成功停止了 {stopped_count} 个定时任务进程")
|
||||||
|
else:
|
||||||
|
print("未找到运行中的定时任务进程")
|
||||||
|
|
||||||
|
# 额外检查:查看是否还有相关进程
|
||||||
|
print("\n检查剩余进程...")
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq pythonw.exe'],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
if 'pythonw.exe' in result.stdout:
|
||||||
|
print("仍有pythonw.exe进程在运行:")
|
||||||
|
print(result.stdout)
|
||||||
|
else:
|
||||||
|
print("没有发现pythonw.exe进程")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
stop_scheduler()
|
stop_scheduler()
|
||||||
Loading…
x
Reference in New Issue
Block a user