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目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/878869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vscode中如何配置c/c++环境

“批判他人总是想的太简单 剖析自己总是想的太困难” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;一、准备工作二、安装 VSCode 插件三、配置 VSCode1. 配置编译任务&#xff08;tasks.json&#xff09;2. 配置调试器&#xff08;launch.json&#xff09; 四、运行和调…

数据结构(Day14)

一、学习内容 结构体 概念 引入&#xff1a;定义整数赋值为10 int a10; 定义小数赋值为3.14 float b3.14; 定义5个整数并赋值 int arr[5] {1 , 2 , 3 , 4 ,5}; 定义一个学生并赋值学号姓名成绩 定义一个雪糕并赋值名称产地单价 问题&#xff1a;没有学生、雪糕 数据类型 解决&…

【C/C++】程序的构建(编译)过程概述

&#x1f984;个人主页:小米里的大麦-CSDN博客 &#x1f38f;所属专栏:C_小米里的大麦的博客-CSDN博客 &#x1f381;代码托管:C: 探索C编程精髓&#xff0c;打造高效代码仓库 (gitee.com) ⚙️操作环境:Visual Studio 2022 目录 一、前言 二、预处理&#xff08;Preprocessi…

C# USB通信技术(通过LibUsbDotNet库)

文章目录 1.下载LibusbDotNet库2.引入命名空间3. 实例化USB设备4.发送数据5.关闭连接 1.下载LibusbDotNet库 右击项目选择管理NuGet程序包在弹出的界面中搜索LibusbDotNet&#xff0c;然后下载安装。 2.引入命名空间 using LibUsbDotNet; using LibUsbDotNet.Main;3. 实例化…

MoneyPrinterTurbo 安装使用流程

项目地址&#xff1a; https://github.com/harry0703/MoneyPrinterTurbo 开发环境&#xff1a;mac 1 git 下载 # 下载代码到本地 git clone https://github.com/harry0703/MoneyPrinterTurbo.git cd MoneyPrinterTurbo2 docker 配源 在 docker 安装目录执行以下命令显示隐藏…

《Nginx核心技术》第17章:使用自签CA配置HTTPS加密反向代理访问

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

3.Java高级编程实用类介绍(一)

三、Java高级编程实用类介绍(一) 文章目录 三、Java高级编程实用类介绍(一)一、枚举类型二、包装类三、Math 一、枚举类型 使用enum进行定义 public enum 枚举名字{值1,值2.... }二、包装类 每个基本类型在java.lang包中都有一个相应的包装类 /** new包装类&#xff08;字符…

华硕产品资料的查询方法

华硕网站有些奇怪&#xff0c;比如我要查询x99-pro这款已经停售的主板的资料&#xff0c;在它的首页搜索&#xff0c;搜索结果为空&#xff1a; 然后在服务支持和下载中心&#xff0c;同样搜不到。 经高人指点&#xff0c;用下面的方法&#xff0c;可以搜到&#xff1a; https…

C++ char*和char[] 可能指向的内存区域详解(附实验)

C char* 指向的内存区域详解 写在前面c内存结构简介指针常量和常量指针简介情况一&#xff1a;char* 指向栈区内容情况二&#xff1a;char* 指向堆区内容情况三&#xff1a;char* 指向常量区内容情况四&#xff1a;char* 指向静态区内容情况五&#xff1a;char* 指向全局区内容…

mysql 8.0 时间维度表生成(可运行)

文章目录 mysql 8.0 时间维度表生成实例时间维度表的作用时间维度表生成技术细节使用时间维度表的好处 mysql 8.0 时间维度表生成实例 时间维度表的作用 dim_times&#xff08;时间维度表&#xff09;在数据仓库&#xff08;Data Warehouse&#xff09;中的作用至关重要。作为…

Vite + Electron 时,Electron 渲染空白,静态资源加载错误等问题解决

问题 如果在 electron 里直接引入 vite 打包后的东西&#xff0c;那么有些资源是请求不到的 这是我的引入方式 根据报错&#xff0c;我们来到 vite 打包后的路径看一看 &#xff0c;修改一下 dist 里的文件路径试了一试 修改后的样子&#xff0c;发现是可以的了 原因分析 …

Java-idea小锤子图标

这一版的idea小锤子图标其实就在这里 点进去就找到了~

航空航司reese84逆向

reese84逆向 Reese84 是一种用于保护网站防止自动化爬虫抓取的防护机制&#xff0c;尤其是在航空公司网站等需要严格保护数据的平台上广泛使用。这种机制通过复杂的指纹识别和行为分析技术来检测和阻止非人类的互动。例如&#xff0c;Reese84 可以通过分析访问者的浏览器指纹、…

java技术栈介绍

Java技术栈是一个庞大而丰富的生态系统&#xff0c;它包含了从基础语言特性到高级框架、库和工具的整个集合。这个技术栈为开发者提供了构建各种类型应用&#xff08;包括企业级应用、Web应用、移动应用、大数据应用等&#xff09;所需的全部组件。以下是对Java技术栈的一个更详…

Java 技巧 如何在IDEA2024 中快速打出System.out.println();

1.基本用法 键入sout回车 回车后变成&#xff1a; 2.打印变量 快速打印变量,以打印变量名为set为例&#xff0c;set.sout回车&#xff0c; 回车后变成

YOLOv8 人体姿态估计动作识别关键点检测(代码+教程)

YOLOv8 人体姿态判断 项目介绍 YOLOv8 人体姿态判断 是一个基于最新YOLOv8模型的深度学习项目&#xff0c;旨在识别和分析人体姿态。该项目利用先进的计算机视觉技术和深度学习框架&#xff0c;通过摄像头捕捉实时图像或处理存储图像&#xff0c;识别人体的关键点&#xff0c…

ubuntu服务器版NVIDIA驱动失效解决方案

ubuntu服务器版NVIDIA驱动失效解决方案 1. 问题描述2. 解决方法--卸载并重新安装最新版显卡驱动cudacudnn2.1 卸载显卡驱动2.2 重新安装最新版显卡驱动cudacudnn2.2.1 显卡驱动2.2.2 cuda2.2.3 cuda安装cudnn 1. 问题描述 在终端输入nvidia-smi&#xff0c;输出如下&#xff1…

安全工具 | 使用Burp Suite的10个小tips

Burp Suite 应用程序中有用功能的集合 img Burp Suite 是一款出色的分析工具&#xff0c;用于测试 Web 应用程序和系统的安全漏洞。它有很多很棒的功能可以在渗透测试中使用。您使用它的次数越多&#xff0c;您就越发现它的便利功能。 本文内容是我在测试期间学到并经常的主要…

oracle 使用 PL/SQL Developer创建表并插入单条、多条数据

第一步&#xff1a;使用工具创建表&#xff08;前提是库已经创建好了&#xff09;&#xff1a;在当前用户下找到Tables 然后点击并右键&#xff0c;点击新建 写上表名&#xff0c;写上表名的注释 第二步添加字段&#xff1a;点击列&#xff0c;然后分别写上你自己需要的字段及名…

在线查看 Android 系统源代码 AOSPXRef and AndroidXRef

在线查看 Android 系统源代码 AOSPXRef and AndroidXRef 1. AOSPXRef1.1. http://aospxref.com/android-14.0.0_r2/1.2. build/envsetup.sh 2. AndroidXRef2.1. http://androidxref.com/9.0.0_r3/2.2. build/envsetup.sh 3. HELLO AndroidReferences 1. AOSPXRef http://aospx…