分类: 编码

  • 几行搞定 WordPress 邮件发送

    要通过代码方式在 WordPress 中配置 SMTP,而无需使用插件,您可以通过修改 wp-config.php 文件并添加一些代码来实现。以下是详细步骤:

    1. 打开 wp-config.php 文件

    在您的 WordPress 根目录下找到 wp-config.php 文件,使用文本编辑器打开。

    2. 添加 SMTP 配置代码

    wp-config.php 文件中,添加以下代码来配置 SMTP 设置:

    // SMTP Configuration
    define('WP_MAIL_SMTP_HOST', 'smtp.example.com');  // SMTP server address
    define('WP_MAIL_SMTP_PORT', 587);                 // SMTP port number
    define('WP_MAIL_SMTP_USERNAME', '[email protected]');  // SMTP username
    define('WP_MAIL_SMTP_PASSWORD', 'your-email-password');     // SMTP password
    define('WP_MAIL_SMTP_FROM', '[email protected]');      // Sender email
    define('WP_MAIL_SMTP_FROM_NAME', 'Your Name');              // Sender name
    define('WP_MAIL_SMTP_SECURE', 'tls');                       // Encryption method, use 'tls' or 'ssl'
    define('WP_MAIL_SMTP_AUTH', true);                          // Whether to enable authentication

    3. 使用 phpmailer 配置 SMTP

    在主题的 functions.php 文件中添加以下代码来启用 SMTP 配置:

    // SMTP Configuration
    add_action( 'phpmailer_init', 'custom_phpmailer_init' );
    
    function custom_phpmailer_init( $phpmailer ) {
        $phpmailer->isSMTP();
        $phpmailer->Host = WP_MAIL_SMTP_HOST;
        $phpmailer->SMTPAuth = WP_MAIL_SMTP_AUTH;
        $phpmailer->Port = WP_MAIL_SMTP_PORT;
        $phpmailer->Username = WP_MAIL_SMTP_USERNAME;
        $phpmailer->Password = WP_MAIL_SMTP_PASSWORD;
        $phpmailer->From = WP_MAIL_SMTP_FROM;
        $phpmailer->FromName = WP_MAIL_SMTP_FROM_NAME;
        $phpmailer->SMTPSecure = WP_MAIL_SMTP_SECURE;
    }

    4. 保存文件并测试

    • 保存 wp-config.phpfunctions.php 文件。

    这将配置 WordPress 使用指定的 SMTP 服务器发送电子邮件,而不需要使用插件。

  • WordPress代码高亮无需插件快速实现

    在 WordPress 中使用 Prism.js 实现代码高亮

    Prism.js 是一个轻量级、可扩展的代码语法高亮显示工具。通过将 Prism.js 集成到您的 WordPress 主题中,可以轻松地为博客文章中的代码片段添加漂亮的语法高亮。

    我们的目标是利用 WordPress 古腾堡编辑器内置的“代码”区块,并结合 Prism.js 这个轻量级的代码高亮库,通过 CDN 方式加载,从而实现快速且无需插件的代码高亮效果。

    步骤 1:编辑主题的 functions.php 文件

    1. 编辑到您当前使用的主题目录,通常位于 wp-content/themes/your-theme-name/
    2. 找到 functions.php 文件并使用文本编辑器打开它。

    步骤 2:添加 Prism.js 代码

    将以下代码片段复制并粘贴到 functions.php 文件中

    // Code highlighting
    function enqueue_prism_cdn() {
        $prism_version = '1.29.0';
        $cdn = 'https://cdnjs.cloudflare.com/ajax/libs/prism/' . $prism_version;
        $theme_css = $cdn . '/themes/prism-okaidia.min.css';
        $line_numbers_css = $cdn . '/plugins/line-numbers/prism-line-numbers.min.css';
        $prism_js = $cdn . '/prism.min.js';
        $line_numbers_js = $cdn . '/plugins/line-numbers/prism-line-numbers.min.js';
        $bash_js = $cdn . '/components/prism-bash.min.js';
        $custom_css = 'pre.line-numbers, pre { background: #2d2d2d; padding: 1em; overflow: auto; border-radius: 4px; color: #f8f8f2; } pre.line-numbers { position: relative; padding-left: 3.8em; } code { background: none !important; padding: 0 !important; }';
        $custom_js = 'document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll("pre:not(.line-numbers)").forEach(pre => { pre.classList.add("line-numbers"); const code = pre.querySelector("code:not([class*=\'language-\'])"); if (code) code.classList.add("language-bash"); }); if (typeof Prism !== "undefined") Prism.highlightAll(); });';
        wp_enqueue_style('prism-css', $theme_css);
        wp_enqueue_style('prism-line-numbers-css', $line_numbers_css);
        wp_enqueue_script('prism-js', $prism_js, [], $prism_version, true);
        wp_enqueue_script('prism-line-numbers-js', $line_numbers_js, ['prism-js'], $prism_version, true);
        wp_enqueue_script('prism-bash', $bash_js, ['prism-js'], $prism_version, true);
        wp_add_inline_style('prism-css', $custom_css);
        wp_add_inline_script('prism-js', $custom_js);
    }
    add_action('wp_enqueue_scripts', 'enqueue_prism_cdn');

    步骤 3:保存 functions.php 文件

    • 保存对 functions.php 文件的更改。

    如何使用

    1. 在WordPress古腾堡编辑器中,添加“代码”区块。
    2. 在代码区块中,输入您的代码。
    3. 保存文章或页面,查看效果。

  • Visual Studio Code配置Ollama


    1. 安装Ollama

    1.1 下载Ollama

    https://ollama.com/
    

    1.2 使用终端下载模型

    ollama pull gemma2:9b   
    ollama pull llama3.1:8b
    ollama pull llama3.2:3b
    ollama pull qwen2.5:7b
    ollama pull qwen2.5:3b
    ollama pull gemma2:2b
    

    2. 安装Visual Studio Code

    2.1 下载Visual Studio Code

    https://code.visualstudio.com/
    

    2.2.Visual Studio Code安装Continue 插件

    2.3 配置插件config

    {
      "models": [
        {
          "title": "Llama 3.1 8B",
          "provider": "ollama",
          "model": "llama3.1:8b"
        },
        {
          "title": "llama3.2:3b",
          "provider": "ollama",
          "model": "llama3.2:3b"
        },
        {
          "title": "qwen2.5:7b",
          "provider": "ollama",
          "model": "qwen2.5:7b"
        },
        {
          "title": "qwen2.5:3b",
          "provider": "ollama",
          "model": "qwen2.5:3b"
        },
        {
          "title": "gemma2:2b",
          "provider": "ollama",
          "model": "gemma2:2b"
        },
        {
          "title": "gemma2:9b",
          "provider": "ollama",
          "model": "gemma2:9b"
        },
      ],
      "customCommands": [
        {
          "name": "test",
          "prompt": "{{{ input }}}\n\nWrite a comprehensive set of unit tests for the selected code. It should setup, run tests that check for correctness including important edge cases, and teardown. Ensure that the tests are complete and sophisticated. Give the tests just as chat output, don't edit any file.",
          "description": "Write unit tests for highlighted code"
        }
      ],
      "contextProviders": [
        {
          "name": "code",
          "params": {}
        },
        {
          "name": "docs",
          "params": {}
        },
        {
          "name": "diff",
          "params": {}
        },
        {
          "name": "terminal",
          "params": {}
        },
        {
          "name": "problems",
          "params": {}
        },
        {
          "name": "folder",
          "params": {}
        },
        {
          "name": "codebase",
          "params": {}
        }
      ],
      "slashCommands": [
        {
          "name": "edit",
          "description": "Edit selected code"
        },
        {
          "name": "comment",
          "description": "Write comments for the selected code"
        },
        {
          "name": "share",
          "description": "Export the current chat session to markdown"
        },
        {
          "name": "cmd",
          "description": "Generate a shell command"
        },
        {
          "name": "commit",
          "description": "Generate a git commit message"
        }
      ],
    }
  • Web日志分析工具

    1. Web日志分析工具

    一年前,我写了一个Web日志进行分析并按照分类导出到Excel的工具
    一年后,我在AI的加持帮助下对这个工具代码进行了重构
    通过Web页面的方式进行呈现,支持了更多的日志解析,更灵活的使用

    2. 为什么要重构这个工具

    想法

    1. 日志分析的过程中总会遇到性能瓶颈和查找指定相关数据的瓶颈,最终只需要日志中的部分数据,只需要一个小工具获取想要的结果就可以了,暂时不考虑重量级产品全流量匹配
    2. 会遇到跨平台代码处理的问题,既然都跨平台了直接搞个Web版本更直观
    3. 无论是流量匹配还是日志匹配,归根结底还是通过正则表达式的方式去做,随着AI时代的猛烈迭代,我尝试使用AI去编码看看能否给我一个其它的处理数据的方式,尝试了不同的AI产品,例如LLAMA3,ChatGPT,Gemini等相关AI产品,最终的结论依旧是通过正则表达式的方式匹配
    4. 既然使用正则表达式的方式,我依旧在想能不能搞个自动匹配的方式实现,只需要上传日志脚本自动分析匹配最后输出结果,但事实是其实电脑也同样看不懂猜不出来日志中的每个字段究竟是什么,希望未来的AI可以猜出来人类想要什么,哪怕是给个选项!
    5. 在可以输出结果的同时顺便统计出次数数量方便进行统计工作,开始打算使用图表的方式去做最终没做,无法适配不同的图表不如给出输出的数据自己用其它的工具去做,这样更灵活
    6. 在第一版的Web日志分析工具中,输出的是Excel格式,这次直接被我取消了
      1. 原因1:Excel文件需要依赖Microsoft Excel或其他兼容工具
      2. 原因2:Excel在处理非常大的数据集时可能会变得非常缓慢
      3. 原因3:而如果需要人类易读的格式,并且计划由用户手动操作数据,Excel可能是更方便的选择,但它的处理能力不如CSV和JSON强大
    7. 这次使用的CSV和JSON格式进行输出
      1. CSV格式兼容性更好,几乎所有的数据分析工具、数据库和编程语言都能轻松处理CSV格式。它是一种通用的文本格式,可以在不同平台和工具之间无缝传输
      2. CSV文件结构简单,数据存储在纯文本中,适合快速读取和处理,如果后续有其它工具进行调用的话更方便
      3. 为什么增加了JSON呢,因为简单易懂:JSON采用键值对的形式,结构清晰,容易理解。即使没有专业的编程背景的人也能很快理解JSON的数据结构,JSON跨平台兼容性也不错

    实现过程

    参考了几个框架最终选择的streamlit框架,别问为啥,对我来说无论用什么好用就行

    按照思路:
    第一步上传文件能不能上传成功,日志大小问题
    第二步使用正则匹配日志,能不能匹配上选择的日志,反反复复的找了很多日志去测试,确实非常耗时的
    第三步输出日志,能输出结果就好了,别输出报错或者无法下载就行

    代码量虽然不大但中途改了很多次代码,主要改的都是正则表达式用来匹配日志的,中途反反复复的匹配日志,最终这事儿成了

    中途遇到的困难

    1. 困难还是有的,一年前第一版的Web日志分析工具改正则表达式匹配日志确实挺难的,没想打一年后有AI可以帮我干了,在LLAMA3,ChatGPT,Gemini等相关AI工具的帮助下写正则表达式方便多了,每家AI输出的正则表达式大同小异,不行就多试几次比手写快
    2. 中途大胆的做了些尝试,把我的代码全部交给AI例如LLAMA3,ChatGPT,Gemini等相关AI产品,让AI帮我修改全部的代码重构去实现最初的想法只需要上传日志脚本自动分析匹配最后输出结果,但结果是不行,等以后有其它的方式可以做到我在升级V3版本的Web日志分析工具吧,目前确实不太好做
    3. 既然没办法实现全自动的方式,最终把Apache、Nginx、IIS和Tomcat常用的日志格式进行正则表达式进行匹配,不像V1版本一样只处理Nginx日志
    4. 希望未来的AI工具更好用,以后有条件了一定搞个全自动的,因为目前增加新的日志格式的话还是要增加正则的规则,我不想改正则了。

    未来的计划(还没实现)

    1. 上传日志,脚本全自动分析匹配,输出结果
    2. 上传日志,解析全部日志字段,手动打类型标签,输出结果

    3. 功能介绍

    1. 支持多种日志格式:支持Apache、Nginx、IIS和Tomcat日志格式。
    2. 自动识别日志格式:自动识别日志格式,无需手动配置。
    3. 高效分析:快速分析大型日志文件,获取有关网站访问量、用户行为和系统性能的详细信息。
    4. 灵活筛选:支持多种筛选条件,例如日期范围、请求方法、请求URL等。
    5. 详细统计:支持多种统计条件,例如请求方法、请求URL、状态码等。
    6. 导出文件:支持导出CSV和JSON文件,方便进一步分析和处理。

    4. 项目地址

    以下是完成的Python代码

    # Author: liqixin
    # Mail: [email protected]
    # Web: https://www.qixinlee.com
    
    import streamlit as st
    import pandas as pd
    import json
    import logging
    import os
    import re
    from datetime import datetime
    from typing import List, Dict
    
    # 设置日志级别和格式
    logging.basicConfig(filename='log.log', format='%(asctime)s - %(levelname)s - %(message)s', level=logging.INFO)
    
    # 定义日志解析器的基类
    class LogParser:
        def __init__(self, log_file: bytes):
            self.log_file = log_file
    
        def _parse_log(self, log_pattern: re.Pattern) -> List[Dict]:
            parsed_log_entries = []
            for line in self.log_file:
                line = line.decode('utf-8')
                match = log_pattern.findall(line)
                if match:
                    for match_item in match:
                        request = match_item[3]
                        request_parts = request.split(' ', 2)
                        if len(request_parts) == 3:
                            request_method, request_url, http_protocol = request_parts
                        else:
                            request_method = request_parts[0]
                            request_url = ''
                            http_protocol = ''
                        parsed_log_entries.append({
                            'remote_addr': match_item[0],
                            'remote_user': match_item[1],
                            'time_local': match_item[2],
                            'request_method': request_method,
                            'request_url': request_url,
                            'http_protocol': http_protocol,
                            'status': match_item[4],
                            'body_bytes_sent': match_item[5],
                            'http_referer': match_item[6],
                            'http_user_agent': match_item[7]
                        })
            return parsed_log_entries
    
        def parse(self) -> List[Dict]:
            raise NotImplementedError("必须实现解析方法")
    
    # Apache 日志解析器
    class ApacheLogParser(LogParser):
        def parse(self) -> List[Dict]:
            log_pattern = re.compile(r'(\S+) - (\S+) \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"', re.DOTALL)
            return self._parse_log(log_pattern)
    
    # Nginx 日志解析器
    class NginxLogParser(LogParser):
        def parse(self) -> List[Dict]:
            log_pattern = re.compile(r'(\S+) - - \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"', re.DOTALL)
            return self._parse_log(log_pattern)
    
    # IIS 日志解析器
    class IISLogParser(LogParser):
        def parse(self) -> List[Dict]:
            log_pattern = re.compile(r'(\S+) (\S+) (\S+) \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"', re.DOTALL)
            return self._parse_log(log_pattern)
    
    # Tomcat 日志解析器
    class TomcatLogParser(LogParser):
        def parse(self) -> List[Dict]:
            log_pattern = re.compile(r'(\S+) (\S+) \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"', re.DOTALL)
            return self._parse_log(log_pattern)
    
    # 通用日志解析方法
    class LogParserFactory:
        @staticmethod
        def create_parser(log_type: str, log_file: bytes) -> LogParser:
            if log_type == 'Apache':
                return ApacheLogParser(log_file)
            elif log_type == 'Nginx':
                return NginxLogParser(log_file)
            elif log_type == 'IIS':
                return IISLogParser(log_file)
            elif log_type == 'Tomcat':
                return TomcatLogParser(log_file)
            else:
                raise ValueError(f"不支持的日志类型: {log_type}")
    
    # 定义导出文件函数
    def export_file(df: pd.DataFrame, export_format: str) -> str:
        try:
            current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
            if export_format == 'CSV(逗号分隔值)':
                csv_file_path = f'log_entries_{current_time}.csv'
                df.to_csv(csv_file_path, index=False)
                return csv_file_path
            elif export_format == 'JSON(JavaScript对象表示法)':
                json_file_path = f'log_entries_{current_time}.json'
                df['time_local'] = df['time_local'].apply(lambda x: x.isoformat())
                df['date'] = df['date'].apply(lambda x: x.isoformat())
                with open(json_file_path, 'w', encoding='utf-8') as json_file:
                    json.dump(df.to_dict(orient='records'), json_file, indent=4)
                return json_file_path
        except Exception as e:
            logging.error(f"导出文件失败:{e}")
            raise
    
    # 定义Web应用程序
    def main():
        # 设置主题
        st.set_page_config(layout="wide", page_title="安全运营 - Web日志分析工具")
        st.markdown("<style>body {background-color: #2F4F4F; color: #66D9EF;}</style>", unsafe_allow_html=True)
        st.markdown("<h1 style='text-align: center;'>安全运营 - Web日志分析工具</h1>", unsafe_allow_html=True)
    
        # 上传日志文件
        st.subheader('请选择日志文件')
        log_file = st.file_uploader('请选择日志文件', type=['log'])
        log_type = st.selectbox("请选择日志类型", ['Apache', 'Nginx', 'IIS', 'Tomcat'])
    
        if log_file is not None:
            try:
                # 使用工厂模式创建适当的日志解析器
                log_parser = LogParserFactory.create_parser(log_type, log_file)
                parsed_log_entries = log_parser.parse()
    
                if parsed_log_entries:
                    # 日志解析结果
                    st.subheader('日志解析结果')
                    df = pd.DataFrame(parsed_log_entries)
                    df['time_local'] = df['time_local'].apply(lambda x: datetime.strptime(x, '%d/%b/%Y:%H:%M:%S %z'))
                    df['date'] = df['time_local'].dt.date
                    st.write(df)
    
                    # 选择日期范围
                    st.subheader('请选择日期范围')
                    col1, col2 = st.columns(2)
                    start_date = col1.date_input('请选择开始日期')
                    end_date = col2.date_input('请选择结束日期')
                    filtered_df = df[(df['time_local'].dt.date >= start_date) & 
                                     (df['time_local'].dt.date <= end_date)]
    
                    # 筛选功能
                    st.subheader('筛选功能')
                    st.subheader('请选择筛选条件')
                    columns = filtered_df.columns.tolist()
                    select_columns = st.multiselect('请选择筛选字段', columns)
                    select_values = {}
                    for column in select_columns:
                        if column == 'date':
                            select_values[column] = st.date_input(f'请选择{column}值')
                        else:
                            select_values[column] = st.selectbox(f'请选择{column}值', filtered_df[column].unique())
                    filtered_df = filtered_df
                    for column, value in select_values.items():
                        if column == 'date':
                            filtered_df = filtered_df[filtered_df[column] == value]
                        else:
                            filtered_df = filtered_df[filtered_df[column] == value]
    
                    st.write(filtered_df)
    
                    # 统计功能
                    st.subheader('统计功能')
                    rank_columns = filtered_df.columns.tolist()
                    rank_columns_selected = st.multiselect('请选择统计字段', rank_columns)
    
                    if rank_columns_selected:
                        for i, column in enumerate(rank_columns_selected):
                            rank_df = filtered_df[column].value_counts().reset_index()
                            rank_df.columns = [column, '次数']
                            
                            if i % 2 == 0:
                                col1, col2 = st.columns(2)
                                col1.write(rank_df)
                            else:
                                col2.write(rank_df)
                    else:
                        st.write("请选择至少一个字段")
                    
                    # 导出文件功能
                    st.subheader('请选择导出格式')
                    export_format = st.selectbox('请选择导出格式', ['CSV(逗号分隔值)', 'JSON(JavaScript对象表示法)'])
                    if export_format:
                        file_path = export_file(filtered_df, export_format)
                        with open(file_path, 'rb') as file:
                            if export_format == 'CSV(逗号分隔值)':
                                st.download_button('下载CSV文件', file, file_path.split('/')[-1])
                            elif export_format == 'JSON(JavaScript对象表示法)':
                                st.download_button('下载JSON文件', file, file_path.split('/')[-1])
    
                else:
                    st.error('没有匹配的日志条目')
            except Exception as e:
                st.error(f"错误:{e}")
    
    if __name__ == '__main__':
        main()
  • WOL 主机唤醒工具

    1. 我为什么要写WOL 唤醒工具

    答案:是为了省电(是为了环保)

    2. MarsCode是什么?

    MarsCode对话框官方回答:MarsCode是一个在线的集成开发环境(IDE),它专注于提供一个高效、便捷的编程环境,特别是在教育领域。MarsCode支持多种编程语言,包括Python、Java、C++等,并且提供了实时的代码编辑、调试和运行功能。

    MarsCode的特点包括:

    1. 实时协作:支持多人实时协作编程,适用于团队项目或教学场景。
    2. 代码自动补全:提供智能的代码自动补全功能,帮助开发者提高编码效率。
    3. 语法高亮:支持多种编程语言的语法高亮,使代码更加易读。
    4. 调试工具:内置调试工具,方便开发者进行代码调试。
    5. 版本控制:集成了Git版本控制系统,方便管理代码版本。
    6. 云端存储:所有代码和项目都存储在云端,用户可以随时随地访问和编辑。

    MarsCode的目标是为开发者和学习者提供一个简单、易用且功能强大的编程环境,帮助他们更高效地编写代码。

    3. 为什么要使用这个工具

    写这个代码的起因是前段时间参加字节跳动豆包MarsCode活动
    既然参加了活动,我觉得我还是要体验一下产品,使用产品要做点什么的

    4. 项目需求

    对于使用远程桌面工具经常连接回家的我来说,日常电脑正常开机跑编译或是本地跑AI等情景挺多的,但也有很多闲置的时候

    因此做了一个主机唤醒工具方便在不使用电脑的时候关闭电脑,在需要的时候通过远程唤醒的方式打开电脑让电脑起飞

    在豆包MarsCode的帮助下,提供需求和多次改进终于把代码写好啦

    多了一次使用AI编程的实战

    5. 实现方法

    1. 注册一个MarsCode账号
    2. 进入工作台
    3. 可以在本地IDE中集成,或者直接使用云端网页版
    4. 创建一个项目
    5. 把你的想法告诉MarsCode,开启代码创作之旅
    6. 不停的更改你的需求,让MarsCode输出代码
    7. 在本地搭建好环境运行就好啦
    8. 在多次代码的输出下这事儿成啦,可以啦

    6. 总结

    在使用MarsCode时候,在提需求的时候AI会输出代码(你说啥我输出啥只要快就好)
    不停的进行改改改,对于新手小白来说充满了新奇和在不会编程的同时更容易去实现写代码的功能
    刚开始输出的时候的确给了可以用的功能,但不太满意,需要继续提需求达到满意(再一次想起了我的甲方爸爸),我会在提供可用功能的同时继续提供给MarsCode代码让他继续优化,这样的结果会更完美,功夫不负有心人,终于搞定了

    7. 项目地址

    以下是完成的Python代码

    # Author: liqixin
    # Mail: [email protected]
    # Web: https://www.qixinlee.com
    
    import streamlit as st
    import wakeonlan
    
    # 设置页面标题
    st.title("WOL 唤醒工具")
    
    # 预设的常用主机MAC地址列表
    common_mac_addresses = {
        "Host 1": "00:11:22:33:44:55",
        "Host 2": "AA:BB:CC:DD:EE:FF",
        "Host 3": "11:22:33:44:55:66"
    }
    
    # 在页面上添加下拉框,用于选择目标主机
    selected_host = st.selectbox("请选择要唤醒的主机:", list(common_mac_addresses.keys()))
    
    # 在页面上添加文本输入框,用于输入自定义主机MAC地址
    custom_mac_address = st.text_input("或者输入自定义主机MAC地址:")
    
    # 使用st.empty()创建一个占位符,用于在条件满足时显示警告信息
    warning_placeholder = st.empty()
    
    # 在页面上添加一个按钮,用于发送魔法包
    if st.button("唤醒主机"):
        # 检查 MAC 地址是否为空
        if not custom_mac_address and not selected_host:
            # 在占位符中显示警告信息
            warning_placeholder.warning("请选择要唤醒的主机或输入自定义主机MAC地址。")
        else:
            # 发送魔法包
            if custom_mac_address:
                wakeonlan.send_magic_packet(custom_mac_address)
                st.success(f"已发送魔法包到 {custom_mac_address},尝试唤醒主机。")
            else:
                mac_address = common_mac_addresses[selected_host]
                wakeonlan.send_magic_packet(mac_address)
                st.success(f"已发送魔法包到 {mac_address},尝试唤醒主机。")