yj
2025-08-07 2e391d599d08ea7a7c11442bc2845a1191494c3d
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
在线状态检测工作进程
"""
 
import time
import threading
from datetime import datetime
from loguru import logger
from config import settings
from app.services.ecloud_client import ecloud_client
from app.services.email_service import email_service
from app.services.sms_service import sms_service
 
 
class OnlineStatusWorker:
    """在线状态检测工作进程"""
 
    def __init__(self):
        self.running = False
        self.worker_thread = None
        self.last_notification_time = None
        self.notification_cooldown = 30 * 60  # 30分钟冷却时间,避免频繁发送通知
 
    def start(self):
        """启动在线状态检测工作进程"""
        if not settings.online_status_enabled:
            logger.info("在线状态检测功能已禁用")
            return
 
        self.running = True
        self.worker_thread = threading.Thread(target=self._monitor_online_status, daemon=True)
        self.worker_thread.start()
        logger.info("在线状态检测工作进程已启动")
 
    def stop(self):
        """停止在线状态检测工作进程"""
        self.running = False
        if self.worker_thread and self.worker_thread.is_alive():
            self.worker_thread.join(timeout=10)
        logger.info("在线状态检测工作进程已停止")
 
    def _monitor_online_status(self):
        """监控在线状态的主循环"""
        logger.info(f"开始监控在线状态,检测间隔: {settings.online_status_check_interval}分钟")
        
        while self.running:
            try:
                # 检测在线状态
                self._check_online_status()
                
                # 等待下次检测
                sleep_seconds = settings.online_status_check_interval * 60
                for _ in range(sleep_seconds):
                    if not self.running:
                        break
                    time.sleep(1)
                    
            except Exception as e:
                logger.error(f"在线状态监控异常: {str(e)}")
                time.sleep(60)  # 异常时等待1分钟再继续
 
    def _check_online_status(self):
        """检测在线状态并发送通知"""
        try:
            logger.info("开始检测微信在线状态")
            
            # 查询在线微信列表
            online_list = ecloud_client.query_online_wechat_list()
            
            if online_list is None:
                logger.error("查询在线微信列表失败,跳过本次检测")
                return
            
            online_count = len(online_list)
            logger.info(f"当前在线微信数量: {online_count}")
            
            # 如果有在线微信,更新w_id并重置通知时间
            if online_count > 0:
                # 获取第一个在线微信的w_id并更新配置
                if online_list and len(online_list) > 0:
                    current_w_id = online_list[0].get("wId")
                    if current_w_id:
                        self._update_w_id_if_needed(current_w_id)
 
                if self.last_notification_time:
                    logger.info("检测到在线微信,重置通知状态")
                    self.last_notification_time = None
                return
            
            # 没有在线微信,检查是否需要发送通知
            current_time = time.time()
            
            # 检查冷却时间
            if (self.last_notification_time and 
                current_time - self.last_notification_time < self.notification_cooldown):
                remaining_time = self.notification_cooldown - (current_time - self.last_notification_time)
                logger.info(f"通知冷却中,剩余时间: {remaining_time/60:.1f}分钟")
                return
            
            # 发送掉线通知
            logger.warning("检测到微信全部掉线,发送通知")
            self._send_offline_notification()
            self.last_notification_time = current_time
            
        except Exception as e:
            logger.error(f"检测在线状态异常: {str(e)}")
 
    def _update_w_id_if_needed(self, current_w_id: str):
        """
        如果需要,更新w_id配置
 
        Args:
            current_w_id: 当前检测到的w_id
        """
        try:
            # 获取配置中的当前w_id
            config_w_id = settings.get_current_w_id()
 
            # 如果w_id发生变化,则更新配置
            if current_w_id != config_w_id:
                logger.info(f"检测到w_id变化: {config_w_id} -> {current_w_id}")
                success = settings.update_ecloud_w_id(current_w_id)
                if success:
                    logger.info("w_id更新成功")
                else:
                    logger.error("w_id更新失败")
 
        except Exception as e:
            logger.error(f"更新w_id异常: {str(e)}")
 
    def _send_offline_notification(self):
        """发送掉线通知"""
        try:
            # 准备通知内容
            subject = "微信掉线提醒"
            content = settings.online_status_notification_message
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            # 添加时间戳到内容
            full_content = f"{content}\n\n检测时间: {timestamp}"
            
            # 发送邮件通知
            email_success = False
            if settings.email_enabled:
                try:
                    email_success = email_service.send_notification(subject, full_content)
                    if email_success:
                        logger.info("掉线通知邮件发送成功")
                    else:
                        logger.error("掉线通知邮件发送失败")
                except Exception as e:
                    logger.error(f"发送掉线通知邮件异常: {str(e)}")
            
            # 发送短信通知
            sms_success = False
            if settings.sms_enabled:
                try:
                    # 短信内容不包含时间戳,避免过长
                    sms_success = sms_service.send_notification(content)
                    if sms_success:
                        logger.info("掉线通知短信发送成功")
                    else:
                        logger.error("掉线通知短信发送失败")
                except Exception as e:
                    logger.error(f"发送掉线通知短信异常: {str(e)}")
            
            # 记录通知结果
            if email_success or sms_success:
                logger.info("掉线通知发送完成")
            else:
                logger.error("掉线通知发送全部失败")
                
        except Exception as e:
            logger.error(f"发送掉线通知异常: {str(e)}")
 
    def get_status(self) -> dict:
        """获取工作进程状态"""
        return {
            "running": self.running,
            "enabled": settings.online_status_enabled,
            "check_interval_minutes": settings.online_status_check_interval,
            "last_notification_time": self.last_notification_time,
            "notification_cooldown_minutes": self.notification_cooldown / 60
        }
 
 
# 全局在线状态检测工作进程实例
online_status_worker = OnlineStatusWorker()