rename argument mod to config; implement name, tracker config options

This commit is contained in:
yggverse 2025-09-08 15:11:52 +03:00
parent bdc5496d45
commit e8b409c4d6
2 changed files with 39 additions and 14 deletions

View file

@ -1,11 +1,11 @@
mod argument;
mod config;
mod format;
use anyhow::Result;
use argument::Argument;
use btracker_fs::public::{Order, Public, Sort};
use chrono::Local;
use clap::Parser;
use config::Config;
use librqbit_core::torrent_metainfo::{TorrentMetaV1Owned, torrent_from_bytes};
use log::*;
use native_tls::{HandshakeError, Identity, TlsAcceptor, TlsStream};
@ -34,33 +34,33 @@ fn main() -> Result<()> {
.init()
}
let argument = Arc::new(Argument::parse());
let config = Arc::new(Config::parse());
let public =
Arc::new(Public::init(&argument.storage, argument.limit, argument.capacity).unwrap());
let public = Arc::new(Public::init(&config.storage, config.limit, config.capacity).unwrap());
// https://geminiprotocol.net/docs/protocol-specification.gmi#the-use-of-tls
let acceptor = TlsAcceptor::new(Identity::from_pkcs12(
&{
let mut buffer = vec![];
File::open(&argument.identity)?.read_to_end(&mut buffer)?;
File::open(&config.identity)?.read_to_end(&mut buffer)?;
buffer
},
&argument.password,
&config.password,
)?)?;
let listener = TcpListener::bind(&argument.bind)?;
let listener = TcpListener::bind(&config.bind)?;
info!("Server started on `{}`", argument.bind);
info!("Server started on `{}`", config.bind);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
thread::spawn({
let config = config.clone();
let public = public.clone();
let peer = stream.peer_addr()?;
let connection = acceptor.accept(stream);
move || handle(public, peer, connection)
move || handle(config, public, peer, connection)
});
}
Err(e) => error!("{e}"),
@ -70,6 +70,7 @@ fn main() -> Result<()> {
}
fn handle(
config: Arc<Config>,
public: Arc<Public>,
peer: SocketAddr,
connection: Result<TlsStream<TcpStream>, HandshakeError<TcpStream>>,
@ -108,7 +109,7 @@ fn handle(
if header_buffer.last().is_some_and(|&b| b == b'\n') {
// header bytes contain valid Gemini **request**
if let Ok(request) = request::Gemini::from_bytes(&header_buffer) {
return response(request, &public, &peer, &mut stream);
return response(request, &config, &public, &peer, &mut stream);
}
// header bytes received but yet could not be parsed,
@ -146,6 +147,7 @@ fn handle(
fn response(
request: titanite::request::Gemini,
config: &Config,
public: &Public,
peer: &SocketAddr,
stream: &mut TlsStream<TcpStream>,
@ -156,6 +158,7 @@ fn response(
if request.url.path().trim_end_matches("/").is_empty() {
return send(
&match index(
config,
public,
request.url.query_pairs().find_map(|a| {
if a.0 == "page" {
@ -207,7 +210,7 @@ fn send(data: &[u8], stream: &mut TlsStream<TcpStream>, callback: impl FnOnce(Re
})());
}
fn index(public: &Public, page: Option<usize>) -> Result<String> {
fn index(config: &Config, public: &Public, page: Option<usize>) -> Result<String> {
let (total, torrents) = public.torrents(
None, // @TODO
Some((Sort::Modified, Order::Desc)),
@ -215,7 +218,19 @@ fn index(public: &Public, page: Option<usize>) -> Result<String> {
Some(public.default_limit),
)?;
let mut b = Vec::with_capacity(torrents.len());
let mut b = Vec::new();
b.push(format!("# {}\n", config.name));
if let Some(ref trackers) = config.tracker {
b.push("```".into());
for tracker in trackers {
b.push(tracker.clone());
}
b.push("```\n".into());
}
b.push("## Recent\n".into());
for torrent in torrents {
let i: TorrentMetaV1Owned = torrent_from_bytes(&torrent.bytes)?;
@ -236,6 +251,8 @@ fn index(public: &Public, page: Option<usize>) -> Result<String> {
));
}
b.push("## Navigation\n".into());
b.push(format!(
"Page {} / {} ({total} {} total)",
page.unwrap_or(1),