forked from mirrors/relay
Add an 'About' section to the relay
This commit is contained in:
parent
5043892981
commit
a77a4cde22
9 changed files with 174 additions and 70 deletions
6
.env
6
.env
|
@ -1,6 +1,12 @@
|
||||||
HOSTNAME=localhost:8079
|
HOSTNAME=localhost:8079
|
||||||
PORT=8079
|
PORT=8079
|
||||||
|
HTTPS=false
|
||||||
|
DEBUG=true
|
||||||
RESTRICTED_MODE=true
|
RESTRICTED_MODE=true
|
||||||
|
VALIDATE_SIGNATURES=false
|
||||||
API_TOKEN=somesecretpassword
|
API_TOKEN=somesecretpassword
|
||||||
FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a> for inquiries"
|
FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a> for inquiries"
|
||||||
|
LOCAL_DOMAINS="masto.asonix.dog"
|
||||||
|
LOCAL_BLURB="<p>Welcome to my cool relay where I have cool relay things happening. I hope you enjoy your stay!</p>"
|
||||||
|
RUST_LOG=info
|
||||||
# OPENTELEMETRY_URL=http://localhost:4317
|
# OPENTELEMETRY_URL=http://localhost:4317
|
||||||
|
|
|
@ -100,7 +100,9 @@ TELEGRAM_TOKEN=secret
|
||||||
TELEGRAM_ADMIN_HANDLE=your_handle
|
TELEGRAM_ADMIN_HANDLE=your_handle
|
||||||
TLS_KEY=/path/to/key
|
TLS_KEY=/path/to/key
|
||||||
TLS_CERT=/path/to/cert
|
TLS_CERT=/path/to/cert
|
||||||
FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a>
|
FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a> for inquiries"
|
||||||
|
LOCAL_DOMAINS=masto.asonix.dog
|
||||||
|
LOCAL_BLURB="<p>Welcome to my cool relay where I have cool relay things happening. I hope you enjoy your stay!</p>"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Descriptions
|
#### Descriptions
|
||||||
|
@ -140,6 +142,10 @@ Optional - This is specified if you are running the relay directly on the intern
|
||||||
Optional - This is specified if you are running the relay directly on the internet and have a TLS certificate chain to provide HTTPS for your relay
|
Optional - This is specified if you are running the relay directly on the internet and have a TLS certificate chain to provide HTTPS for your relay
|
||||||
##### `FOOTER_BLURB`
|
##### `FOOTER_BLURB`
|
||||||
Optional - Add custom notes in the footer of the page
|
Optional - Add custom notes in the footer of the page
|
||||||
|
##### `LOCAL_DOMAINS`
|
||||||
|
Optional - domains of mastodon servers run by the same admin as the relay
|
||||||
|
##### `LOCAL_BLURB`
|
||||||
|
Optional - description for the relay
|
||||||
|
|
||||||
### Subscribing
|
### Subscribing
|
||||||
Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings.
|
Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings.
|
||||||
|
|
|
@ -41,7 +41,7 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
article {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #333;
|
color: #333;
|
||||||
border: 1px solid #e5e5e5;
|
border: 1px solid #e5e5e5;
|
||||||
|
@ -51,9 +51,17 @@ section {
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
padding-bottom: 32px;
|
padding-bottom: 32px;
|
||||||
|
|
||||||
|
section {
|
||||||
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
|
||||||
|
> h4:first-child,
|
||||||
> p:first-child {
|
> p:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
> p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
|
@ -67,13 +75,13 @@ section {
|
||||||
|
|
||||||
li {
|
li {
|
||||||
padding-top: 36px;
|
padding-top: 36px;
|
||||||
border-bottom: 1px solid #e5e5e5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.padded {
|
.padded {
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.local-explainer,
|
||||||
.joining {
|
.joining {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
@ -174,9 +182,11 @@ footer {
|
||||||
|
|
||||||
li {
|
li {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-bottom: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
article section {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +236,7 @@ footer {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
article {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
|
@ -38,6 +38,8 @@ pub(crate) struct ParsedConfig {
|
||||||
tls_key: Option<PathBuf>,
|
tls_key: Option<PathBuf>,
|
||||||
tls_cert: Option<PathBuf>,
|
tls_cert: Option<PathBuf>,
|
||||||
footer_blurb: Option<String>,
|
footer_blurb: Option<String>,
|
||||||
|
local_domains: Option<String>,
|
||||||
|
local_blurb: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -58,6 +60,8 @@ pub struct Config {
|
||||||
api_token: Option<String>,
|
api_token: Option<String>,
|
||||||
tls: Option<TlsConfig>,
|
tls: Option<TlsConfig>,
|
||||||
footer_blurb: Option<String>,
|
footer_blurb: Option<String>,
|
||||||
|
local_domains: Vec<String>,
|
||||||
|
local_blurb: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -115,6 +119,8 @@ impl std::fmt::Debug for Config {
|
||||||
.field("tls_key", &"[redacted]")
|
.field("tls_key", &"[redacted]")
|
||||||
.field("tls_cert", &"[redacted]")
|
.field("tls_cert", &"[redacted]")
|
||||||
.field("footer_blurb", &self.footer_blurb)
|
.field("footer_blurb", &self.footer_blurb)
|
||||||
|
.field("local_domains", &self.local_domains)
|
||||||
|
.field("local_blurb", &self.local_blurb)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,6 +145,8 @@ impl Config {
|
||||||
.set_default("tls_key", None as Option<&str>)?
|
.set_default("tls_key", None as Option<&str>)?
|
||||||
.set_default("tls_cert", None as Option<&str>)?
|
.set_default("tls_cert", None as Option<&str>)?
|
||||||
.set_default("footer_blurb", None as Option<&str>)?
|
.set_default("footer_blurb", None as Option<&str>)?
|
||||||
|
.set_default("local_domains", None as Option<&str>)?
|
||||||
|
.set_default("local_blurb", None as Option<&str>)?
|
||||||
.add_source(Environment::default())
|
.add_source(Environment::default())
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
|
@ -160,6 +168,13 @@ impl Config {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let local_domains = config
|
||||||
|
.local_domains
|
||||||
|
.iter()
|
||||||
|
.flat_map(|s| s.split(","))
|
||||||
|
.map(|d| d.to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
hostname: config.hostname,
|
hostname: config.hostname,
|
||||||
addr: config.addr,
|
addr: config.addr,
|
||||||
|
@ -177,6 +192,8 @@ impl Config {
|
||||||
api_token: config.api_token,
|
api_token: config.api_token,
|
||||||
tls,
|
tls,
|
||||||
footer_blurb: config.footer_blurb,
|
footer_blurb: config.footer_blurb,
|
||||||
|
local_domains,
|
||||||
|
local_blurb: config.local_blurb,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +246,20 @@ impl Config {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn local_blurb(&self) -> Option<crate::templates::Html<&str>> {
|
||||||
|
if let Some(blurb) = &self.local_blurb {
|
||||||
|
if !blurb.is_empty() {
|
||||||
|
return Some(crate::templates::Html(blurb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn local_domains(&self) -> &[String] {
|
||||||
|
&self.local_domains
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn sled_path(&self) -> &PathBuf {
|
pub(crate) fn sled_path(&self) -> &PathBuf {
|
||||||
&self.sled_path
|
&self.sled_path
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,29 @@ pub(crate) async fn route(
|
||||||
state: web::Data<State>,
|
state: web::Data<State>,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let mut nodes = state.node_cache().nodes().await?;
|
let all_nodes = state.node_cache().nodes().await?;
|
||||||
|
|
||||||
|
let mut nodes = Vec::new();
|
||||||
|
let mut local = Vec::new();
|
||||||
|
|
||||||
|
for node in all_nodes {
|
||||||
|
if node
|
||||||
|
.base
|
||||||
|
.authority_str()
|
||||||
|
.map(|authority| {
|
||||||
|
config
|
||||||
|
.local_domains()
|
||||||
|
.iter()
|
||||||
|
.find(|domain| domain.as_str() == authority)
|
||||||
|
.is_some()
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
local.push(node);
|
||||||
|
} else {
|
||||||
|
nodes.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nodes.sort_by(|lhs, rhs| match (open_reg(lhs), open_reg(rhs)) {
|
nodes.sort_by(|lhs, rhs| match (open_reg(lhs), open_reg(rhs)) {
|
||||||
(true, true) | (false, false) => std::cmp::Ordering::Equal,
|
(true, true) | (false, false) => std::cmp::Ordering::Equal,
|
||||||
|
@ -37,7 +59,7 @@ pub(crate) async fn route(
|
||||||
|
|
||||||
let mut buf = BufWriter::new(Vec::new());
|
let mut buf = BufWriter::new(Vec::new());
|
||||||
|
|
||||||
crate::templates::index(&mut buf, &nodes, &config)?;
|
crate::templates::index(&mut buf, &local, &nodes, &config)?;
|
||||||
let buf = buf.into_inner().map_err(|e| {
|
let buf = buf.into_inner().map_err(|e| {
|
||||||
tracing::error!("Error rendering template, {}", e.error());
|
tracing::error!("Error rendering template, {}", e.error());
|
||||||
ErrorKind::FlushBuffer
|
ErrorKind::FlushBuffer
|
||||||
|
|
|
@ -4,7 +4,7 @@ data::Node,
|
||||||
templates::{info, instance, statics::index_css},
|
templates::{info, instance, statics::index_css},
|
||||||
};
|
};
|
||||||
|
|
||||||
@(nodes: &[Node], config: &Config)
|
@(local: &[Node], nodes: &[Node], config: &Config)
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
|
@ -24,16 +24,23 @@ templates::{info, instance, statics::index_css},
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
@if !local.is_empty() || config.local_blurb().is_some() {
|
||||||
<h3>@nodes.len() Connected Servers</h3>
|
<article>
|
||||||
@if nodes.is_empty() {
|
<h3>About</h3>
|
||||||
<p>There are no connected servers at this time.</p>
|
<section class="local-explainer">
|
||||||
|
@if let Some(blurb) = config.local_blurb() {
|
||||||
|
@blurb
|
||||||
} else {
|
} else {
|
||||||
|
<p>These domains are run by the same admins as this relay.</p>
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
@if !local.is_empty() {
|
||||||
<ul>
|
<ul>
|
||||||
@for node in nodes {
|
@for node in local {
|
||||||
@if let Some(inst) = node.instance.as_ref() {
|
@if let Some(inst) = node.instance.as_ref() {
|
||||||
<li>
|
<li>
|
||||||
@:instance(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(), &node.base)
|
@:instance(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
|
||||||
|
&node.base)
|
||||||
</li>
|
</li>
|
||||||
} else {
|
} else {
|
||||||
@if let Some(inf) = node.info.as_ref() {
|
@if let Some(inf) = node.info.as_ref() {
|
||||||
|
@ -45,10 +52,32 @@ templates::{info, instance, statics::index_css},
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
</section>
|
</article>
|
||||||
<section>
|
}
|
||||||
|
@if !nodes.is_empty() {
|
||||||
|
<article>
|
||||||
|
<h3>@nodes.len() Connected Servers</h3>
|
||||||
|
<ul>
|
||||||
|
@for node in nodes {
|
||||||
|
@if let Some(inst) = node.instance.as_ref() {
|
||||||
|
<li>
|
||||||
|
@:instance(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
|
||||||
|
&node.base)
|
||||||
|
</li>
|
||||||
|
} else {
|
||||||
|
@if let Some(inf) = node.info.as_ref() {
|
||||||
|
<li>
|
||||||
|
@:info(inf, &node.base)
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
}
|
||||||
|
<article>
|
||||||
<h3>Joining</h3>
|
<h3>Joining</h3>
|
||||||
<article class="joining">
|
<section class="joining">
|
||||||
@if config.restricted_mode() {
|
@if config.restricted_mode() {
|
||||||
<h4>
|
<h4>
|
||||||
This relay is Restricted
|
This relay is Restricted
|
||||||
|
@ -80,8 +109,8 @@ templates::{info, instance, statics::index_css},
|
||||||
Consult the documentation for your server. It's likely that it follows either
|
Consult the documentation for your server. It's likely that it follows either
|
||||||
Mastodon or Pleroma's relay formatting.
|
Mastodon or Pleroma's relay formatting.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
|
||||||
</section>
|
</section>
|
||||||
|
</article>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
@if let Some(blurb) = config.footer_blurb() {
|
@if let Some(blurb) = config.footer_blurb() {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
@(info: &Info, base: &IriString)
|
@(info: &Info, base: &IriString)
|
||||||
|
|
||||||
<article class="info">
|
<section class="info">
|
||||||
@if let Some(authority) = base.authority_str() {
|
@if let Some(authority) = base.authority_str() {
|
||||||
<h4 class="padded"><a href="@base">@authority</a></h4>
|
<h4 class="padded"><a href="@base">@authority</a></h4>
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,4 @@
|
||||||
Registration is open
|
Registration is open
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</section>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &IriString)
|
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &IriString)
|
||||||
|
|
||||||
<article class="instance">
|
<section class="instance">
|
||||||
<h4 class="padded"><a href="@base">@instance.title</a></h4>
|
<h4 class="padded"><a href="@base">@instance.title</a></h4>
|
||||||
<p class="padded">
|
<p class="padded">
|
||||||
@if let Some(software) = software {
|
@if let Some(software) = software {
|
||||||
|
@ -34,4 +34,4 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</article>
|
</section>
|
||||||
|
|
Loading…
Reference in a new issue