This commit is contained in:
Robin Appelman 2023-04-08 23:21:21 +02:00
commit 6e456a6596
6 changed files with 212 additions and 0 deletions

View file

@ -7,6 +7,7 @@ mod pages;
pub use crate::config::Config;
use crate::config::Listen;
use crate::data::demo::{Demo, ListDemo};
use crate::pages::about::AboutPage;
use crate::pages::demo::DemoPage;
use crate::pages::index::Index;
use crate::pages::render;
@ -56,6 +57,7 @@ async fn main() -> Result<()> {
.route("/style.css", get(serve_compiled!("style.css")))
.route("/images/logo.png", get(serve_static!("../images/logo.png")))
.route("/images/logo.svg", get(serve_static!("../images/logo.svg")))
.route("/about", get(about))
.route("/:id", get(demo))
.layer(
TraceLayer::new_for_http().make_span_with(|request: &Request<_>| {
@ -102,6 +104,10 @@ async fn index(State(app): State<Arc<App>>) -> Result<Markup> {
Ok(render(Index { demos }))
}
async fn about(State(_app): State<Arc<App>>) -> Result<Markup> {
Ok(render(AboutPage { key: None }))
}
async fn demo(State(app): State<Arc<App>>, Path(id): Path<u32>) -> Result<Markup> {
let demo = Demo::by_id(&app.connection, id)
.await?

91
src/pages/about.rs Normal file
View file

@ -0,0 +1,91 @@
use crate::pages::plugin_section::PluginSection;
use crate::pages::Page;
use maud::{html, Markup};
use std::borrow::Cow;
pub struct AboutPage {
pub key: Option<String>,
}
impl AboutPage {
pub fn plugin_section(&self) -> PluginSection {
PluginSection {
key: self.key.as_deref(),
}
}
}
impl Page for AboutPage {
fn title(&self) -> Cow<'static, str> {
"About - demos.tf".into()
}
fn render(&self) -> Markup {
html! {
div {
section {
.title {
h3 { "About" }
}
p {
"demos.tf is a hosting platform for Team Fortress 2 demo files and automatic stv demo uploader."
}
}
section {
.title {
h3 { "Contact" }
}
p {
"Contact us using any of the following methods for feedback or questions."
}
p {
a href = "https://steamcommunity.com/id/icewind1991" { "Steam" }
" "
a href = "mailto:icewind@demos.tf" { "Email" }
" "
a href = "https://github.com/demostf" { "Github" }
}
}
(self.plugin_section())
section {
.title {
h3 { "Reporting issues" }
}
p {
"Any issue, bug or suggestion can be reported over on "
a href = "https://github.com/demostf/demos.tf/issues" { "Github" }
"."
}
}
section {
.title {
h3 { "API" }
}
p {
"The demos.tf data is available to 3rd parties using a REST api."
}
p {
"See the "
a href = "/api" { "API Documentation" }
" for details."
}
}
section {
.title {
h3 { "Donate" }
}
p {
"Storing demos isn't free, you can help paying the server costs by donating using PayPal."
}
form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top" {
input type = "hidden" name = "cmd" value = "_s-xclick";
input type = "hidden" name = "encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----";
input type = "image" src = "https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" name = "submit" alt = "PayPal - The safer, easier way to pay online!";
}
}
}
}
}
}

View file

@ -1,5 +1,7 @@
pub mod about;
pub mod demo;
pub mod index;
mod plugin_section;
use crate::asset::saved_asset_url;
use maud::{html, Markup, DOCTYPE};

View file

@ -0,0 +1,71 @@
use maud::{html, Markup, Render};
pub struct PluginSection<'a> {
pub key: Option<&'a str>,
}
impl Render for PluginSection<'_> {
fn render(&self) -> Markup {
html! {
section {
.title {
h3 { "Plugin" }
}
p {
"The demos.tf server plugin automatically uploads any stv demo recorded on the server and makes it"
"available for download."
}
p {
"Note that the plugin does "
u { "not" }
" automatically record demos on it's own but relies on other plugins like "
a href = "http://teamfortress.tv/thread/13598/?page=1#post-1" { "F2's RecordSTV" }
" to manage the recording of stv demos"
}
h5 { "How to install" }
ol {
li {
"Make sure "
a href = "http://wiki.alliedmods.net/Installing_SourceMod" { "SourceMod" }
" is installed on your server."
}
li {
"Make sure the "
a href = "https://github.com/spiretf/docker-comp-server/raw/master/curl.ext.so" { "cURL extension" }
" is installed on your server."
}
li {
"Download the "
a href = "https://github.com/demostf/plugin" { "plugin"}
"."
}
li {
"Upload the .smx file to "
code { "/tf/addons/sourcemod/plugins/" }
" on your server."
}
@if let None = self.key {
li {
"Login to retrieve your api-key."
}
}
li {
"Add the following code to"
code { "/tf/cfg/server.cfg" }
" on the server:"
pre {
"sm_demostf_apikey "
@if let Some(key) = self.key {
(key)
} @else {
"<<API KEY>>"
}
}
}
}
a.button.button-primary href = "https://github.com/demostf/plugin/raw/master/demostf.smx" { "Download" }
a.button href = "https://github.com/demostf/plugin/raw/master/demostf.sp" { "Source" }
}
}
}
}

41
style/section.css Normal file
View file

@ -0,0 +1,41 @@
section > div.title {
overflow: hidden;
padding-left: 30px;
margin-left: -30px;
margin-right: -30px;
}
section > div > h3 {
font-size: 22px;
display: inline-block;
padding: 0 5px;
position: relative;
margin-left: 20px;
margin-bottom: 0;
min-width: 50px;
}
section > div > h3:before,
section > div > h3:after {
background: #888;
content: "";
display: block;
height: 2px;
position: absolute;
top: 45%;
}
section > div > h3:before {
width: 100%;
margin-left: -20px;
right: 100%;
}
section > div > h3:after {
left: 100%;
width: 9999%;
}
section > div > h3 + * {
margin-top: 10px;
}

View file

@ -1,6 +1,7 @@
@import 'header.css';
@import 'footer.css';
@import 'pure.css';
@import 'section.css';
@import 'pages/index.css';
@import 'pages/demo.css';