mirror of
https://github.com/LordMZTE/mcstat.git
synced 2024-05-16 05:49:45 +02:00
use viuer for mcstat image output.
This commit is contained in:
parent
27517a6994
commit
5068996284
|
@ -8,7 +8,6 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.40"
|
anyhow = "1.0.40"
|
||||||
asciify = "0.1.6"
|
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
clap = "2.33.3"
|
clap = "2.33.3"
|
||||||
image = "0.23.14"
|
image = "0.23.14"
|
||||||
|
@ -19,6 +18,7 @@ structopt = "0.3.21"
|
||||||
term_size = "0.3.2"
|
term_size = "0.3.2"
|
||||||
termcolor = "1.1.2"
|
termcolor = "1.1.2"
|
||||||
unicode-width = "0.1.8"
|
unicode-width = "0.1.8"
|
||||||
|
viuer = "0.4.0"
|
||||||
|
|
||||||
[dependencies.async-minecraft-ping]
|
[dependencies.async-minecraft-ping]
|
||||||
git = "https://github.com/LordMZTE/async-minecraft-ping.git"
|
git = "https://github.com/LordMZTE/async-minecraft-ping.git"
|
||||||
|
|
17
src/lib.rs
17
src/lib.rs
|
@ -3,7 +3,6 @@ extern crate smart_default;
|
||||||
|
|
||||||
use crate::output::Table;
|
use crate::output::Table;
|
||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
use asciify::AsciiBuilder;
|
|
||||||
use image::{DynamicImage, ImageFormat};
|
use image::{DynamicImage, ImageFormat};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
@ -27,22 +26,6 @@ macro_rules! none_if_empty {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsciiConfig {
|
|
||||||
pub size: Option<u32>,
|
|
||||||
pub colored: bool,
|
|
||||||
pub deep: bool,
|
|
||||||
pub invert: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsciiConfig {
|
|
||||||
pub fn apply(&self, mut builder: AsciiBuilder) -> AsciiBuilder {
|
|
||||||
if let Some(n) = self.size {
|
|
||||||
builder = builder.set_resize((n * 2, n))
|
|
||||||
}
|
|
||||||
builder.set_deep(self.deep).set_invert(self.invert)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove_formatting(s: &str) -> String {
|
pub fn remove_formatting(s: &str) -> String {
|
||||||
let chars = s.char_indices().rev();
|
let chars = s.char_indices().rev();
|
||||||
let mut buf = s.to_owned();
|
let mut buf = s.to_owned();
|
||||||
|
|
137
src/main.rs
137
src/main.rs
|
@ -1,21 +1,12 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use asciify::AsciiBuilder;
|
|
||||||
use async_minecraft_ping::{ConnectionConfig, ServerDescription, StatusResponse};
|
use async_minecraft_ping::{ConnectionConfig, ServerDescription, StatusResponse};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use termcolor::{Buffer, BufferWriter, ColorChoice, WriteColor};
|
|
||||||
use time::{Duration, Instant};
|
use time::{Duration, Instant};
|
||||||
use tokio::time;
|
use tokio::time;
|
||||||
|
|
||||||
use mcstat::{
|
use mcstat::{get_table, none_if_empty, output::Table, parse_base64_image, remove_formatting};
|
||||||
get_table,
|
|
||||||
none_if_empty,
|
|
||||||
output::Table,
|
|
||||||
parse_base64_image,
|
|
||||||
remove_formatting,
|
|
||||||
AsciiConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
#[structopt(
|
#[structopt(
|
||||||
|
@ -62,35 +53,24 @@ struct Opt {
|
||||||
#[structopt(long, help = "displays forge mod channels if the server sends them")]
|
#[structopt(long, help = "displays forge mod channels if the server sends them")]
|
||||||
channels: bool,
|
channels: bool,
|
||||||
|
|
||||||
#[structopt(long, short, help = "print the server's favicon as ASCII art")]
|
#[structopt(long, short, help = "print the server's favicon to stdout")]
|
||||||
image: bool,
|
image: bool,
|
||||||
|
|
||||||
#[structopt(
|
|
||||||
long,
|
|
||||||
short = "c",
|
|
||||||
requires = "image",
|
|
||||||
help = "print the server's favicon with color"
|
|
||||||
)]
|
|
||||||
color: bool,
|
|
||||||
|
|
||||||
#[structopt(short, requires = "image", help = "size of the favicon ascii art")]
|
#[structopt(short, requires = "image", help = "size of the favicon ascii art")]
|
||||||
size: Option<u32>,
|
size: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
#[structopt(
|
impl Opt {
|
||||||
long,
|
fn get_viuer_conf(&self) -> viuer::Config {
|
||||||
short,
|
let size = self.size.unwrap_or(16);
|
||||||
requires = "image",
|
viuer::Config {
|
||||||
help = "print the ascii art favicon with more diverse chars"
|
transparent: true,
|
||||||
)]
|
absolute_offset: false,
|
||||||
deep: bool,
|
width: Some(size * 2),
|
||||||
|
height: Some(size),
|
||||||
#[structopt(
|
..viuer::Config::default()
|
||||||
long,
|
}
|
||||||
short = "n",
|
}
|
||||||
requires = "image",
|
|
||||||
help = "inverts ascii art favicon"
|
|
||||||
)]
|
|
||||||
invert: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -132,23 +112,6 @@ async fn main() -> Result<()> {
|
||||||
let response = serde_json::from_str::<StatusResponse>(&raw_response)?;
|
let response = serde_json::from_str::<StatusResponse>(&raw_response)?;
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Image
|
|
||||||
let mut image = None;
|
|
||||||
|
|
||||||
if let (Some(favicon), true) = (&response.favicon, opt.image) {
|
|
||||||
// The image parsing and asciifying is done while the table is printing
|
|
||||||
image = Some(tokio::spawn(asciify_base64_image(
|
|
||||||
favicon.clone(),
|
|
||||||
AsciiConfig {
|
|
||||||
size: Some(opt.size.unwrap_or(16)),
|
|
||||||
colored: opt.color,
|
|
||||||
deep: opt.deep,
|
|
||||||
invert: opt.invert,
|
|
||||||
},
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region printing
|
// region printing
|
||||||
// if the server has mods, and the user hasn't used the -m argument, notify
|
// if the server has mods, and the user hasn't used the -m argument, notify
|
||||||
// that.
|
// that.
|
||||||
|
@ -165,45 +128,47 @@ async fn main() -> Result<()> {
|
||||||
)
|
)
|
||||||
.stdout()?;
|
.stdout()?;
|
||||||
|
|
||||||
if let Some(img) = image {
|
if let (Some(img), true) = (response.favicon, opt.image) {
|
||||||
println!("\n{}", img.await??);
|
let decoded = parse_base64_image(img)?;
|
||||||
|
viuer::print(&decoded, &opt.get_viuer_conf())
|
||||||
|
.map_err(|e| anyhow!("Failed to print favicon: {}", e))?;
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the asciifyed image from base64
|
// returns the asciifyed image from base64
|
||||||
/// returns Err if the base64 image is invalid
|
// returns Err if the base64 image is invalid
|
||||||
async fn asciify_base64_image(favicon: String, config: AsciiConfig) -> Result<String> {
|
// async fn asciify_base64_image(favicon: String, config: AsciiConfig) ->
|
||||||
let image = parse_base64_image(favicon)?;
|
// Result<String> { let image = parse_base64_image(favicon)?;
|
||||||
|
//
|
||||||
let builder = config.apply(AsciiBuilder::new_from_image(image));
|
// let builder = config.apply(AsciiBuilder::new_from_image(image));
|
||||||
|
//
|
||||||
let mut buf = if config.colored {
|
// let mut buf = if config.colored {
|
||||||
// this does not write to stdout but just gets the correct color
|
// this does not write to stdout but just gets the correct color
|
||||||
// information for stdout
|
// information for stdout
|
||||||
let mut buf = BufferWriter::stdout(ColorChoice::Always).buffer();
|
// let mut buf = BufferWriter::stdout(ColorChoice::Always).buffer();
|
||||||
builder.to_stream_colored(&mut buf);
|
// builder.to_stream_colored(&mut buf);
|
||||||
buf
|
// buf
|
||||||
} else {
|
// } else {
|
||||||
let mut buf = Buffer::no_color();
|
// let mut buf = Buffer::no_color();
|
||||||
builder.to_stream(&mut buf);
|
// builder.to_stream(&mut buf);
|
||||||
buf
|
// buf
|
||||||
};
|
// };
|
||||||
// reset color
|
// reset color
|
||||||
buf.reset()?;
|
// buf.reset()?;
|
||||||
|
//
|
||||||
let bytes = buf.as_slice().to_vec();
|
// let bytes = buf.as_slice().to_vec();
|
||||||
|
//
|
||||||
// only check utf8 format in debug mode
|
// only check utf8 format in debug mode
|
||||||
#[cfg(debug_assertions)]
|
// #[cfg(debug_assertions)]
|
||||||
let out = String::from_utf8(bytes).expect("asciifyed image is invalid utf8");
|
// let out = String::from_utf8(bytes).expect("asciifyed image is invalid utf8");
|
||||||
// bytes should always be valid utf8
|
// bytes should always be valid utf8
|
||||||
#[cfg(not(debug_assertions))]
|
// #[cfg(not(debug_assertions))]
|
||||||
let out = unsafe { String::from_utf8_unchecked(bytes) };
|
// let out = unsafe { String::from_utf8_unchecked(bytes) };
|
||||||
|
//
|
||||||
Ok(out)
|
// Ok(out)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn format_table(
|
fn format_table(
|
||||||
response: &StatusResponse,
|
response: &StatusResponse,
|
||||||
|
|
Loading…
Reference in a new issue