idk if th is is good ima jus commit anyways

This commit is contained in:
lda
2025-12-07 00:13:42 +07:00 Unverified
parent afffcd5528
commit 00cf33eefb
17 changed files with 58 additions and 125 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"rust-analyzer.cargo.target": "armv7-unknown-linux-musleabihf", "rust-analyzer.cargo.target": "armv7-unknown-linux-musleabihf",
"rust-analyzer.diagnostics.disabled": ["unlinked-file"] // "rust-analyzer.diagnostics.disabled": ["unlinked-file"]
} }
+1 -1
View File
@@ -65,7 +65,7 @@ pub enum NUDState {
/// failed. /// failed.
Failed, Failed,
Other(u16) Other(u16),
} }
/// everything i see /// everything i see
+1 -1
View File
@@ -1,2 +1,2 @@
pub mod mac; pub mod mac;
pub mod vec; // pub mod vec;
+1 -1
View File
@@ -8,7 +8,7 @@ enum OneOrMany<T> {
Many(Vec<T>), Many(Vec<T>),
} }
pub fn vec_from_strs<'de, D, T>(des: D) -> Result<Vec<T>, D::Error> pub fn deserialize<'de, D, T>(des: D) -> Result<Vec<T>, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
T: std::str::FromStr, T: std::str::FromStr,
+2 -2
View File
@@ -10,7 +10,7 @@
use std::{net::IpAddr, str::FromStr}; use std::{net::IpAddr, str::FromStr};
use crate::utils::parse::mac::ser_opm; use crate::utils::parse::mac;
use macaddr::MacAddr; use macaddr::MacAddr;
use serde_with::skip_serializing_none; use serde_with::skip_serializing_none;
use strum::{Display, EnumString}; use strum::{Display, EnumString};
@@ -33,7 +33,7 @@ pub struct IpNeighLine {
pub ip: IpAddr, pub ip: IpAddr,
pub dev: Option<String>, pub dev: Option<String>,
/// link layer address /// link layer address
#[serde(serialize_with = "ser_opm")] #[serde(with = "mac::option_mac")]
pub mac: Option<MacAddr>, pub mac: Option<MacAddr>,
/// Neighbour Unreachability Detection /// Neighbour Unreachability Detection
pub state: NUDState, pub state: NUDState,
+2 -6
View File
@@ -42,8 +42,8 @@ pub async fn read_dhcp_leases_with_names() -> io::Result<Vec<DhcpLeaseLine>> {
} }
Ok(leases_with_names) Ok(leases_with_names)
} }
use crate::utils::parse::mac;
use macaddr::MacAddr; use macaddr::MacAddr;
use serde::Serializer;
use std::io::{self, ErrorKind}; use std::io::{self, ErrorKind};
use std::net::IpAddr; use std::net::IpAddr;
@@ -53,15 +53,11 @@ pub struct DhcpLeaseLine {
/// Epoch seconds when the lease expires /// Epoch seconds when the lease expires
pub expires_epoch: u64, pub expires_epoch: u64,
pub ip: IpAddr, pub ip: IpAddr,
#[serde(serialize_with = "ser_mac")] #[serde(with = "mac")]
pub mac: MacAddr, pub mac: MacAddr,
pub name: Option<String>, pub name: Option<String>,
} }
fn ser_mac<S: Serializer>(m: &MacAddr, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&m.to_string())
}
/// Parse one line of /tmp/dhcp.leases /// Parse one line of /tmp/dhcp.leases
pub fn parse_dhcp_lease_line(line: &str) -> Option<DhcpLeaseLine> { pub fn parse_dhcp_lease_line(line: &str) -> Option<DhcpLeaseLine> {
let mut c = line.split_whitespace(); let mut c = line.split_whitespace();
+1 -1
View File
@@ -13,7 +13,7 @@ pub async fn status_smart_redirect(
Path(q): Path<String>, Path(q): Path<String>,
) -> axum::response::Result<Redirect, impl IntoResponse> { ) -> axum::response::Result<Redirect, impl IntoResponse> {
// no less bullshit // no less bullshit
let query = match parse_query(q) { let query = match parse_query(q).await {
QueryType::Ip(ip_addr) => DeviceQuery { QueryType::Ip(ip_addr) => DeviceQuery {
filter: Filters { filter: Filters {
ips: vec![ip_addr], ips: vec![ip_addr],
+1 -1
View File
@@ -2,6 +2,6 @@ use crate::utils::query::dev;
use axum::Json; use axum::Json;
pub async fn devs_router() -> Json<Vec<String>> { pub async fn devs_router() -> Json<Vec<String>> {
dev::devs_sorted().into() dev::devs_sorted().await.into()
} }
// Device listing endpoints // Device listing endpoints
+1 -1
View File
@@ -13,7 +13,7 @@ pub struct ApiError {
} }
impl ApiError { impl ApiError {
/// [StatusCode::INTERNAL_SERVER_ERROR] /// [StatusCode::INTERNAL_SERVER_ERROR] shortcut
pub const fn ise(error: String) -> Self { pub const fn ise(error: String) -> Self {
Self { Self {
code: StatusCode::INTERNAL_SERVER_ERROR, code: StatusCode::INTERNAL_SERVER_ERROR,
+10 -10
View File
@@ -4,11 +4,10 @@ use axum_extra::extract::Query;
use macaddr::MacAddr; use macaddr::MacAddr;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none; use serde_with::skip_serializing_none;
use serde_with::{DisplayFromStr, OneOrMany, serde_as};
use std::net::IpAddr; use std::net::IpAddr;
use crate::arpparse::NUDState; use crate::arpparse::NUDState;
use crate::utils::parse::de_many;
use crate::utils::parse::serialize_macs;
use crate::utils::query::get_macs; use crate::utils::query::get_macs;
#[derive(Debug, Default, Clone, Hash, Deserialize, Serialize)] #[derive(Debug, Default, Clone, Hash, Deserialize, Serialize)]
@@ -31,19 +30,20 @@ pub struct Status<T> {
pub filters: Filters, pub filters: Filters,
} }
#[serde_as]
#[derive(Debug, Default, Clone, Hash, Serialize, Deserialize)] #[derive(Debug, Default, Clone, Hash, Serialize, Deserialize)]
pub struct Filters { pub struct Filters {
#[serde(default, deserialize_with = "de_many::vec_from_strs")] #[serde_as(as = "OneOrMany<_>")]
#[serde(default)]
pub ips: Vec<IpAddr>, pub ips: Vec<IpAddr>,
#[serde(default, deserialize_with = "de_many::vec_from_strs")] #[serde_as(as = "OneOrMany<_>")]
#[serde(default)]
pub devs: Vec<String>, pub devs: Vec<String>,
#[serde(default, deserialize_with = "de_many::vec_from_strs")] #[serde_as(as = "OneOrMany<_>")]
#[serde(default)]
pub nuds: Vec<NUDState>, pub nuds: Vec<NUDState>,
#[serde( #[serde_as(as = "OneOrMany<DisplayFromStr>")]
default, #[serde(default)]
deserialize_with = "de_many::vec_from_strs",
serialize_with = "serialize_macs"
)]
pub macs: Vec<MacAddr>, pub macs: Vec<MacAddr>,
} }
+2 -2
View File
@@ -4,7 +4,7 @@ use std::net::IpAddr;
/* use crate::arpparse::IpNeighLine; /* use crate::arpparse::IpNeighLine;
use crate::route::api::Status; */ use crate::route::api::Status; */
use crate::utils::parse::mac::{des_opm, ser_opm}; use crate::utils::parse::mac;
use crate::utils::wake::wake_one; use crate::utils::wake::wake_one;
use axum::{extract::Json, http::StatusCode, response::IntoResponse}; use axum::{extract::Json, http::StatusCode, response::IntoResponse};
use futures::TryFutureExt; use futures::TryFutureExt;
@@ -44,7 +44,7 @@ pub enum WakeTargetStatus {
pub struct WakeTarget { pub struct WakeTarget {
#[serde(default)] #[serde(default)]
pub ip: Option<IpAddr>, pub ip: Option<IpAddr>,
#[serde(default, serialize_with = "ser_opm", deserialize_with = "des_opm")] #[serde(default, with = "mac::option_mac")]
pub mac: Option<MacAddr>, pub mac: Option<MacAddr>,
} }
+8 -47
View File
@@ -100,52 +100,12 @@ pub fn boolish_str(s: &str) -> bool {
&& t.parse::<u64>().map(|n| n != 0).unwrap_or(false)) && t.parse::<u64>().map(|n| n != 0).unwrap_or(false))
} }
pub mod de_many {
use serde::Deserialize;
use serde::de;
#[derive(Deserialize)]
#[serde(untagged)]
enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
pub fn vec_from_strs<'de, D, T>(des: D) -> Result<Vec<T>, D::Error>
where
D: serde::Deserializer<'de>,
T: std::str::FromStr,
T::Err: std::fmt::Display,
{
let raw: OneOrMany<String> = OneOrMany::<String>::deserialize(des)?;
let mut out = Vec::new();
match raw {
OneOrMany::One(s) => {
let t = s.trim();
if !t.is_empty() {
out.push(t.parse().map_err(de::Error::custom)?);
}
}
OneOrMany::Many(vs) => {
for s in vs {
let t = s.trim();
if t.is_empty() {
continue;
}
out.push(t.parse().map_err(de::Error::custom)?);
}
}
}
Ok(out)
}
}
pub mod mac { pub mod mac {
use macaddr::MacAddr; use macaddr::MacAddr;
use serde::{self, Deserialize, Deserializer, de::Error as DeError}; use serde::{self, Deserialize, Deserializer, de::Error as DeError};
use serde::{Serialize, Serializer, de}; use serde::{Serialize, Serializer, de};
pub fn serialize_macs<S>(macs: &[MacAddr], serializer: S) -> Result<S::Ok, S::Error> pub fn _serialize_macs<S>(macs: &[MacAddr], serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
@@ -154,7 +114,7 @@ pub mod mac {
} }
/// Serialize a MacAddr as a string /// Serialize a MacAddr as a string
pub fn _serialize_mac<S>(mac: &MacAddr, serializer: S) -> Result<S::Ok, S::Error> pub fn serialize<S>(mac: &MacAddr, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
@@ -162,7 +122,7 @@ pub mod mac {
} }
/// Deserialize a MacAddr from a string /// Deserialize a MacAddr from a string
pub fn _deserialize_mac<'de, D>(deserializer: D) -> Result<MacAddr, D::Error> pub fn _deserialize<'de, D>(deserializer: D) -> Result<MacAddr, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
@@ -170,13 +130,15 @@ pub mod mac {
s.parse::<MacAddr>().map_err(DeError::custom) s.parse::<MacAddr>().map_err(DeError::custom)
} }
pub mod option_mac {
use super::*;
/// serialize an [`Option<MacAddr>`] /// serialize an [`Option<MacAddr>`]
pub fn ser_opm<S: Serializer>(bro: &Option<MacAddr>, ser: S) -> Result<S::Ok, S::Error> { pub fn serialize<S: Serializer>(bro: &Option<MacAddr>, ser: S) -> Result<S::Ok, S::Error> {
Option::<String>::serialize(&bro.as_ref().map(ToString::to_string), ser) Option::<String>::serialize(&bro.as_ref().map(ToString::to_string), ser)
} }
/// deserialize an [`Option<MacAddr>`] /// deserialize an [`Option<MacAddr>`]
pub fn des_opm<'de, D>(des: D) -> Result<Option<MacAddr>, D::Error> pub fn deserialize<'de, D>(des: D) -> Result<Option<MacAddr>, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
@@ -185,6 +147,5 @@ pub mod mac {
.transpose() .transpose()
.map_err(de::Error::custom) .map_err(de::Error::custom)
} }
}
} }
pub use mac::*;
+11 -32
View File
@@ -1,45 +1,24 @@
use std::{collections::HashSet, fs}; use lda_ipjs::subcommands::address::json as ipjs_json;
use std::collections::HashSet;
pub fn get_dev() -> HashSet<String> { pub async fn get_dev() -> HashSet<String> {
let mut devs: HashSet<String> = HashSet::new(); let mut devs: HashSet<String> = HashSet::new();
if let Ok(rd) = std::fs::read_dir("/sys/class/net") { if let Ok(items) = ipjs_json::get(None).await {
for e in rd.flatten() { for item in items {
if e.file_type() if item.ifname != "lo" && !item.ifname.is_empty() {
.map(|ft| { devs.insert(item.ifname);
if ft.is_symlink() {
// true
fs::metadata(e.path()).map(|m| m.is_dir()).unwrap_or(false)
} else {
ft.is_dir()
}
})
.unwrap_or(false)
&& let Ok(name) = e.file_name().into_string()
&& name != "lo"
&& !name.is_empty()
{
devs.insert(name);
}
}
} else if let Ok(txt) = std::fs::read_to_string("/proc/net/dev") {
for line in txt.lines().skip(2) {
if let Some((name, _rest)) = line.split_once(':') {
let n = name.trim().to_string();
if n != "lo" && !n.is_empty() {
devs.insert(n);
}
} }
} }
} }
devs devs
} }
pub fn devs_sorted() -> Vec<String> { pub async fn devs_sorted() -> Vec<String> {
let mut v: Vec<String> = get_dev().into_iter().collect(); let mut v: Vec<String> = get_dev().await.into_iter().collect();
v.sort(); v.sort();
v v
} }
pub fn has_dev(name: &str) -> bool { pub async fn has_dev(name: &str) -> bool {
get_dev().contains(name) get_dev().await.contains(name)
} }
-5
View File
@@ -13,11 +13,6 @@ pub async fn get_ips(machine_name: &str) -> Result<impl Iterator<Item = IpAddr>>
.map(|c| c.ip())) .map(|c| c.ip()))
} }
// #[deprecated(
// since = "0.1.5",
// note = "just call once everything with get mac
// and then filter it bro WHY DO YOU EVEN DO TS"
// )]
// good now // good now
// //
// Current logic: When filtering by exactly 1 dev/mac, exclude entries missing that field. // Current logic: When filtering by exactly 1 dev/mac, exclude entries missing that field.
+2 -2
View File
@@ -12,7 +12,7 @@ pub enum QueryType {
Unknown(String), Unknown(String),
} }
pub fn parse_query(q: String) -> QueryType { pub async fn parse_query(q: String) -> QueryType {
let s = if cfg!(feature = "very-smart-parsing") { let s = if cfg!(feature = "very-smart-parsing") {
crate::utils::parse::extract_host(&q) crate::utils::parse::extract_host(&q)
} else { } else {
@@ -36,7 +36,7 @@ pub fn parse_query(q: String) -> QueryType {
return QueryType::Nud(state); return QueryType::Nud(state);
} }
// 4) Known device? prefer dev first // 4) Known device? prefer dev first
if has_dev(s) { if has_dev(s).await {
return QueryType::Dev(s.to_string()); return QueryType::Dev(s.to_string());
} }
// Default: name last // it will fail also // Default: name last // it will fail also
+2
View File
@@ -1,3 +1,5 @@
//! why did my Head Ass split these into two.
pub mod impls; pub mod impls;
use std::{io, net::IpAddr}; use std::{io, net::IpAddr};