<!-- .slide: data-background="linear-gradient(to bottom right, #2b5876, #4e4376)" -->
# F0rmF0551l
## When Retro Meets Reality 🦕
<br>
A journey through time with ("outdated") form processing
Note:
Open in Vivaldi
---
## Was ist F0rmF0551l? 🤔
<br>
- F0rmF0551l = **FormFossil**
- Ein Formular-Verarbeitungssystem geschrieben in Rust
- Bringt den Charme alter Internet-Protokolle in die moderne Welt
- Unterstützt multiple Interfaces für maximalen Retro-Spaß
- Perfekt für Vereine, Hackspaces und alle, die Formulare hassen 😉
Note:
- Es ist einfach ein Fun-Projekt - mit Hoffnung auf Spaceeinsatz
- Entstanden aus der Idee, Formulare weniger langweilig zu machen
- es geht spezifisch eher um Anträge als um grundsätzliche Formulare, aber Application Fossil klingt halt sch****
- Gleichzeitig ein Experiment in Rust, der Protokoll-Implementierung und der Digitalisierung von verstaubten Formularen
- Perfekt für alle die Formulare hassen .. sie werden sie danach nur noch mehr hassen
---
## Die Tech-Stack Highlights 🚀
<br>
- 🦀 **Rust Backend**
- Modulare Protocol und Submission Handler Implementierung
- Asynchrone Annahme und Verarbeitung mit Tokio
- 🔒 **Type-safe Formulardefinitionen** in JSON Schema
- 📝 **PDF-Template System**: Custom Template Engine auf Basis von lopdf
- 📡 **Native Implementierung der User Interfaces**
- **Telnet** (für echte Terminal-Fans; inkl. 🎨 ANSI-Art)
- **Gopher** (90er Internet FTW!)
- Web (für Normalos)
Note:
- Rust Backend gewählt für Performance, Type-Safety und Lerneffekt
- Modulare Protocol und Submission Handler Implementierung
- Asynchrone Annahme und Verarbeitung mit Tokio
- Native Rust Implementierung für die verwendeten User Interface Protokolle
- keine externen Server
- keine telnet oder gopher lib
- web mit axum und handlebars
- PDF-System basiert auf low-level PDF Manipulation mit lopdf
- Nicht perfekt, aber funktional
- nice to know: Telnet Interface unterstützt ANSI Farben
- Gopher implementiert die wichtigsten Teile des Protokolls für Formulare
- dazu nachher noch etwas mehr
---
## Technischer Deep-Dive: Architektur 🛠
### Modulare Architektur
<br>
- Anträge / Formulare werden als .json einfach in einen Ordner gelegt
- unabhängige, async, protokollspezische **User Interface Handler**
- protokollspezisches Rendering der Formulare
- Gemeinsame **Core Logic für Validierung**
- voneinander unabhängige **SubmissionStrategy** Implementierungen
- **Submission Queue** zur Abarbeitung der Submission Strategies
Note:
- Die json Antragsdateien werden beim Applikations(neu)start eingelesen
- Es gibt technische Herausforderungen, weshalb ein App interner Reload schwierig, aber nicht unmöglich ist. Wäre eine Idee für die Zukunft. Oder einfach nur Overengineering.
- Jedes implementierte Protokoll bzw. User Interface hat einen eigenen Renderer für die Anträge
- Gemeinsame Core Logic für die Validierung der Formularfelder
- Submission Queue für asynchrone Verarbeitung von übermittelten Formularen
- Die SubmissionStrategy Implementierungen haben alle das gleiche Interface für die Annahme von zu verarbeitenden Anträgen, die dann über die Submission Queue entsprechend aufgerufen werden
----
## Technischer Deep-Dive: Architektur 🛠
### Submission
<br>
```rust
// Initialize submission strategies
let mut strategies: Vec<Box<dyn SubmissionStrategy + Send + Sync>> = Vec::new();
// Add email strategy if enabled
if let Some(email_config) = &config.submission.email {
if email_config.enabled {
strategies.push(Box::new(EmailSubmissionStrategy::new(
EmailSubmissionConfig {
...
// Add cleanup strategy last - it will run after all other strategies
strategies.push(Box::new(CleanupStrategy::new(file_upload_manager.clone())));
// Create shared submission strategies and queue
let submission_strategies = Arc::new(strategies);
let submission_queue = SubmissionQueue::new(submission_strategies.clone());
```
----
## Technischer Deep-Dive: Architektur 🛠
### Submission Queue
<br>
```rust
impl SubmissionQueue {
pub fn new(strategies: Arc<Vec<Box<dyn SubmissionStrategy + Send + Sync>>>) -> Self {
let (sender, mut receiver) = mpsc::channel(42); // Buffer size of 42 submissions
// Spawn background worker
tokio::spawn(async move {
while let Some(submission) = receiver.recv().await {
// Process submission with all strategies
for strategy in strategies.iter() {
if let Err(e) = strategy.submit(&submission).await {
eprintln!("Error processing submission: {}", e);
}
}
}
});
Self { sender }
}
pub async fn submit(
&self,
submission: ApplicationSubmission,
) -> Result<(), Box<dyn Error + Send + Sync>> {
self.sender.send(submission).await.map_err(|e| {
Box::new(InterfaceError::Processing(format!(
"Failed to queue submission: {}",
e
))) as Box<dyn Error + Send + Sync>
})
}
}
```
----
## Technischer Deep-Dive: Architektur 🛠
### User interfaces
<br>
```rust
// Protocol Handler Interfaces
let telnet_interface = TelnetInterface::new(
config.server.telnet_address.parse()?,
applications.clone(),
submission_queue.clone(),
file_upload_manager.clone(),
config.server.show_demo_notice,
);
// Run all interfaces concurrently
tokio::select! {
result = web_interface.start() => {
if let Err(e) = result {
eprintln!("Web interface error: {}", e);
}
}
result = telnet_interface.start() => {
if let Err(e) = result {
eprintln!("Telnet interface error: {}", e);
}
}
result = gopher_interface.start() => {
if let Err(e) = result {
eprintln!("Gopher interface error: {}", e);
}
}
result = file_upload_server.start() => {
if let Err(e) = result {
eprintln!("File upload server error: {}", e);
}
}
_ = shutdown_signal() => {
println!("\nShutting down...");
}
}
```
---
## Deployment Optionen 🐳
1. **Docker** (für die Container-Fans):
```bash
# Latest Stable (mit example config; deaktivierter Email Versand)
docker run -d \
--name f0rmf0551l \
-p 3000:3000 \
-p 3023:3023 \
-p 7070:7070 \
-p 7071:7071 \
docker.maglab.space/binsky/f0rmf0551l:latest
```
2. **Bare Metal** (für Puristen):
```bash
# Build from source
git clone https://git.maglab.space/binsky/f0rmf0551l
cd f0rmf0551l
cargo build --release
# Run with custom config
./target/release/f0rmf0551l -c config.toml
```
Note:
- Docker Images sind ca ~100MB groß
- Volumes für einfache Konfiguration (mehr Details in der Projekt README)
---
## Coole Hacks & Features 🛠 <small style="color: chartreuse; margin-top: 2rem; margin-left: 2rem;">(ja, noch mehr!)</small>
<br>
- **PDF Magie**:
- Windows-1252 Encoding für PDF Kompatibilität
- Fake Checkboxes in PDFs via Text-Fields
- **Protocol Tricks**:
- "a bissl" ASCII Art im Telnet Interface
- ANSI Escape Sequences <span style="background-image: radial-gradient(circle at bottom, #ff0000, #4b00ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;">für Farben</span> im Telnet UI
- Gopher Menu Rendering
- 
Note:
- wilde PDF Hacks waren notwendig für Kompatibilität zu Radio-Buttons / Checkboxen
- "a bissl" ASCII Art im Telnet Interface
- Telnet unterstützt ANSI Farben
- Gopher Menüs sind quasi über Ordner gelöst, und der State dauerhaft in der URL/Query gehalten und aktualisiert
- soll heißen man ruft eigentlich mega viele verschiedene dynamisch generierte API Endpunkt auf, um Eingaben zu verarbeiten und eine Art Menüführung zu haben
---
## Live Demo Time! 💻
<br>
```bash
# Via Telnet (Raw Terminal Experience)
telnet f0rmf0551l.binsky.dev 3023
# Via Gopher (90s Style)
sacc gopher://f0rmf0551l.binsky.dev:7070
# Oder Web (langweilig...)
http://f0rmf0551l.binsky.dev
```
Note:
- Browser links anordnen: Meta + <-
- Terminal in der FormFossil Dev nix-shell nach rechts
- Live Demo: Zeige gleiches Formular in allen drei Interfaces
- Demonstriere ANSI-Farben im Telnet
- Zeige Gopher in Lynx und modernem Browser (wenn möglich)
---
## Mitmachen & Beitragen 🤝
<br>
- Links und Infos: [wiki.maglab.space](https://wiki.maglab.space/de/Projekte/F0rmF0551l) -> Projekte -> F0rmF0551l
- Ideen für neue Retro-Protokolle?
- FidoNet Support?
- BBS Integration?
- IRC Bot Interface?
- Serial Port Support?
- (Issues) und PRs sehr willkommen!
Note:
- Perfektes Projekt zum Rust lernen
- Viele interessante Protocol-Details
- Community-Driven Development
---
## Danke! 👾
<br>
Keep the retro spirit alive!
<br>
🕹️ 📟 💾 🖥️
---
## Q&A 🎤
Fragen? Ideen? Retro-Computing Stories?
Note:
- Hier ist Zeit für Diskussion und Erfahrungsaustausch
- Live Demo von speziellen Features auf Anfrage
- Zeige gerne auch den Source Code
{"title":"F0rmF0551l - When Retro Meets Reality","tags":"presentation, rust, retro-computing","type":"slide","slideOptions":{"transition":"slide","theme":"black","width":"80%"}}