Skip to content

Commit d4926d8

Browse files
committed
功能:增加自动更新命令,支持检查和下载最新版本
1 parent ae00745 commit d4926d8

6 files changed

Lines changed: 136 additions & 2 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ repository = "https://github.com/FishPiOffical/fishpi-rust"
99
documentation = "https://docs.rs/fishpi-rust"
1010
readme = "README.md"
1111
keywords = ["fishpi"]
12+
build = "build.rs"
1213

1314
[lib]
1415
name = "fishpi_rust"

client/src/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl App {
4848
}
4949

5050
fn show_welcome(&self) {
51-
println!("{}", "欢迎使用摸鱼派 Rust 客户端".bold().cyan());
51+
println!("{} {}", "欢迎使用摸鱼派 Rust 客户端".bold().cyan(), env!("GIT_TAG").bold().cyan());
5252
println!("{}", "=====================================".cyan());
5353
}
5454

client/src/commands/handlers/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod chatroom;
55
pub mod filter;
66
pub mod notice;
77
pub mod redpacket;
8+
pub mod update;
89

910
pub use article::ArticleCommand;
1011
pub use breezemoon::BreezemoonCommand;
@@ -13,3 +14,4 @@ pub use chatroom::ChatroomCommand;
1314
pub use filter::FilterCommand;
1415
pub use notice::NoticeCommand;
1516
pub use redpacket::RedpacketCommand;
17+
pub use update::UpdateCommand;
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use anyhow::Result;
2+
use reqwest::Client;
3+
use std::env;
4+
use std::fs;
5+
use std::io::Write;
6+
use std::process::Command;
7+
use async_trait::async_trait;
8+
use crate::commands::{Command as CCommand, CommandContext, CommandResult};
9+
10+
#[allow(dead_code)]
11+
pub struct UpdateCommand {
12+
context: CommandContext,
13+
}
14+
15+
impl UpdateCommand {
16+
pub fn new(context: CommandContext) -> Self {
17+
Self { context }
18+
}
19+
20+
async fn get_latest_release(&self) -> Result<(String, String)> {
21+
let api = "https://api.github.com/repos/FishPiOffical/fishpi-rust/releases/latest";
22+
let client = Client::new();
23+
let resp = client
24+
.get(api)
25+
.header("User-Agent", "fishpi-rust-chatroom")
26+
.send()
27+
.await?
28+
.json::<serde_json::Value>()
29+
.await?;
30+
31+
let tag = resp["tag_name"].as_str().unwrap_or("").to_string();
32+
let asset_url = resp["assets"][0]["browser_download_url"]
33+
.as_str()
34+
.unwrap_or("")
35+
.to_string();
36+
Ok((tag, asset_url))
37+
}
38+
39+
async fn download_and_replace(&self, url: &str) -> Result<()> {
40+
let exe_path = env::current_exe()?;
41+
let tmp_path = exe_path.with_extension("new");
42+
43+
let resp = reqwest::get(url).await?;
44+
let bytes = resp.bytes().await?;
45+
let mut file = fs::File::create(&tmp_path)?;
46+
file.write_all(&bytes)?;
47+
48+
self.launch_update_script(exe_path.to_str().unwrap(), tmp_path.to_str().unwrap())?;
49+
println!("已启动自动更新,程序即将退出并自动替换为新版本。");
50+
std::process::exit(0);
51+
}
52+
53+
fn launch_update_script(&self, exe_path: &str, new_exe_path: &str) -> std::io::Result<()> {
54+
#[cfg(target_os = "windows")]
55+
{
56+
let script = format!(
57+
r#"
58+
@echo off
59+
ping 127.0.0.1 -n 2 > nul
60+
move /Y "{new}" "{old}"
61+
start "" "{old}"
62+
"#,
63+
new = new_exe_path,
64+
old = exe_path
65+
);
66+
let script_path = format!("{}.update.bat", exe_path);
67+
let mut file = fs::File::create(&script_path)?;
68+
file.write_all(script.as_bytes())?;
69+
Command::new("cmd")
70+
.args(&["/C", &script_path])
71+
.spawn()?;
72+
}
73+
#[cfg(any(target_os = "linux", target_os = "macos"))]
74+
{
75+
let script = format!(
76+
r#"
77+
#!/bin/sh
78+
sleep 1
79+
mv "{new}" "{old}"
80+
chmod +x "{old}"
81+
"{old}" &
82+
"#,
83+
new = new_exe_path,
84+
old = exe_path
85+
);
86+
let script_path = format!("{}.update.sh", exe_path);
87+
let mut file = fs::File::create(&script_path)?;
88+
file.write_all(script.as_bytes())?;
89+
Command::new("sh")
90+
.arg(&script_path)
91+
.spawn()?;
92+
}
93+
Ok(())
94+
}
95+
}
96+
97+
#[async_trait]
98+
impl CCommand for UpdateCommand {
99+
async fn execute(&mut self, _args: &[&str]) -> Result<CommandResult> {
100+
println!("正在检查新版本...");
101+
let (latest_tag, asset_url) = self.get_latest_release().await?;
102+
let latest_tag_clean = latest_tag.trim().trim_start_matches('v');
103+
let current_version = env!("GIT_TAG").trim().trim_start_matches('v');
104+
if latest_tag_clean == current_version {
105+
println!("已是最新版本。");
106+
return Ok(CommandResult::Success);
107+
}
108+
println!(
109+
"检测到新版本: v{},当前版本: v{}",
110+
latest_tag_clean, current_version
111+
);
112+
self.download_and_replace(&asset_url).await?;
113+
Ok(CommandResult::Success)
114+
}
115+
116+
fn help(&self) -> &'static str {
117+
"检查并自动更新到最新版本"
118+
}
119+
}

client/src/commands/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::commands::handlers::{
1010
// BreezemoonCommand,
1111
ChatCommand,
1212
ChatroomCommand,
13+
UpdateCommand,
1314
};
1415
use colored::*;
1516
pub use registry::CommandRegistry;
@@ -66,6 +67,10 @@ impl CommandContext {
6667
// command.execute(&[]).await?;
6768
println!("清风明月模式暂未实现");
6869
}
70+
"update" => {
71+
let mut command = UpdateCommand::new(self.clone());
72+
command.execute(&[]).await?;
73+
}
6974
_ => {
7075
println!("未知模式: {}", mode);
7176
}

client/src/commands/registry.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use colored::*;
33
use std::collections::HashMap;
44

55
use crate::commands::handlers::{
6-
ArticleCommand, BreezemoonCommand, ChatCommand, ChatroomCommand, NoticeCommand,
6+
ArticleCommand, BreezemoonCommand, ChatCommand, ChatroomCommand, NoticeCommand, UpdateCommand
77
};
88
use crate::commands::{Command, CommandContext, CommandFactory, CommandResult};
99
pub struct CommandRegistry {
@@ -143,5 +143,12 @@ impl CommandRegistry {
143143
"清风明月",
144144
vec!["bm", "moon"],
145145
);
146+
147+
self.register(
148+
"update",
149+
|context| Box::new(UpdateCommand::new(context.clone())),
150+
"检查并自动更新到最新版本",
151+
vec!["upgrade"],
152+
);
146153
}
147154
}

0 commit comments

Comments
 (0)