Fix API and Voice
This commit is contained in:
parent
26eabbe275
commit
fa4863bfb3
50
Cargo.lock
generated
50
Cargo.lock
generated
@ -1425,6 +1425,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"reqwest 0.13.3",
|
"reqwest 0.13.3",
|
||||||
"rust-dsn-parser",
|
"rust-dsn-parser",
|
||||||
|
"rustls 0.23.40",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha3",
|
"sha3",
|
||||||
@ -4375,6 +4376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ring",
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@ -5208,9 +5210,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia"
|
name = "symphonia"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"symphonia-bundle-flac",
|
"symphonia-bundle-flac",
|
||||||
@ -5227,9 +5229,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-bundle-flac"
|
name = "symphonia-bundle-flac"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
|
checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
@ -5239,9 +5241,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-bundle-mp3"
|
name = "symphonia-bundle-mp3"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4"
|
checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@ -5251,9 +5253,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-codec-adpcm"
|
name = "symphonia-codec-adpcm"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f"
|
checksum = "2dddc50e2bbea4cfe027441eece77c46b9f319748605ab8f3443350129ddd07f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
@ -5261,9 +5263,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-codec-pcm"
|
name = "symphonia-codec-pcm"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b"
|
checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
@ -5271,9 +5273,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-codec-vorbis"
|
name = "symphonia-codec-vorbis"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
|
checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
@ -5282,9 +5284,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-core"
|
name = "symphonia-core"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
|
checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
@ -5295,9 +5297,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-format-mkv"
|
name = "symphonia-format-mkv"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f"
|
checksum = "122d786d2c43a49beb6f397551b4a050d8229eaa54c7ddf9ee4b98899b8742d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@ -5308,9 +5310,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-format-ogg"
|
name = "symphonia-format-ogg"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931"
|
checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
@ -5320,9 +5322,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-format-riff"
|
name = "symphonia-format-riff"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50"
|
checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"extended",
|
"extended",
|
||||||
"log",
|
"log",
|
||||||
@ -5332,9 +5334,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-metadata"
|
name = "symphonia-metadata"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c"
|
checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@ -5344,9 +5346,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "symphonia-utils-xiph"
|
name = "symphonia-utils-xiph"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
|
checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"symphonia-core",
|
"symphonia-core",
|
||||||
"symphonia-metadata",
|
"symphonia-metadata",
|
||||||
|
|||||||
@ -38,6 +38,7 @@ thousands = "0.2.0"
|
|||||||
url = { version = "2.5.7", features = ["serde"] }
|
url = { version = "2.5.7", features = ["serde"] }
|
||||||
convert_case = "0.11.0"
|
convert_case = "0.11.0"
|
||||||
rust-dsn-parser = { version = "1.0.0", registry = "ahines"}
|
rust-dsn-parser = { version = "1.0.0", registry = "ahines"}
|
||||||
|
rustls = "0.23.40"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.35.1"
|
version = "1.35.1"
|
||||||
@ -48,5 +49,5 @@ version = "0.6.0"
|
|||||||
features = ["builtin-queue"]
|
features = ["builtin-queue"]
|
||||||
|
|
||||||
[dependencies.symphonia]
|
[dependencies.symphonia]
|
||||||
version = "0.5"
|
version = "0.5.5"
|
||||||
features = ["mp3", "wav"]
|
features = ["mp3", "wav"]
|
||||||
|
|||||||
@ -1,23 +1,29 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
use crate::config::GlobalData;
|
use crate::config::GlobalData;
|
||||||
use crate::discord::voices::speak;
|
use crate::discord::voices::speak;
|
||||||
use crate::models::api_key::Apikey;
|
use crate::models::api_key::Apikey;
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum::{http::StatusCode, response::IntoResponse, routing::post, Json, Router};
|
use axum::{http::StatusCode, response::IntoResponse, routing::post, Json, Router};
|
||||||
|
use log::info;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serenity::prelude::Context;
|
|
||||||
|
|
||||||
pub async fn web_server(ctx: Context) {
|
#[derive(Clone)]
|
||||||
let addr = {
|
struct ApiContext {
|
||||||
let data = ctx.data.read().await;
|
data: Arc<GlobalData>,
|
||||||
let global_data = data.get::<GlobalData>().unwrap();
|
ctx: poise::serenity_prelude::Context
|
||||||
global_data.cfg.api_addr
|
}
|
||||||
};
|
|
||||||
|
pub async fn web_server(data: Arc<GlobalData>, ctx: poise::serenity_prelude::Context) {
|
||||||
|
let addr = data.cfg.api_addr;
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/play", post(play_sound))
|
.route("/play", post(play_sound))
|
||||||
.with_state(ctx);
|
.with_state(ApiContext {
|
||||||
|
data,
|
||||||
|
ctx
|
||||||
|
});
|
||||||
|
|
||||||
println!("Serving bot api on: {}", addr);
|
info!("Serving bot api on: {}", addr);
|
||||||
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
@ -30,18 +36,17 @@ struct SoundPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn play_sound(
|
async fn play_sound(
|
||||||
State(ctx): State<Context>,
|
State(ctx): State<ApiContext>,
|
||||||
Json(payload): Json<SoundPayload>,
|
Json(payload): Json<SoundPayload>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let data = ctx.data.read().await;
|
|
||||||
let global_data = data.get::<GlobalData>().unwrap();
|
|
||||||
|
|
||||||
if let Some(api_key) = Apikey::find_key_from_secret(&global_data.db, &payload.api_key).unwrap()
|
if let Some(api_key) = Apikey::find_key_from_secret(&ctx.data.db, &payload.api_key).unwrap()
|
||||||
{
|
&& let Some(user_id) = api_key.user_id {
|
||||||
if let Some(user_id) = api_key.user_id {
|
info!("Playing audio for {user_id}");
|
||||||
speak(
|
speak(
|
||||||
&ctx,
|
&ctx.ctx,
|
||||||
global_data.cfg.guild_id,
|
&ctx.data,
|
||||||
|
ctx.data.cfg.guild_id,
|
||||||
user_id,
|
user_id,
|
||||||
&payload.voice,
|
&payload.voice,
|
||||||
&payload.phrase,
|
&payload.phrase,
|
||||||
@ -49,7 +54,6 @@ async fn play_sound(
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
StatusCode::ACCEPTED
|
StatusCode::ACCEPTED
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ use songbird::SerenityInit;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
use crate::api::web_server;
|
||||||
|
|
||||||
pub type Context<'a> = poise::Context<'a, Arc<GlobalData>, Error>;
|
pub type Context<'a> = poise::Context<'a, Arc<GlobalData>, Error>;
|
||||||
|
|
||||||
@ -54,15 +55,25 @@ async fn event_handler(
|
|||||||
|
|
||||||
{
|
{
|
||||||
info!("Starting tasks handler...");
|
info!("Starting tasks handler...");
|
||||||
let data = data.clone();
|
let data_task = data.clone();
|
||||||
let ctx = ctx.clone();
|
let ctx_task = ctx.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _ = Task::create_reoccurring_tasks(&data).await.is_ok();
|
let _ = Task::create_reoccurring_tasks(&data_task).await.is_ok();
|
||||||
loop {
|
loop {
|
||||||
let _ = Task::run_tasks(&ctx, &data).await.is_ok();
|
let _ = Task::run_tasks(&ctx_task, &data_task).await.is_ok();
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let data_web = data.clone();
|
||||||
|
let ctx_web = ctx.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
web_server(
|
||||||
|
data_web,
|
||||||
|
ctx_web
|
||||||
|
).await;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serenity::FullEvent::Message { new_message } => {
|
serenity::FullEvent::Message { new_message } => {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use std::collections::HashMap;
|
|||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use crate::config::GlobalData;
|
||||||
|
|
||||||
async fn get_voice_dictionary(path: &Path) -> Result<HashMap<String, PathBuf>, tokio::io::Error> {
|
async fn get_voice_dictionary(path: &Path) -> Result<HashMap<String, PathBuf>, tokio::io::Error> {
|
||||||
let mut dir = tokio::fs::read_dir(path).await?;
|
let mut dir = tokio::fs::read_dir(path).await?;
|
||||||
@ -124,15 +125,16 @@ impl EventHandler for LeaveHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn speak(
|
pub async fn speak(
|
||||||
ctx: Context<'_>,
|
ctx: &poise::serenity_prelude::Context,
|
||||||
|
data: &Arc<GlobalData>,
|
||||||
guild_id: GuildId,
|
guild_id: GuildId,
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
voice: &str,
|
voice: &str,
|
||||||
phrase: &str,
|
phrase: &str,
|
||||||
) -> Result<(), VoiceError> {
|
) -> Result<(), VoiceError> {
|
||||||
let _ = ctx.data().speak_lock.lock().await;
|
let _ = data.speak_lock.lock().await;
|
||||||
|
|
||||||
let voice_path = match find_voice(&ctx.data().cfg.voice_path, voice).await.unwrap() {
|
let voice_path = match find_voice(&data.cfg.voice_path, voice).await.unwrap() {
|
||||||
None => return Err(VoiceError::VoiceNotFound(voice.to_string())),
|
None => return Err(VoiceError::VoiceNotFound(voice.to_string())),
|
||||||
Some(voice_path) => voice_path,
|
Some(voice_path) => voice_path,
|
||||||
};
|
};
|
||||||
@ -170,7 +172,7 @@ pub async fn speak(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let channel_id = {
|
let channel_id = {
|
||||||
let guild = ctx.cache().guild(guild_id).unwrap();
|
let guild = guild_id.to_guild_cached(&ctx).unwrap();
|
||||||
|
|
||||||
guild
|
guild
|
||||||
.voice_states
|
.voice_states
|
||||||
@ -185,7 +187,7 @@ pub async fn speak(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let manager = songbird::get(ctx.serenity_context())
|
let manager = songbird::get(ctx)
|
||||||
.await
|
.await
|
||||||
.expect("Songbird not initialized")
|
.expect("Songbird not initialized")
|
||||||
.clone();
|
.clone();
|
||||||
@ -215,7 +217,7 @@ pub async fn speak(
|
|||||||
.add_event(
|
.add_event(
|
||||||
Event::Track(TrackEvent::End),
|
Event::Track(TrackEvent::End),
|
||||||
LeaveHandler {
|
LeaveHandler {
|
||||||
guild: ctx.guild_id().unwrap(),
|
guild: guild_id,
|
||||||
manager: manager.clone(),
|
manager: manager.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -238,7 +240,7 @@ pub async fn say(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let guild_id = ctx.guild_id().unwrap();
|
let guild_id = ctx.guild_id().unwrap();
|
||||||
|
|
||||||
if let Err(err) = speak(ctx, guild_id, ctx.author().id, &voice, &phrase).await {
|
if let Err(err) = speak(ctx.serenity_context(), ctx.data(), guild_id, ctx.author().id, &voice, &phrase).await {
|
||||||
match err {
|
match err {
|
||||||
VoiceError::VoiceNotFound(_)
|
VoiceError::VoiceNotFound(_)
|
||||||
| VoiceError::WordNotFound(_)
|
| VoiceError::WordNotFound(_)
|
||||||
|
|||||||
@ -9,12 +9,14 @@ mod migrations;
|
|||||||
mod models;
|
mod models;
|
||||||
mod music;
|
mod music;
|
||||||
mod user;
|
mod user;
|
||||||
|
mod api;
|
||||||
|
|
||||||
use crate::config::{Args, BotConfig, GlobalData};
|
use crate::config::{Args, BotConfig, GlobalData};
|
||||||
use crate::discord::run_bot;
|
use crate::discord::run_bot;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use magick_rust::magick_wand_genesis;
|
use magick_rust::magick_wand_genesis;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
use rustls::crypto;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use tracing_core::LevelFilter;
|
use tracing_core::LevelFilter;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
@ -25,6 +27,8 @@ static START: Once = Once::new();
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
crypto::aws_lc_rs::default_provider().install_default().expect("Unable to setup default Rustls provider");
|
||||||
|
|
||||||
let args: Args = Args::from_args();
|
let args: Args = Args::from_args();
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
.with_env_filter(
|
.with_env_filter(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user