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

news2024/11/16 2:26:05

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.coloradmin.cn/o/2142455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv8目标检测模型——遥感小目标检测经验分享

小目标检测——YOLOV8 一、引言 背景介绍 &#xff08;1&#xff09;目标检测的重要性 目标检测在许多领域都具有极其重要的作用。在自动驾驶中&#xff0c;目标检测能够识别道路上的障碍物和行人&#xff0c;确保行车安全。在视频监控中&#xff0c;目标检测能够实时发现异…

【matlab】生成 GIF 的函数(已封装可直接调用)

文章目录 前言一、函数输入与输出二、函数代码三、例程&#xff08;可直接运行&#xff09;参考文献 前言 生成 gif 图片时遇到的问题&#xff0c;为了后续调用方便&#xff0c;封装为函数 一、函数输入与输出 输入&#xff1a; cell_figure: cell 数组&#xff0c;数组元素是…

Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用增强版

前言 之前使用Chainlit集成LlamaIndex并使用通义千问大语言模型的API接口&#xff0c;实现一个基于文档文档的网页对话应用。 可以点击我的上一篇文章《Chainlit集成LlamaIndex并使用通义千问模型实现AI知识库检索网页对话应用》 查看。 本次针对上一次的代码功能进一步的完善…

Cursor与Copilot:编程界的双雄对决

引子 在技术快速发展的当下&#xff0c;编程几乎成为了现代社会的基础能力。Cursor与Copilot作为当前备受瞩目的编程助手&#xff0c;各自展现出了独特的魅力。它们不仅改变了程序员的工作方式&#xff0c;更是提升了代码编写的效率&#xff0c;成为了编程界的“双雄”。 Curs…

软件安全、逆向分析、加密与解密--crackme2详解

本次使用到的软件有&#xff1a;PEiD、IDA、X32dbg 刚学逆向不久&#xff0c;可能有些地方会有错误&#xff0c;欢迎各位大佬指导 执行 运行程序 点击About 点击确定&#xff0c;输入如图数据 点击try Now 点击确定&#xff0c;回到主界面 点击Exit&#xff0c;退出 查壳&a…

Docker:SpringBoot项目创建Docker镜像并推送到阿里云容器镜像仓库

0. 准备工作 os&#xff1a;macos 15.0 jdk&#xff1a;1.8 docker&#xff1a;26.0.0 1. 阿里云容器镜像服务创建实例 创建个人版 个人实例创建成功 个人镜像加速器地址 2. 安装Docker Desktop Docker Desktop是Docker的一个集成工具&#xff0c;非必须&#xff0c;过程…

指纹与指甲检测系统源码分享

指纹与指甲检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

这个时代唯一“不变“的又是{变}

这个时代唯一不变的就是“变”&#xff0c;所以每个人都得有规划意识&#xff0c;首先要对自己的价值有清晰的认知&#xff0c;你核心卖点是什么。第二&#xff0c;你取得的成绩是通过平台成就的还是通过自身努力取得的&#xff0c;很多人在一家平台待久了之后&#xff0c;身上…

在Unity UI中实现UILineRenderer组件绘制线条

背景介绍 在Unity的UI系统中&#xff0c;绘制线条并不像在3D世界中那样直观(使用Unity自带的LineRender组件在UI中连线并不方便,它在三维中更合适)。没有内置的工具来处理这种需求。如果你希望在UI元素之间绘制连接线&#xff08;例如在UI上连接不同的图标或控件&#xff09;&a…

26. 构建一个矩形平面几何体

定义矩形几何体顶点坐标 一个矩形平面&#xff0c;可以至少通过两个三角形拼接而成。而且两个三角形有两个顶点的坐标是重合的。 注意三角形的正反面问题&#xff1a;保证矩形平面两个三角形的正面是一样的&#xff0c;也就是从一个方向观察&#xff0c;两个三角形都是逆时针…

