当前位置: 首页 > article >正文

Rust练手项目,写个有趣的小工具定时从一言网获取一段有趣的话并推送通知

Rust练手项目,写个有趣的小工具

    • 代码

继续练习Rust, 写个小工具定时从一言网获取一段有趣的话并提示,如下
图片

练习以下Rust点

  • 并发编程 Mutex, Arc指针使用
  • HTTP请求
  • Windows Gui

代码

Cargo.toml

[package]
name = "funny_word"
edition = "2021"
version.workspace = true
authors.workspace = true
description.workspace = true

[dependencies]
trayicon = "0.2.0"
winapi = { version = "0.3.9", features = [
    "winuser",
    "windef",
    "minwindef",
    "shellapi",
    "libloaderapi",
    "commctrl",
    "basetsd",
] }
win-toast-notify = "0.1.6"
windows = { version = "0.58.0", features = [
    "Win32_Security",
    "Win32_System_Threading",
    "Win32_UI_WindowsAndMessaging",
] }
reqwest = { version = "0.11", features = ["blocking"]  }
[package]
name = "funny_word"
edition = "2021"
version.workspace = true
authors.workspace = true
description.workspace = true

[dependencies]
trayicon = "0.2.0"
winapi = { version = "0.3.9", features = [
    "winuser",
    "windef",
    "minwindef",
    "shellapi",
    "libloaderapi",
    "commctrl",
    "basetsd",
] }
win-toast-notify = "0.1.6"
windows = { version = "0.58.0", features = [
    "Win32_Security",
    "Win32_System_Threading",
    "Win32_UI_WindowsAndMessaging",
] }
reqwest = { version = "0.11", features = ["blocking"]  }

main.rs

#![windows_subsystem = "windows"]
use core::mem::MaybeUninit;
use std::{
    sync::{Arc, Mutex},
    thread::sleep,
    time::Duration,
};
use trayicon::*;
use win_toast_notify::WinToastNotify;
use winapi::um::winuser;

