diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index d19f844..27ec57d 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -35,3 +35,7 @@ jobs: run: ./scripts/release.sh env: DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }} + PATREON_ACCESS_TOKEN: ${{ secrets.PATREON_ACCESS_TOKEN }} + PATREON_REFRESH_TOKEN: ${{ secrets.PATREON_REFRESH_TOKEN }} + PATREON_CLIENT_ID: ${{ secrets.PATREON_CLIENT_ID }} + PATREON_CLIENT_SECRET: ${{ secrets.PATREON_CLIENT_SECRET }} diff --git a/Cargo.lock b/Cargo.lock index 4e8fb41..b6d929e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,15 +42,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" -[[package]] -name = "aho-corasick" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -dependencies = [ - "memchr", -] - [[package]] name = "aho-corasick" version = "0.7.13" @@ -297,7 +288,7 @@ dependencies = [ "lazy_static", "pest", "pest_derive", - "regex 1.3.9", + "regex", "twoway 0.2.1", "typed-arena", "unicode_categories", @@ -401,7 +392,7 @@ dependencies = [ "itertools", "lazy_static", "once_cell", - "percent-encoding 2.1.0", + "percent-encoding", "pest", "pest_consume", "pest_generator", @@ -411,7 +402,7 @@ dependencies = [ "serde_cbor", "sha2", "smallvec", - "url 2.1.1", + "url", "walkdir", ] @@ -487,7 +478,7 @@ dependencies = [ "atty", "humantime", "log 0.4.8", - "regex 1.3.9", + "regex", "termcolor", ] @@ -839,17 +830,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.2.0" @@ -912,20 +892,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonapi" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "814fe35a3361c079fbed80fee6901a041c077c9ffe1a7cb13a31de064e1e97b5" -dependencies = [ - "error-chain", - "log 0.4.8", - "queryst", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "jsonfeed" version = "0.3.0" @@ -1270,7 +1236,6 @@ version = "0.1.0" dependencies = [ "chrono", "envy", - "jsonapi", "log 0.3.9", "pretty_env_logger", "reqwest", @@ -1280,12 +1245,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.1.0" @@ -1511,19 +1470,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "queryst" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee648fdfde06a88a03a225276e2d52c9243439fba1af36362ad6bbe5ea4658b0" -dependencies = [ - "lazy_static", - "regex 0.2.11", - "serde", - "serde_json", - "url 1.7.2", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -1721,38 +1667,16 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -dependencies = [ - "aho-corasick 0.6.10", - "memchr", - "regex-syntax 0.5.6", - "thread_local 0.3.6", - "utf8-ranges", -] - [[package]] name = "regex" version = "1.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" dependencies = [ - "aho-corasick 0.7.13", + "aho-corasick", "memchr", - "regex-syntax 0.6.18", - "thread_local 1.0.1", -] - -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -dependencies = [ - "ucd-util", + "regex-syntax", + "thread_local", ] [[package]] @@ -1791,14 +1715,14 @@ dependencies = [ "mime 0.3.16", "mime_guess 2.0.3", "native-tls", - "percent-encoding 2.1.0", + "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-tls", - "url 2.1.1", + "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1942,7 +1866,7 @@ dependencies = [ "dhall_proc_macros", "doc-comment", "serde", - "url 2.1.1", + "url", ] [[package]] @@ -1965,7 +1889,7 @@ dependencies = [ "dtoa", "itoa", "serde", - "url 2.1.1", + "url", ] [[package]] @@ -2018,7 +1942,7 @@ checksum = "5c95c7e58b4461fec85bdd58f271bcd416ecc4d630c3ac280b60efa3421016b7" dependencies = [ "chrono", "chrono_utils", - "url 2.1.1", + "url", "xml-rs", ] @@ -2133,15 +2057,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -dependencies = [ - "lazy_static", -] - [[package]] name = "thread_local" version = "1.0.1" @@ -2281,7 +2196,7 @@ dependencies = [ "log 0.4.8", "rand 0.7.3", "sha-1", - "url 2.1.1", + "url", "utf-8", ] @@ -2322,12 +2237,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" -[[package]] -name = "ucd-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236" - [[package]] name = "unchecked-index" version = "0.2.2" @@ -2388,26 +2297,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0", + "idna", "matches", - "percent-encoding 2.1.0", + "percent-encoding", ] [[package]] @@ -2422,12 +2320,6 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" -[[package]] -name = "utf8-ranges" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" - [[package]] name = "vcpkg" version = "0.2.10" diff --git a/lib/patreon/Cargo.toml b/lib/patreon/Cargo.toml index 1e77c5a..47298b5 100644 --- a/lib/patreon/Cargo.toml +++ b/lib/patreon/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" [dependencies] chrono = { version = "0.4", features = ["serde"] } -jsonapi = "0.6.6" reqwest = { version = "0.10", features = ["json"] } serde_json = "1.0" serde = { version = "1", features = ["derive"] } diff --git a/lib/patreon/src/lib.rs b/lib/patreon/src/lib.rs index 1f5df72..07e6228 100644 --- a/lib/patreon/src/lib.rs +++ b/lib/patreon/src/lib.rs @@ -1,6 +1,4 @@ #[macro_use] -extern crate jsonapi; -#[macro_use] extern crate log; use serde::{Deserialize, Serialize}; @@ -9,6 +7,7 @@ use chrono::prelude::*; pub type Campaigns = Vec>; pub type Pledges = Vec>; +pub type Users = Vec>; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Campaign { diff --git a/scripts/release.sh b/scripts/release.sh index 7458012..11848cd 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,5 +1,6 @@ #!/usr/bin/env nix-shell #! nix-shell -p doctl -p kubectl -i bash +nix-env -if ./nix/dhall-yaml.nix doctl kubernetes cluster kubeconfig save kubermemes dhall-to-yaml-ng < ./site.dhall | kubectl apply -n apps -f - kubectl rollout status -n apps deployment/christinewebsite diff --git a/site.dhall b/site.dhall index 48d66db..0850da4 100644 --- a/site.dhall +++ b/site.dhall @@ -8,11 +8,27 @@ let tag = env:GITHUB_SHA as Text ? "latest" let image = "xena/christinewebsite:${tag}" -let prefix = env:SITE_PREFIX as Text ? "" - let vars : List kubernetes.EnvVar.Type - = [ kubernetes.EnvVar::{ name = "PORT", value = Some "3030" } ] + = [ kubernetes.EnvVar::{ name = "PORT", value = Some "3030" } + , kubernetes.EnvVar::{ name = "RUST_LOG", value = Some "info" } + , kubernetes.EnvVar::{ + , name = "PATREON_CLIENT_ID" + , value = Some env:PATREON_CLIENT_ID as Text + } + , kubernetes.EnvVar::{ + , name = "PATREON_CLIENT_SECRET" + , value = Some env:PATREON_CLIENT_SECRET as Text + } + , kubernetes.EnvVar::{ + , name = "PATREON_ACCESS_TOKEN" + , value = Some env:PATREON_ACCESS_TOKEN as Text + } + , kubernetes.EnvVar::{ + , name = "PATREON_REFRESH_TOKEN" + , value = Some env:PATREON_REFRESH_TOKEN as Text + } + ] in kms.app.make kms.app.Config::{ diff --git a/src/app.rs b/src/app.rs index 272e673..6b27e0f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -30,6 +30,23 @@ pub fn markdown(inp: &str) -> String { markdown_to_html(inp, &options) } +async fn patrons() -> Result> { + use patreon::*; + let creds: Credentials = envy::prefixed("PATREON_").from_env().unwrap(); + let cli = Client::new(creds); + + if let Ok(camp) = cli.campaign().await { + let id = camp.data[0].id.clone(); + if let Ok(users) = cli.pledges(id).await { + Ok(Some(users)) + } else { + Ok(None) + } + } else { + Ok(None) + } +} + pub const ICON: &'static str = "https://christine.website/static/img/avatar.png"; pub struct State { @@ -44,9 +61,10 @@ pub struct State { pub rf: rss::Channel, pub af: atom::Feed, pub sitemap: Vec, + pub patrons: Option, } -pub fn init(cfg: PathBuf) -> Result { +pub async fn init(cfg: PathBuf) -> Result { let cfg: Config = serde_dhall::from_file(cfg).parse()?; let sb = cfg.signalboost.clone(); let resume = fs::read_to_string(cfg.resume_fname.clone())?; @@ -151,15 +169,16 @@ pub fn init(cfg: PathBuf) -> Result { af: af, rf: rf, sitemap: sm, + patrons: patrons().await?, }) } #[cfg(test)] mod tests { use anyhow::Result; - #[test] - fn init() -> Result<()> { - super::init("./config.dhall".into())?; + #[tokio::test] + async fn init() -> Result<()> { + super::init("./config.dhall".into()).await?; Ok(()) } } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index fc0233b..6f785ff 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -37,6 +37,15 @@ pub async fn resume(state: Arc) -> Result { Response::builder().html(|o| templates::resume_html(o, Html(state.resume.clone()))) } +pub async fn patrons(state: Arc) -> Result { + HIT_COUNTER.with_label_values(&["patrons"]).inc(); + let state = state.clone(); + match &state.patrons { + None => Response::builder().html(|o| templates::error_html(o, "Could not load patrons, let me know the API token expired again".to_string())), + Some(patrons) => Response::builder().html(|o| templates::patrons_html(o, patrons.clone())) + } +} + pub async fn signalboost(state: Arc) -> Result { HIT_COUNTER.with_label_values(&["signalboost"]).inc(); let state = state.clone(); diff --git a/src/main.rs b/src/main.rs index 51075c7..aa5400e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ async fn main() -> Result<()> { .unwrap_or("./config.dhall".into()) .as_str() .into(), - )?); + ).await?); let healthcheck = warp::get().and(warp::path(".within").and(warp::path("health")).map(|| "OK")); @@ -79,7 +79,6 @@ async fn main() -> Result<()> { ); let index = warp::get().and(path::end().and_then(handlers::index)); - let contact = warp::path!("contact").and_then(handlers::contact); let feeds = warp::path!("feeds").and_then(handlers::feeds); let resume = warp::path!("resume") @@ -88,6 +87,9 @@ async fn main() -> Result<()> { let signalboost = warp::path!("signalboost") .and(with_state(state.clone())) .and_then(handlers::signalboost); + let patrons = warp::path!("patrons") + .and(with_state(state.clone())) + .and_then(handlers::patrons); let files = warp::path("static").and(warp::fs::dir("./static")); let css = warp::path("css").and(warp::fs::dir("./css")); @@ -126,7 +128,7 @@ async fn main() -> Result<()> { }); let site = index - .or(contact.or(feeds).or(resume.or(signalboost))) + .or(contact.or(feeds).or(resume.or(signalboost)).or(patrons)) .or(blog_index.or(series.or(series_view).or(post_view))) .or(gallery_index.or(gallery_post_view)) .or(talk_index.or(talk_post_view)) diff --git a/templates/patrons.rs.html b/templates/patrons.rs.html new file mode 100644 index 0000000..c5f939c --- /dev/null +++ b/templates/patrons.rs.html @@ -0,0 +1,20 @@ +@use patreon::Users; +@use super::{header_html, footer_html}; + +@(users: Users) + +@:header_html(Some("Patrons"), None) + +

Patrons

+ +

These awesome people donate to me on Patreon. If you would like to show up in this list, please donate to me on Patreon. This is refreshed every time the site is deployed.

+ +

+

    + @for user in users { +
  • @user.attributes.full_name
  • + } +
+

+ +@:footer_html()