7 Commits
9 changed files with 108 additions and 16 deletions

No files matched your search

File renamed without changes.
+60
View File
@@ -0,0 +1,60 @@
# taking back my code AHHHH
this is going to be lengthy. ci is spotless but idk how it works cuz powershell. this is good but i cant afford VPN on the router; we will need to do some bullshit.
## overview
we need a:
- small ahh bin in the router.
- forwards a shell and some functions.
- may be shell calling fns maybe some unsafe c. i cant unsafe c.
- big ahh bin in the vps.
- connect to the small ahh bin thru the wide ass internet.
- forwards some APIs.
- static site
- now need no hosts; apis can be called anywhere anyway.
- do offer these in the big ahh bins tho lets not miss out some shit.
- automation
- gitea
- on the vps or the uh idk.
- ABSOLUTELY can auto build main:latest every day / other day.
- and releases.
- router
- a script to pull the tar. from actions artifacts or from releases. (lua or shell yo)
- a script for the bin and the init.d scripts for these two.
- vps
- a systemd service (ima use ai for ts ngl)
- an auto updater. maybe we overkill and dnf. maybe go easy and git clone + cargo install. maybe we pull from release or nightly. idk
i think idk
## router
### current
everything.
we have some functions that call ip neigh a bajillion times.
we have some other functions that read the same file/folder in /sys or sum shit.
we have a function that broadcast to a set ahh address.
we have some routes; and some data structures acting as schema for them ahh. we dont do posts with json but gets with query strings for some ahh reasons.
these are carryover from the early days.
also from the early days are the js.
static was 100% ai with 0 intervention.
we have a search bar of sort that hooks through a smart endpoint that searches for everything.
we have some bullshit. and two buttons to check and wake. that pings `/api/smart/{query}` and `/wake?name=query`. why.
we have the result of the wake and or status and the errors in the first text box.
the list of cliets with names connected to the router the second box.
thats cool.
### changes?
idk changes.
+5 -1
View File
@@ -7,9 +7,11 @@ use crate::route::api::Status; */
use crate::utils::parse::mac::{des_opm, ser_opm}; use crate::utils::parse::mac::{des_opm, ser_opm};
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 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 tokio::net::UdpSocket;
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Debug, Default, Serialize, Clone)] #[derive(Debug, Default, Serialize, Clone)]
@@ -75,7 +77,9 @@ pub async fn wake_multi(Json(req): Json<Vec<WakeTarget>>) -> impl IntoResponse {
pub async fn wake_multi_split( pub async fn wake_multi_split(
targets: impl IntoIterator<Item = WakeTarget>, targets: impl IntoIterator<Item = WakeTarget>,
) -> io::Result<Vec<WakeTargetResult>> { ) -> io::Result<Vec<WakeTargetResult>> {
let sock = tokio::net::UdpSocket::bind("0.0.0.0:0").await?; let sock = UdpSocket::bind("[::]:0")
.or_else(|_| UdpSocket::bind(":0"))
.await?;
sock.set_broadcast(true)?; sock.set_broadcast(true)?;
Ok( Ok(
+11 -2
View File
@@ -1,10 +1,19 @@
use std::collections::HashSet; use std::{collections::HashSet, fs};
pub fn get_dev() -> HashSet<String> { pub 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(rd) = std::fs::read_dir("/sys/class/net") {
for e in rd.flatten() { for e in rd.flatten() {
if let Ok(name) = e.file_name().into_string() if e.file_type()
.map(|ft| {
if ft.is_symlink() {
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 != "lo"
&& !name.is_empty() && !name.is_empty()
{ {
+2 -2
View File
@@ -58,12 +58,12 @@ pub async fn status_smart_redirect(q: String) -> DeviceQuery {
}; };
} }
// 5) Try DNS: if it resolves, treat as name // 5) Try DNS: if it resolves, treat as name
if tokio::net::lookup_host((s, 0)).await.is_ok() { /* if tokio::net::lookup_host((s, 0)).await.is_ok() {
return DeviceQuery { return DeviceQuery {
name: Some(s.to_string()), name: Some(s.to_string()),
..Default::default() ..Default::default()
}; };
} } */
// Default: name last // it will fail also // Default: name last // it will fail also
DeviceQuery { DeviceQuery {
name: Some(s.to_string()), name: Some(s.to_string()),
+4 -1
View File
@@ -1,6 +1,7 @@
pub mod impls; pub mod impls;
use std::{io, net::IpAddr}; use std::{io, net::IpAddr};
use futures::TryFutureExt;
use macaddr::MacAddr; use macaddr::MacAddr;
use tokio::net::UdpSocket; use tokio::net::UdpSocket;
@@ -74,7 +75,9 @@ impl WakeTargetResult {
pub async fn _wake_multi( pub async fn _wake_multi(
targets: impl IntoIterator<Item = WakeTarget>, targets: impl IntoIterator<Item = WakeTarget>,
) -> io::Result<Vec<WakeTargetResult>> { ) -> io::Result<Vec<WakeTargetResult>> {
let sock = UdpSocket::bind(":0").await?; let sock = UdpSocket::bind("[::]:0")
.or_else(|_| UdpSocket::bind(":0"))
.await?;
sock.set_broadcast(true)?; sock.set_broadcast(true)?;
let fs = targets.into_iter().map(|t| wake_one(&sock, t)); let fs = targets.into_iter().map(|t| wake_one(&sock, t));
Ok(futures::future::join_all(fs).await) Ok(futures::future::join_all(fs).await)
+14 -4
View File
@@ -1,6 +1,8 @@
import { filter_array } from "./status.js";
export const qs = new URLSearchParams(location.search); export const qs = new URLSearchParams(location.search);
// not real cuh // $ is normally queryselector are we fr
export const $ = (id) => document.getElementById(id); export const $ = (id) => document.getElementById(id);
export const elName = $("name"); export const elName = $("name");
export const elCheck = $("check"); export const elCheck = $("check");
@@ -17,10 +19,18 @@ export function setPill(kind, text) {
pill.textContent = text; pill.textContent = text;
} }
export function setLink(name) { export function setLink(name, clear) {
const url = new URL(location.href); const url = new URL(location.href);
if (name) url.searchParams.set("name", name); if (clear) url.searchParams.forEach((_, k) => url.searchParams.delete(k)); // FUCK
else url.searchParams.delete("name"); /* const hasExtraFilters = filter_array.some(
(k) => url.searchParams.getAll(k).length
);
if (hasExtraFilters) {
// jus returns whatever; they are specifying further
} else */ {
if (name) url.searchParams.set("name", name);
else url.searchParams.delete("name");
}
history.replaceState(null, "", url); history.replaceState(null, "", url);
link.href = url.toString(); link.href = url.toString();
} }
+9 -3
View File
@@ -42,7 +42,7 @@ function pickTarget(value) {
elName.value = v; elName.value = v;
updatePreview(); updatePreview();
saveName(v); saveName(v);
setLink(v); setLink(v, true);
fetchStatus(v); fetchStatus(v);
fetchLeases(); fetchLeases();
} }
@@ -74,10 +74,16 @@ const initial = loadName(qs);
if (initial) { if (initial) {
elName.value = initial; elName.value = initial;
updatePreview(); updatePreview();
setLink(initial); if (qs.has("name")) {
fetchStatus(initial); setLink(initial);
fetchStatus(initial);
} else {
fetchStatus();
}
fetchLeases(); fetchLeases();
} else { } else {
setPill("warn", "unknown"); setPill("warn", "unknown");
updatePreview();
fetchStatus();
fetchLeases(); fetchLeases();
} }
+3 -3
View File
@@ -8,8 +8,8 @@ const status_map = {
state: "state", state: "state",
dev: "interface", dev: "interface",
}; };
export const status_array = Object.keys(status_map);
const filter_array = ["ip", "dev", "nud", "mac"]; export const filter_array = ["ip", "dev", "nud", "mac"];
function buildStatusUrl(name) { function buildStatusUrl(name) {
const hasExtraFilters = filter_array.some((k) => qs.getAll(k).length); const hasExtraFilters = filter_array.some((k) => qs.getAll(k).length);
@@ -18,7 +18,7 @@ function buildStatusUrl(name) {
} }
const u = new URL("/api/status", location.origin); const u = new URL("/api/status", location.origin);
if (name) u.searchParams.set("name", name); if (name) u.searchParams.set("name", name);
for (const k of Object.keys(status_map)) { for (const k of filter_array) {
const vals = qs.getAll(k); const vals = qs.getAll(k);
for (const v of vals) u.searchParams.append(k, v); for (const v of vals) u.searchParams.append(k, v);
} }