fn main() {
    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
    enum Events {
        RightClickTrayIcon,
        LeftClickTrayIcon,
        OneMinute,
        FiveMinute,
        FifteenMinute,
        HalfHour,
        OneHour,
        Exit,
    }

    let (sender, receiver) = std::sync::mpsc::channel::<Events>();
    let icon_bytes = include_bytes!("rust.ico");

    let mut tray_icon = TrayIconBuilder::new()
        .sender(move |e: &Events| {
            let _ = sender.send(*e);
        })
        .icon(Icon::from_buffer(icon_bytes, None, None).unwrap())
        .tooltip("💪没事喝点鸡汤吧!")
        .on_right_click(Events::RightClickTrayIcon)
        .on_click(Events::LeftClickTrayIcon)
        .menu(
            MenuBuilder::new()
                .separator()
                .submenu(
                    "提醒间隔",
                    MenuBuilder::new()
                        .checkable("1分钟", true, Events::OneMinute)
                        .checkable("5分钟", false, Events::FiveMinute)
                        .checkable("15分钟", false, Events::FifteenMinute)
                        .checkable("半小时", false, Events::HalfHour)
                        .checkable("一小时", false, Events::OneHour),
                )
                .separator()
                .item("退出", Events::Exit),
        )
        .build()
        .unwrap();

    let _interval = Arc::new(Mutex::new(1));
    let interval = _interval.clone();
    std::thread::spawn(move || {
        receiver.iter().for_each(|m| match m {
            Events::RightClickTrayIcon => {
                tray_icon.show_menu().unwrap();
            }
            Events::LeftClickTrayIcon => {
                tray_icon.show_menu().unwrap();
            }
            Events::Exit => {
                std::process::exit(0);
            }
            Events::OneMinute => {
                let mut i = interval.lock().unwrap();
                *i = 1;
                tray_icon
                    .set_menu_item_checkable(Events::OneMinute, true)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FiveMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FifteenMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::HalfHour, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::OneHour, false)
                    .unwrap();
            }
            Events::FiveMinute => {
                let mut i = interval.lock().unwrap();
                *i = 5;
                tray_icon
                    .set_menu_item_checkable(Events::OneMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FiveMinute, true)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FifteenMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::HalfHour, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::OneHour, false)
                    .unwrap();
            }
            Events::FifteenMinute => {
                let mut i = interval.lock().unwrap();
                *i = 15;
                tray_icon
                    .set_menu_item_checkable(Events::OneMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FiveMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FifteenMinute, true)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::HalfHour, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::OneHour, false)
                    .unwrap();
            }
            Events::HalfHour => {
                let mut i = interval.lock().unwrap();
                *i = 30;
                tray_icon
                    .set_menu_item_checkable(Events::OneMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FiveMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::FifteenMinute, false)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::HalfHour, true)
                    .unwrap();
                tray_icon
                    .set_menu_item_checkable(Events::OneHour, false)
                    .unwrap();
            }
            Events::OneHour => {
                let mut i = interval.lock().unwrap();
                *i = 60;
                tray_icon.set_menu_item_checkable(Events::OneMinute, false);
                tray_icon.set_menu_item_checkable(Events::FiveMinute, false);
                tray_icon.set_menu_item_checkable(Events::FifteenMinute, false);
                tray_icon.set_menu_item_checkable(Events::HalfHour, false);
                tray_icon.set_menu_item_checkable(Events::OneHour, true);
            }
        })
    });

    std::thread::spawn(move || loop {
        match reqwest::blocking::get("https://v1.hitokoto.cn?&encode=text") {
            Ok(resp) => match resp.text() {
                Ok(text) => {
                    WinToastNotify::new()
                        .set_title("来自一言网")
                        .set_messages(vec![&text])
                        .show()
                        .expect("发送通知失败!");
                }
                Err(e) => {
                    WinToastNotify::new()
                        .set_title("错误")
                        .set_messages(vec![&format!(
                            "HTTP错误 {}",
                            e.status().unwrap_or_default()
                        )])
                        .show()
                        .expect("发送通知失败!");
                }
            },
            Err(e) => {
                WinToastNotify::new()
                    .set_title("获取网站内容失败错误")
                    .set_messages(vec![&format!(
                        "HTTP错误 {}",
                        e.status().unwrap_or_default()
                    )])
                    .show()
                    .expect("发送通知失败!");
            }
        }

        let mut _b = 1;
        {
            // 加个大括号是为了尽快释放lock, 免得睡眠中(60 * (*i))一直占用锁,点击右键菜单无反应
            let interval = _interval.clone();
            let i = interval.lock().unwrap();
            _b = *i;
        }
        sleep(Duration::from_secs(60 * _b));
    });

    loop {
        unsafe {
            let mut msg = MaybeUninit::uninit();
            let bret = winuser::GetMessageA(msg.as_mut_ptr(), 0 as _, 0, 0);
            if bret > 0 {
                winuser::TranslateMessage(msg.as_ptr());
                winuser::DispatchMessageA(msg.as_ptr());
            } else {
                break;
            }
        }
    }
}

rust.ico图标文件放在main.rs目录


http://www.kler.cn/a/307825.html

相关文章:

  • C#从入门到放弃
  • linux上海康SDK安装并设置环境变量
  • 《Django 5 By Example》阅读笔记:p76-p104
  • C++STL容器——map和set
  • HTTP常见的状态码有哪些,都代表什么意思
  • 专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结
  • STM32—I2C
  • OpenAI o1真的那么强吗
  • 天地一体化物联网:挑战与机遇
  • 移动订货小程序哪个好 批发订货系统源码哪个好
  • 【Elasticsearch系列八】高阶使用
  • 您的计算机已被.lcrypt勒索病毒感染?恢复您的数据的方法在这里!
  • 春秋云境靶场之CVE-2022-29464
  • element-plus弹窗内分页表格保留勾选项
  • 大数据-134 - ClickHouse 集群三节点 安装配置启动
  • 【2023年】云计算金砖牛刀小试4
  • 机器学习文献|基于循环细胞因子特征,通过机器学习算法预测NSCLC免疫治疗结局
  • 24.9.16数据结构|平衡二叉树
  • 如何切换淘宝最新镜像源npm
  • C++菜鸟教程 - 从入门到精通 第二节
  • Bxbshsbsh
  • 联合条件概率 以及在语言模型中的应用
  • 2、vectorCast集成测试常用功能
  • Flask中的蓝图如何进行模块化
  • ELK在Linux服务器下使用docker快速部署(超详细)
  • 苍穹外卖 修改nginx的端口后websocket连接失败解决