Docker 消息队列RabbitMQ 安装延迟消息插件

介绍 RabbitMQ的官方推出了一个插件&#xff0c;原生支持延迟消息功能。该插件的原理是设计了一种支持延迟消息功能的交换机。当消息投递到交换机后可以暂存一定时间&#xff0c;到期后再投递到队列。 查看版本号 docker exec rabbit名字 rabbitmqctl version根据版本下载 插…

neo4j(spring) 使用示例

文章目录 前言一、neo4j是什么二、开始编码1. yml 配置2. crud 测试3. node relation 与java中对象的关系4. 编码测试 总结 前言 图数据库先驱者 neo4j&#xff1a;neo4j官网地址 可以选择桌面版安装等多种方式,我这里采用的是docker安装 直接执行docker安装命令: docker run…

一键更换软件源的工具——chsrc

前言 经常用pip&#xff0c;ubuntu的apt&#xff0c;或者centos的yum等包下载工具的人不可避免的一件事就是——“更换软件源”&#xff0c;因为以上三个包下载工具的软件源一般都是默认为国外的官方网站&#xff0c;由于国情问题&#xff0c;下载速度就会非常慢&#xff0c;所…

华为OD机试 - 最大矩阵和 - 卡德恩算法(动态规划)(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

线性代数(宋浩版)(4)

2.4逆矩阵 &#xff08;不要把矩阵放在分母上&#xff09; 方阵的行列式 性质1 性质2 性质3 伴随矩阵&#xff08;只有方阵才有&#xff09; 1.求出所有元素的代数余子式&#xff08;矩阵先求行列式&#xff09;。 2.按行求的代数余子式按列放。 定理1&#xff08;重要&…

MySQL篇(窗口函数/公用表达式(CTE))

目录 讲解一&#xff1a;窗口函数 一、简介 二、常见操作 1. sumgroup by常规的聚合函数操作 2. sum窗口函数的聚合操作 三、基本语法 1. Function(arg1,..., argn) 1.1. 聚合函数 sum函数&#xff1a;求和 min函数 &#xff1a;最小值 1.2. 排序函数 1.3. 跨行函数…

ECMAScript与JavaScript的区别

目录 一、什么是ECMAScript&#xff1f; 二、什么是JavaScript&#xff1f; 三、ECMAScript与JavaScript的关系 3.1 ECMAScript规范版本 3.2 JavaScript的实现 四、ECMAScript与JavaScript的主要区别 4.1 规范与实现的区别 4.2 版本更新 4.3 环境支持 4.4 语言特性 五…

C# 使用Socket通信,新建WinForm服务端、客户端程序

一、新建WinForm Socket服务端程序 注&#xff1a;rtbReceviceMsg为RichTextBox控件 服务端程序、界面 服务端代码 public partial class Form1 : Form {public Form1(){InitializeComponent();}public virtual void TriggerOnUpdateUI(string message){if (this.InvokeRequir…

【SpringCloud】服务注册与发现 - Eureka

目录 服务注册/服务发现-Eureka背景问题描述解决思路什么是注册中心CAP 理论常见的注册中心 Eureka 介绍搭建Eureka Server创建Eureka-server 子模块引入eureka-server依赖项目构建插件完善启动类编写配置文件启动服务 服务注册引入eureka-client依赖完善配置文件启动服务 服务…

如图,从左到右在每个小格子中填入一个整数,使得其中任意三个相邻格子中所填整数之和都相等,若前m个格子中所填整数之和是2024,则m的值为?

1、如果图&#xff1a; 任务三个相邻的格子中所填整数之和都相等&#xff0c;则可以列个几个式子&#xff1a; 9ab abcbc(-5)c(-5)1 则可以求出&#xff1a; a-5&#xff0c;b1&#xff0c;c9 2、前m个格子中所填数之和是2024&#xff0c;则表示9abc(-5)1...第m个格子2024 …