atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
bf5f8cb6f60f6e974991335cdfec63b7874a37bf
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: src/http/links.rs

8b8e83329a1datagen2026-10-12 12:01 UTC1
use std::fmt::Write as _;
8b8e83329a1datagen2026-10-12 12:01 UTC2
a11497af08aaatagen2026-10-13 12:04 UTC3
use super::{run::RunResource, runs};
a11497af08aaatagen2026-10-13 12:04 UTC4
use crate::game::{Branch, Run, SHOP};
8b8e83329a1datagen2026-10-12 12:01 UTC5
8b8e83329a1datagen2026-10-12 12:01 UTC6
pub const REL_BASE: &str = "https://jelq.dev/rels/";
8b8e83329a1datagen2026-10-12 12:01 UTC7
8b8e83329a1datagen2026-10-12 12:01 UTC8
/// One RFC 8288 link. `allow` and `lubricant` are extension attributes (§3), so a client never
8b8e83329a1datagen2026-10-12 12:01 UTC9
/// has to guess what a target accepts.
8b8e83329a1datagen2026-10-12 12:01 UTC10
struct Link<'a> {
8b8e83329a1datagen2026-10-12 12:01 UTC11
    href: &'a str,
8b8e83329a1datagen2026-10-12 12:01 UTC12
    rel: &'a str,
8b8e83329a1datagen2026-10-12 12:01 UTC13
    allow: &'a str,
8b8e83329a1datagen2026-10-12 12:01 UTC14
    title: Option<&'a str>,
8b8e83329a1datagen2026-10-12 12:01 UTC15
    lubricant: Option<&'a str>,
8b8e83329a1datagen2026-10-12 12:01 UTC16
}
8b8e83329a1datagen2026-10-12 12:01 UTC17
8b8e83329a1datagen2026-10-12 12:01 UTC18
impl Link<'_> {
8b8e83329a1datagen2026-10-12 12:01 UTC19
    fn write(&self, out: &mut String) {
8b8e83329a1datagen2026-10-12 12:01 UTC20
        if !out.is_empty() {
8b8e83329a1datagen2026-10-12 12:01 UTC21
            out.push_str(", ");
8b8e83329a1datagen2026-10-12 12:01 UTC22
        }
8b8e83329a1datagen2026-10-12 12:01 UTC23
        let _ = write!(out, "<{}>; rel=\"{REL_BASE}{}\"", self.href, self.rel);
8b8e83329a1datagen2026-10-12 12:01 UTC24
        if let Some(title) = self.title {
8b8e83329a1datagen2026-10-12 12:01 UTC25
            let _ = write!(out, "; title=\"{title}\"");
8b8e83329a1datagen2026-10-12 12:01 UTC26
        }
8b8e83329a1datagen2026-10-12 12:01 UTC27
        let _ = write!(out, "; allow=\"{}\"", self.allow);
8b8e83329a1datagen2026-10-12 12:01 UTC28
        if let Some(rule) = self.lubricant {
8b8e83329a1datagen2026-10-12 12:01 UTC29
            let _ = write!(out, "; lubricant=\"{rule}\"");
8b8e83329a1datagen2026-10-12 12:01 UTC30
        }
8b8e83329a1datagen2026-10-12 12:01 UTC31
    }
