commit
48c02fc837
1944
Cargo.lock
generated
1944
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ name = "shibe-bot"
|
||||
description = "A Discord bot written in Rust, using Poise."
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
version = "0.4.2"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
@ -23,3 +23,10 @@ serde = { version = "1.0.217", features = ["serde_derive"] }
|
||||
serde_json = "1.0.134"
|
||||
roux = "2.2.13"
|
||||
structstruck = "0.4.1"
|
||||
reqwest = { version = "0.12.12", features = ["json"] }
|
||||
octocrab = "0.42.1"
|
||||
tempfile = "3.15.0"
|
||||
self-replace = "1.5.0"
|
||||
zip = "2.2.2"
|
||||
nix = { version = "0.29.0", features = ["process"] }
|
||||
minreq = { version = "2.13.0", features = ["https"] }
|
||||
|
BIN
artifact.zip
Normal file
BIN
artifact.zip
Normal file
Binary file not shown.
18
build.rs
18
build.rs
@ -12,11 +12,19 @@ fn main() -> Result<(), Error> {
|
||||
.add_instructions(&rustc)?
|
||||
.emit()?;
|
||||
|
||||
let git_commit_id = std::process::Command::new("git")
|
||||
let git_remote_url = std::process::Command::new("git")
|
||||
.arg("config")
|
||||
.arg("remote.origin.url")
|
||||
.output()?;
|
||||
let git_commit_id_short = std::process::Command::new("git")
|
||||
.arg("rev-parse")
|
||||
.arg("--short")
|
||||
.arg("HEAD")
|
||||
.output()?;
|
||||
let git_commit_id = std::process::Command::new("git")
|
||||
.arg("rev-parse")
|
||||
.arg("HEAD")
|
||||
.output()?;
|
||||
let git_commit_date = std::process::Command::new("git")
|
||||
.arg("show")
|
||||
.arg("-s")
|
||||
@ -38,10 +46,18 @@ fn main() -> Result<(), Error> {
|
||||
.arg("--format=%ae")
|
||||
.output()?;
|
||||
|
||||
println!(
|
||||
"cargo:rustc-env=GIT_REMOTE_URL={}",
|
||||
String::from_utf8(git_remote_url.stdout)?
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-env=GIT_COMMIT_ID={}",
|
||||
String::from_utf8(git_commit_id.stdout)?
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-env=GIT_COMMIT_ID_SHORT={}",
|
||||
String::from_utf8(git_commit_id_short.stdout)?
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-env=GIT_COMMIT_DATE={}",
|
||||
String::from_utf8(git_commit_date.stdout)?
|
||||
|
@ -1,6 +1,17 @@
|
||||
use std::convert::Infallible;
|
||||
use std::os::unix::process::CommandExt;
|
||||
|
||||
use crate::Context;
|
||||
use crate::Error;
|
||||
|
||||
use octocrab;
|
||||
use std::io::Write;
|
||||
|
||||
use self_replace;
|
||||
use zip;
|
||||
|
||||
use minreq;
|
||||
|
||||
/// Print version and build information
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn version(ctx: Context<'_>) -> Result<(), Error> {
|
||||
@ -17,7 +28,7 @@ pub async fn version(ctx: Context<'_>) -> Result<(), Error> {
|
||||
\tTarget triple: {}\n\
|
||||
\trustc version: {}\n",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("GIT_COMMIT_ID"),
|
||||
env!("GIT_COMMIT_ID_SHORT"),
|
||||
env!("GIT_COMMIT_DATE"),
|
||||
env!("GIT_COMMIT_AUTHOR_NAME"),
|
||||
env!("GIT_COMMIT_AUTHOR_EMAIL"),
|
||||
@ -33,33 +44,37 @@ pub async fn version(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
/// Update the bot remotely (Requires updater systemd service)
|
||||
#[poise::command(slash_command, owners_only, hide_in_help)]
|
||||
pub async fn update(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let command_result = std::process::Command::new("systemctl")
|
||||
.arg("--user")
|
||||
.arg("restart")
|
||||
.arg("shibe-bot-update.service")
|
||||
.spawn();
|
||||
match command_result {
|
||||
Ok(_child) => {
|
||||
ctx.say(format!(
|
||||
"Initialized restart service successfully.\n\
|
||||
Expect brief outage soon.\n\
|
||||
Current version: {}\n\
|
||||
Timestamp of last build: {}",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("VERGEN_BUILD_TIMESTAMP")
|
||||
))
|
||||
.await?;
|
||||
info!("Initialized restart service successfully");
|
||||
}
|
||||
Err(what) => {
|
||||
ctx.say(format!(
|
||||
"Failed to initialize restart service. Reason: {}",
|
||||
what
|
||||
))
|
||||
.await?;
|
||||
error!("Failed to initialize restart service: {}", what);
|
||||
pub async fn update(ctx: Context<'_>, override_check: bool) -> Result<(), Error> {
|
||||
// Check if the current commit hash is different from HEAD
|
||||
let head: octocrab::models::repos::Ref = octocrab::instance()
|
||||
.get(
|
||||
"/repos/shibedrill/shibe-bot/git/refs/heads/main",
|
||||
None::<&octocrab::models::Repository>,
|
||||
)
|
||||
.await?;
|
||||
if let octocrab::models::repos::Object::Commit { sha, url: _ } = head.object {
|
||||
if sha == env!("GIT_COMMIT_ID") {
|
||||
if override_check {
|
||||
info!("Update unnecessary, but check overridden.");
|
||||
ctx.say("Update unecessary, but check overridden. Updating.").await?;
|
||||
let Err(what) = self_update();
|
||||
error!("Update failed: {}", what);
|
||||
ctx.say(format!("Error occurred while updating: {}", what))
|
||||
.await?;
|
||||
} else {
|
||||
info!("Update unnecessary: Commit ID of remote is same as compiled commit.");
|
||||
ctx.say("Update unnecessary.").await?;
|
||||
}
|
||||
} else {
|
||||
info!("Update required, latest commit hash: {}", sha);
|
||||
let Err(what) = self_update();
|
||||
error!("Update failed: {}", what);
|
||||
ctx.say(format!("Error occurred while updating: {}", what))
|
||||
.await?;
|
||||
}
|
||||
} else {
|
||||
ctx.say("Update failed: Object field in response is not a Commit.").await?;
|
||||
error!("Checking for updates failed: Response field incorrect type");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -99,3 +114,56 @@ pub async fn say(
|
||||
ctx.say(what).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn self_update() -> Result<Infallible, Error> {
|
||||
let artifact_url = "https://nightly.link/shibedrill/shibe-bot/workflows/rust/main/artifact.zip";
|
||||
let tempdir = tempfile::Builder::new().prefix("shibe-bot").tempdir()?;
|
||||
trace!("Created tempdir successfully: {}", tempdir.path().display());
|
||||
let response = minreq::get(artifact_url).send()?;
|
||||
|
||||
let mut dest = std::fs::File::create_new(tempdir.path().join("artifact.zip"))?;
|
||||
let content = response.as_bytes();
|
||||
dest.write_all(&content)?;
|
||||
trace!("Downloaded latest build artifact successfully");
|
||||
|
||||
|
||||
let mut archive = zip::ZipArchive::new(dest)?;
|
||||
trace!("Created zip archive reader");
|
||||
let mut zipped_bin = archive.by_index(0)?;
|
||||
let new_bin_path = tempdir.path().join("shibe-bot");
|
||||
let mut new_bin = std::fs::File::create_new(&new_bin_path)?;
|
||||
trace!("Created new file for binary");
|
||||
|
||||
std::io::copy(&mut zipped_bin, &mut new_bin)?;
|
||||
trace!("Extracted binary successfully");
|
||||
|
||||
self_replace::self_replace(&new_bin_path)?;
|
||||
trace!("Replaced self with new binary successfully");
|
||||
|
||||
let new_command_args: Vec<_> = std::env::args_os().skip(1).collect();
|
||||
let new_command_path = std::env::current_exe()?;
|
||||
trace!("Got current executable path successfully: {}", new_command_path.display());
|
||||
|
||||
Err(Box::new(
|
||||
std::process::Command::new(new_command_path)
|
||||
.args(&new_command_args)
|
||||
.exec(),
|
||||
))
|
||||
}
|
||||
|
||||
mod test {
|
||||
|
||||
#[cfg(test)]
|
||||
use std::convert::Infallible;
|
||||
#[cfg(test)]
|
||||
use crate::Error;
|
||||
|
||||
#[test]
|
||||
fn test_self_update() -> Result<Infallible, Error> {
|
||||
use pretty_env_logger;
|
||||
use crate::command::devel::self_update;
|
||||
pretty_env_logger::init();
|
||||
self_update()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -89,11 +89,7 @@ pub async fn curbstomp(
|
||||
} else if target == **ctx.cache().current_user() {
|
||||
"nice try lol"
|
||||
} else {
|
||||
&format!(
|
||||
"{} made {} eat pavement.",
|
||||
ctx.author(),
|
||||
target
|
||||
)
|
||||
&format!("{} made {} eat pavement.", ctx.author(), target)
|
||||
};
|
||||
ctx.say(response).await?;
|
||||
info!("Executed command `whack` successfully");
|
||||
|
@ -42,12 +42,13 @@ pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
|
||||
rustc version: {}\n\
|
||||
Build timestamp: {}\n\
|
||||
Website: <https://riverdev.carrd.co>\n\
|
||||
Source code: <https://github.com/shibedrill/shibe-bot>\n\
|
||||
Source code: <{}>\n\
|
||||
Poise: <https://docs.rs/poise/latest/poise/>\n\
|
||||
Rust: <https://www.rust-lang.org/>",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("VERGEN_RUSTC_SEMVER"),
|
||||
env!("VERGEN_BUILD_TIMESTAMP"),
|
||||
env!("GIT_REMOTE_URL"),
|
||||
))
|
||||
.await?;
|
||||
info!("Executed command `info` successfully");
|
||||
|
Loading…
Reference in New Issue
Block a user