Implement dig command (#4)

Reviewed-on: https://git.lemonsh.moe/C4TG1RL5/uberbot/pulls/4
Co-authored-by: famfo <famfo@famfo.xyz>
Co-committed-by: famfo <famfo@famfo.xyz>
This commit is contained in:
famfo 2023-02-08 20:52:38 +01:00 committed by lemon
parent 22a200a2ee
commit 592f7e44fd
7 changed files with 81 additions and 4 deletions

View File

@ -30,6 +30,7 @@ regex = "1.6.0"
hyper = { version = "0.14", features = ["server"] }
ellipse = "0.2.0"
base64 = "0.13"
trust-dns-resolver = "0.22"
[features]
# debug IRC commands

View File

@ -69,10 +69,15 @@ history_depth = 5
# requires a server running bird-lg-go (https://github.com/xddxdd/bird-lg-go)
# optional, trace commands disabled if not set
#[trace]
# TODO: document these options
#base_url = "catgirls.dn42"
#port = 9999
#server = ["at-vie1", "us-pno1", "fi-hel1"] # hostname:port of the server running the birdlg proxy
#base_url = "catgirls.dn42" # base url to the server running the birdlg proxy
#port = 9999 # port of the birdlg proxy
#server = ["at-vie1", "us-pno1", "fi-hel1"] # subdomains to the base url of the server running the birdlg proxy
# DNS lookups
# optional, dns commands disabled if not set
#[dns] # set this if you want to enable DNS lookups
#server = "1.1.1.1" # optional, set a custom DNS server, will use the system resolver by default
# Spotify module. Shows metadata about Spotify URLs sent in chat.

55
src/commands/dns.rs Normal file
View File

@ -0,0 +1,55 @@
use std::str::FromStr;
use crate::bot::{Command, CommandContext};
use async_trait::async_trait;
use trust_dns_resolver::AsyncResolver;
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts, NameServerConfig, Protocol};
use trust_dns_resolver::name_server::{GenericConnection, GenericConnectionProvider, TokioRuntime};
use trust_dns_resolver::proto::rr::RecordType;
pub struct Dig {
resolver: AsyncResolver<GenericConnection, GenericConnectionProvider<TokioRuntime>>,
}
impl Dig {
pub fn new(server: Option<String>) -> anyhow::Result<Self> {
let resolver = if let Some(server) = server {
let mut resolver_config = ResolverConfig::new();
let nserver = format!("{server}:53").parse()?;
resolver_config.add_name_server(NameServerConfig::new(nserver, Protocol::Udp));
AsyncResolver::tokio(resolver_config, ResolverOpts::default())?
} else {
AsyncResolver::tokio_from_system_conf()?
};
Ok(Self { resolver })
}
}
#[async_trait]
impl Command for Dig {
async fn execute(&self, msg: CommandContext) -> anyhow::Result<String> {
if let Some(msg) = msg.content {
let mut builder = String::new();
let parts: Vec<&str> = msg.split_ascii_whitespace().collect();
match parts.len() {
1 => {
let lookup = self.resolver.lookup_ip(&msg).await?;
for a in lookup {
builder.push_str(&format!("{msg}: {}", a.to_string()));
}
},
2 => {
let record = RecordType::from_str(&parts[0].to_ascii_uppercase())?;
let lookup = self.resolver.lookup(parts[1], record).await?;
for a in lookup {
builder.push_str(&format!("{} {}: {}", parts[1], record.to_string(), a.to_string()));
}
},
_ => builder.push_str("Usage: dig <record type> [hostname]"),
}
Ok(builder)
} else {
Ok("Usage: dig <hostname>".into())
}
}
}

View File

@ -9,6 +9,7 @@ const HELP: &str = concat!(
" * owo/mock/leet [user] * quot <user>\r\n",
" * ev <math expression> * qsearch <query>\r\n",
" * trace [ip/hostname] * trace6 [ip/hostname]\r\n",
" * dig [hostname]\r\n",
" - This bot can also resolve HTML titles, Spotify links and a subset of sed expressions."
);

View File

@ -2,6 +2,7 @@
pub mod debug;
pub mod eval;
pub mod dns;
pub mod help;
pub mod leek;
pub mod quotes;

View File

@ -10,6 +10,7 @@ pub struct UberConfig {
pub bot: BotConfig,
pub web: Option<HttpConfig>,
pub trace: Option<TraceConfig>,
pub dns: Option<DnsConfig>,
pub skip_cert_validation: Option<bool>,
}
@ -53,3 +54,9 @@ pub struct TraceConfig {
pub port: u32,
pub server: Vec<String>,
}
#[derive(Clone, Deserialize)]
pub struct DnsConfig {
pub server: Option<String>,
}

View File

@ -16,6 +16,7 @@ use crate::{
title::Title,
trace::{Trace, Trace6},
waifu::Waifu,
dns::Dig,
},
web::HttpContext,
};
@ -194,6 +195,12 @@ async fn main() -> anyhow::Result<()> {
tracing::warn!("Net module disabled, no server specified")
}
if let Some(cfg) = cfg.dns {
bot.add_command("dig".into(), Dig::new(cfg.server)?);
} else {
tracing::warn!("DNS module disable, no server specified")
}
if let Some(spotcfg) = cfg.spotify {
let creds = Credentials::new(&spotcfg.client_id, &spotcfg.client_secret);
let spotify = Spotify::new(creds).await?;