8b8e83329a1datagen2026-10-12 12:01 UTC32
}
8b8e83329a1datagen2026-10-12 12:01 UTC33
8b8e83329a1datagen2026-10-12 12:01 UTC34
pub fn header(run: &Run) -> String {
8b8e83329a1datagen2026-10-12 12:01 UTC35
    let reach = run.reach();
8b8e83329a1datagen2026-10-12 12:01 UTC36
    let mut out = String::new();
8b8e83329a1datagen2026-10-12 12:01 UTC37
    let resources: [(&str, &RunResource, bool); 15] = [
8b8e83329a1datagen2026-10-12 12:01 UTC38
        ("", &runs::RUN, true),
8b8e83329a1datagen2026-10-12 12:01 UTC39
        ("floor", &runs::FLOOR, true),
8b8e83329a1datagen2026-10-12 12:01 UTC40
        ("length", &runs::LENGTH, true),
8b8e83329a1datagen2026-10-12 12:01 UTC41
        ("foreskin", &runs::FORESKIN, reach.foreskin),
8b8e83329a1datagen2026-10-12 12:01 UTC42
        ("inventory", &runs::INVENTORY, true),
8b8e83329a1datagen2026-10-12 12:01 UTC43
        ("techniques", &runs::TECHNIQUES, true),
8b8e83329a1datagen2026-10-12 12:01 UTC44
        ("drawer", &runs::DRAWER, reach.drawer),
8b8e83329a1datagen2026-10-12 12:01 UTC45
        ("kitchen", &runs::KITCHEN, reach.kitchen),
a11497af08aaatagen2026-10-13 12:04 UTC46
        ("thread", &runs::THREAD, reach.thread),
8b8e83329a1datagen2026-10-12 12:01 UTC47
        ("grip", &runs::GRIP, true),
8b8e83329a1datagen2026-10-12 12:01 UTC48
        ("shop", &runs::SHOP, reach.shop),
8b8e83329a1datagen2026-10-12 12:01 UTC49
        ("portal", &runs::PORTAL, reach.portal),
8b8e83329a1datagen2026-10-12 12:01 UTC50
        ("elder", &runs::ELDER, reach.elder),
8b8e83329a1datagen2026-10-12 12:01 UTC51
        ("footage", &runs::FOOTAGE, reach.footage),
8b8e83329a1datagen2026-10-12 12:01 UTC52
        ("diagnosis", &runs::DIAGNOSIS, reach.diagnosis),
8b8e83329a1datagen2026-10-12 12:01 UTC53
    ];
8b8e83329a1datagen2026-10-12 12:01 UTC54
    for (rel, target, _) in resources.iter().filter(|(_, _, relevant)| *relevant) {
8b8e83329a1datagen2026-10-12 12:01 UTC55
        let href = if rel.is_empty() {
8b8e83329a1datagen2026-10-12 12:01 UTC56
            run.path("")
8b8e83329a1datagen2026-10-12 12:01 UTC57
        } else {
8b8e83329a1datagen2026-10-12 12:01 UTC58
            run.path(&format!("/{rel}"))
8b8e83329a1datagen2026-10-12 12:01 UTC59
        };
8b8e83329a1datagen2026-10-12 12:01 UTC60
        Link {
8b8e83329a1datagen2026-10-12 12:01 UTC61
            href: &href,
8b8e83329a1datagen2026-10-12 12:01 UTC62
            rel: if rel.is_empty() { "run" } else { rel },
8b8e83329a1datagen2026-10-12 12:01 UTC63
            allow: &target.resource.allow(run),
8b8e83329a1datagen2026-10-12 12:01 UTC64
            title: None,
8b8e83329a1datagen2026-10-12 12:01 UTC65
            lubricant: None,
8b8e83329a1datagen2026-10-12 12:01 UTC66
        }
8b8e83329a1datagen2026-10-12 12:01 UTC67
        .write(&mut out);
8b8e83329a1datagen2026-10-12 12:01 UTC68
    }
8b8e83329a1datagen2026-10-12 12:01 UTC69
    if reach.branch_pending {
8b8e83329a1datagen2026-10-12 12:01 UTC70
        for (branch, title) in [
8b8e83329a1datagen2026-10-12 12:01 UTC71
            (Branch::Forum, "Read the forum"),
8b8e83329a1datagen2026-10-12 12:01 UTC72
            (Branch::CloseTab, "Close the tab"),
8b8e83329a1datagen2026-10-12 12:01 UTC73
        ] {
8b8e83329a1datagen2026-10-12 12:01 UTC74
            Link {
8b8e83329a1datagen2026-10-12 12:01 UTC75
                href: &run.path(&format!("/branches/{}", branch.slug())),
8b8e83329a1datagen2026-10-12 12:01 UTC76
                rel: "branch",
8b8e83329a1datagen2026-10-12 12:01 UTC77
                allow: "POST",
8b8e83329a1datagen2026-10-12 12:01 UTC78
                title: Some(title),
8b8e83329a1datagen2026-10-12 12:01 UTC79
                lubricant: None,
8b8e83329a1datagen2026-10-12 12:01 UTC80
            }
8b8e83329a1datagen2026-10-12 12:01 UTC81
            .write(&mut out);
8b8e83329a1datagen2026-10-12 12:01 UTC82
        }
8b8e83329a1datagen2026-10-12 12:01 UTC83
    }
8b8e83329a1datagen2026-10-12 12:01 UTC84
    let run_path = run.path("");
8b8e83329a1datagen2026-10-12 12:01 UTC85
    for technique in run.techniques_now() {
8b8e83329a1datagen2026-10-12 12:01 UTC86
        let name = technique.name();
8b8e83329a1datagen2026-10-12 12:01 UTC87
        Link {
8b8e83329a1datagen2026-10-12 12:01 UTC88
            href: &format!("{run_path}?technique={name}"),
8b8e83329a1datagen2026-10-12 12:01 UTC89
            rel: "technique",
8b8e83329a1datagen2026-10-12 12:01 UTC90
            allow: "JELQ",
8b8e83329a1datagen2026-10-12 12:01 UTC91
            title: Some(name),
8b8e83329a1datagen2026-10-12 12:01 UTC92
            lubricant: technique.lubricant(),
8b8e83329a1datagen2026-10-12 12:01 UTC93
        }
8b8e83329a1datagen2026-10-12 12:01 UTC94
        .write(&mut out);
8b8e83329a1datagen2026-10-12 12:01 UTC95
    }
8b8e83329a1datagen2026-10-12 12:01 UTC96
    if reach.shopping {
8b8e83329a1datagen2026-10-12 12:01 UTC97
        for item in SHOP {
8b8e83329a1datagen2026-10-12 12:01 UTC98
            let Some(price) = run.price(item) else {
8b8e83329a1datagen2026-10-12 12:01 UTC99
                continue;
8b8e83329a1datagen2026-10-12 12:01 UTC100
            };
8b8e83329a1datagen2026-10-12 12:01 UTC101
            Link {
8b8e83329a1datagen2026-10-12 12:01 UTC102
                href: &run.path(&format!("/shop/{}", item.slug())),
8b8e83329a1datagen2026-10-12 12:01 UTC103
                rel: "shop-item",
8b8e83329a1datagen2026-10-12 12:01 UTC104
                allow: "POST",
8b8e83329a1datagen2026-10-12 12:01 UTC105
                title: Some(&format!("{} for {price}", item.slug())),
8b8e83329a1datagen2026-10-12 12:01 UTC106
                lubricant: None,
8b8e83329a1datagen2026-10-12 12:01 UTC107
            }
8b8e83329a1datagen2026-10-12 12:01 UTC108
            .write(&mut out);
8b8e83329a1datagen2026-10-12 12:01 UTC109
        }
8b8e83329a1datagen2026-10-12 12:01 UTC110
    }
8b8e83329a1datagen2026-10-12 12:01 UTC111
    out
8b8e83329a1datagen2026-10-12 12:01 UTC112
}