Files
personal-experiment/notifier.py
T
2026-03-06 17:07:57 +08:00

314 lines
8.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
通知模块
OOP设计的通知系统
"""
import platform
from abc import ABC, abstractmethod
from typing import List, Optional
class Notifier(ABC):
"""通知器抽象基类(策略模式)"""
@abstractmethod
def send(self, title: str, message: str) -> bool:
"""
发送通知
Args:
title: 通知标题
message: 通知内容
Returns:
是否发送成功
"""
pass
def is_enabled(self) -> bool:
"""
检查通知器是否启用
Returns:
是否启用
"""
return True
class ConsoleNotifier(Notifier):
"""控制台通知器"""
def send(self, title: str, message: str) -> bool:
"""在控制台显示通知"""
separator = "=" * 60
print(f"\n{separator}")
print(f"【{title}】")
print(f"{message}")
print(f"{separator}\n")
return True
class DesktopNotifier(Notifier):
"""桌面通知器"""
def __init__(self):
"""初始化桌面通知器"""
self.os_type = platform.system().lower()
self.enabled = self._initialize()
def _initialize(self) -> bool:
"""初始化通知库"""
try:
if self.os_type == "windows":
import win10toast
self.toaster = win10toast.ToastNotifier()
elif self.os_type == "linux":
import notify2
notify2.init("网络监控器")
elif self.os_type == "darwin":
import pync
return True
except ImportError:
return False
def is_enabled(self) -> bool:
"""检查是否启用"""
return self.enabled
def send(self, title: str, message: str) -> bool:
"""发送桌面通知"""
if not self.is_enabled():
return False
try:
if self.os_type == "windows":
self.toaster.show_notification(title, message, duration=10)
elif self.os_type == "linux":
import notify2
notification = notify2.Notification(title, message)
notification.show()
elif self.os_type == "darwin":
import pync
pync.notify(message, title=title)
return True
except Exception:
return False
class EmailNotifier(Notifier):
"""邮件通知器"""
def __init__(
self,
smtp_server: Optional[str] = None,
smtp_port: Optional[int] = None,
username: Optional[str] = None,
password: Optional[str] = None,
from_email: Optional[str] = None,
to_email: Optional[str] = None
):
"""
初始化邮件通知器
Args:
smtp_server: SMTP服务器
smtp_port: SMTP端口
username: 用户名
password: 密码
from_email: 发件人邮箱
to_email: 收件人邮箱
"""
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.username = username
self.password = password
self.from_email = from_email
self.to_email = to_email
self.enabled = self._check_enabled()
def _check_enabled(self) -> bool:
"""检查是否配置完整"""
return all([
self.smtp_server,
self.smtp_port,
self.username,
self.password,
self.from_email,
self.to_email
])
def is_enabled(self) -> bool:
"""检查是否启用"""
return self.enabled
def send(self, title: str, message: str) -> bool:
"""发送邮件通知"""
if not self.is_enabled():
return False
try:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
msg = MIMEMultipart()
msg['From'] = self.from_email
msg['To'] = self.to_email
msg['Subject'] = title
msg.attach(MIMEText(message, 'plain', 'utf-8'))
with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
server.starttls()
server.login(self.username, self.password)
server.send_message(msg)
return True
except Exception:
return False
class NotificationManager:
"""通知管理器(组合模式)"""
def __init__(self, notifiers: Optional[List[Notifier]] = None):
"""
初始化通知管理器
Args:
notifiers: 通知器列表
"""
self.notifiers: List[Notifier] = notifiers or []
def add_notifier(self, notifier: Notifier) -> None:
"""
添加通知器
Args:
notifier: 通知器实例
"""
self.notifiers.append(notifier)
def remove_notifier(self, notifier: Notifier) -> None:
"""
移除通知器
Args:
notifier: 通知器实例
"""
if notifier in self.notifiers:
self.notifiers.remove(notifier)
def notify(self, title: str, message: str) -> int:
"""
发送通知到所有通知器
Args:
title: 通知标题
message: 通知内容
Returns:
成功发送的通知器数量
"""
success_count = 0
for notifier in self.notifiers:
if notifier.send(title, message):
success_count += 1
return success_count
def notify_connection_lost(self, ip: str, duration: float) -> None:
"""
通知连接丢失
Args:
ip: IP地址
duration: 持续时间(秒)
"""
self.notify(
"网络连接丢失",
f"无法连接到 {ip}\n已断开 {duration:.1f} 秒"
)
def notify_shutdown(self, reason: str) -> None:
"""
通知系统即将关机
Args:
reason: 关机原因
"""
self.notify(
"系统即将关机",
f"原因: {reason}\n请保存所有工作!"
)
class NotificationBuilder:
"""通知构建器(建造者模式)"""
def __init__(self):
"""初始化构建器"""
self._enable_console = True
self._enable_desktop = False
self._enable_email = False
self._email_config: dict = {}
def enable_console(self, enable: bool = True) -> 'NotificationBuilder':
"""
启用控制台通知
Args:
enable: 是否启用
Returns:
构建器实例
"""
self._enable_console = enable
return self
def enable_desktop(self, enable: bool = True) -> 'NotificationBuilder':
"""
启用桌面通知
Args:
enable: 是否启用
Returns:
构建器实例
"""
self._enable_desktop = enable
return self
def enable_email(self, **config) -> 'NotificationBuilder':
"""
启用邮件通知
Args:
**config: 邮件配置
Returns:
构建器实例
"""
self._enable_email = True
self._email_config = config
return self
def build(self) -> NotificationManager:
"""
构建通知管理器
Returns:
通知管理器实例
"""
notifiers = []
if self._enable_console:
notifiers.append(ConsoleNotifier())
if self._enable_desktop:
notifiers.append(DesktopNotifier())
if self._enable_email:
notifiers.append(EmailNotifier(**self._email_config))
return NotificationManager(notifiers)