# Source: https://github.com/3ixi/CodeScripts/blob/main/SendNotify.py
# Raw: https://raw.githubusercontent.com/3ixi/CodeScripts/main/SendNotify.py
# Repo: 3ixi/CodeScripts
# Path: SendNotify.py
# UploadedAt: 2025-09-23T14:07:43+08:00
# SHA256: 81becf638236ec4140dce7f3bcbcc2c46c1108bf5b5dcea6bc2bde763482d06c
# Category: APP版/抓包
# Evidence: APP/Android/iOS/device关键词

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
通知模块 - 仅用于捕获脚本输出并转发给notify.py
创建日期：2025-09-17
模块作者：3iXi
项目主页：https://github.com/3ixi/CloudScripts
使用方法：访问青龙面板，打开“配置文件”页面，从44行开始，找到自己想要使用的推送方式，在双引号中填入对应的配置，脚本运行结束后会自动发送通知。
"""

import os
import sys
from datetime import datetime

# ==================== notify.py 集成 ====================
NOTIFY_PATHS = ['./notify.py', '../notify.py']
HAS_NOTIFY = False
notify_send = None

for path in NOTIFY_PATHS:
    if os.path.exists(path):
        try:
            sys.path.append(os.path.dirname(os.path.abspath(path)))
            from notify import send as notify_send
            HAS_NOTIFY = True
            break
        except ImportError:
            continue

if not HAS_NOTIFY:
    print("⚠️ 未找到青龙自带通知模块，请确保notify.py文件存在于当前目录或上级目录中")
    print("   访问青龙面板，打开“配置文件”页面，从44行开始，找到自己想要使用的推送方式，在双引号中填入对应的配置")

# ==================== 输出捕获类 ====================
class OutputCapture:
    
    def __init__(self):
        self.content = []
        self.original_stdout = sys.stdout
        self.capture_enabled = False
    
    def start_capture(self):
        if not self.capture_enabled:
            self.capture_enabled = True
            sys.stdout = self._DualOutput(self.original_stdout, self)
    
    def stop_capture(self):
        if self.capture_enabled:
            sys.stdout = self.original_stdout
            self.capture_enabled = False
    
    def add_content(self, content):
        if content:
            self.content.append(str(content))
    
    def get_content(self):
        return "\n".join(self.content)
    
    def clear(self):
        self.content.clear()
    
    def __enter__(self):
        self.start_capture()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop_capture()
    
    class _DualOutput:
        
        def __init__(self, original_stdout, capture_instance):
            self.original_stdout = original_stdout
            self.capture_instance = capture_instance
        
        def write(self, text):
            self.original_stdout.write(text)
            if text.strip():
                self.capture_instance.add_content(text.strip())
        
        def flush(self):
            self.original_stdout.flush()
        
        def __getattr__(self, name):
            return getattr(self.original_stdout, name)

_global_output_capture = OutputCapture()

def capture_output(title="脚本运行结果"):
    def decorator(func):
        def wrapper(*args, **kwargs):
            global _global_output_capture
            
            _global_output_capture.clear()
            _global_output_capture.start_capture()
            
            try:
                result = func(*args, **kwargs)
                return result
            except Exception as e:
                _global_output_capture.add_content(f"❌ 脚本运行错误: {e}")
                raise
            finally:
                _global_output_capture.stop_capture()
                
                captured_content = _global_output_capture.get_content()
                if captured_content:
                    SendNotify(title, captured_content)
        
        return wrapper
    return decorator


def start_capture():
    global _global_output_capture
    _global_output_capture.clear()
    _global_output_capture.start_capture()


def stop_capture_and_notify(title="脚本运行结果"):
    global _global_output_capture
    _global_output_capture.stop_capture()
    
    captured_content = _global_output_capture.get_content()
    if captured_content:
        SendNotify(title, captured_content)


def add_to_capture(content):
    global _global_output_capture
    _global_output_capture.add_content(content)


class NotificationSender:
    def __init__(self):
        pass

    def _truncate_title(self, content: str, max_length: int = 30) -> str:
        if not content:
            return "3iXi云函数脚本通知"
        
        title = content.replace('\n', ' ').replace('\r', ' ').strip()
        if len(title) > max_length:
            title = title[:max_length] + "..."
        
        return title or "3iXi云函数脚本通知"

    def _get_current_time(self) -> str:
        return datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    def send_notification(self, title: str = "", content: str = "") -> bool:
        if not content:
            print("⚠️ 通知内容为空，跳过推送")
            return False
        
        if not title:
            title = self._truncate_title(content)
        
        timestamp = self._get_current_time()
        content = f"发送时间: {timestamp}\n\n{content}"
        
        if HAS_NOTIFY and notify_send:
            try:
                notify_send(title, content)
                print("✅ 通知已通过notify.py发送")
                return True
            except Exception as e:
                print(f"❌ 通过notify.py发送通知失败: {e}")
                return False
        else:
            print("⚠️ 未找到notify.py模块，无法发送通知")
            print("   请确保notify.py文件存在于当前目录或上级目录中")
            print("   访问青龙面板，打开“配置文件”页面，找到自己想要使用的推送方式填入对应的配置")
            return False


_notification_sender = None

def SendNotify(title: str = "", content: str = "") -> bool:
    global _notification_sender
    
    if _notification_sender is None:
        _notification_sender = NotificationSender()
    
    return _notification_sender.send_notification(title, content)


# ==================== 测试代码 ====================
if __name__ == "__main__":
    print("📱 SendNotify通知模块测试")
    print("=" * 30)
    
    # 测试通知
    test_title = "SendNotify测试通知"
    test_content = """这是一条测试通知消息。

测试内容包括：
✅ 通知模块正常工作
📱 仅通过notify.py推送功能测试成功

如果您收到此消息，说明通知配置正确"""
    
    result = SendNotify(test_title, test_content)
    
    if result:
        print("✅ 测试完成，通知发送成功")
    else:
        print("❌ 测试完成，但通知发送失败")