Compare commits

...

4 Commits

9 changed files with 97 additions and 54 deletions

60
Cargo.lock generated
View File

@ -95,6 +95,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"getrandom 0.2.10",
"once_cell", "once_cell",
"version_check", "version_check",
] ]
@ -958,13 +959,13 @@ dependencies = [
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.27.2" version = "0.29.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa"
dependencies = [ dependencies = [
"cssparser-macros", "cssparser-macros",
"dtoa-short", "dtoa-short",
"itoa 0.4.8", "itoa",
"matches", "matches",
"phf 0.8.0", "phf 0.8.0",
"proc-macro2", "proc-macro2",
@ -1099,6 +1100,16 @@ dependencies = [
"dtoa", "dtoa",
] ]
[[package]]
name = "duplicate"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de78e66ac9061e030587b2a2e75cc88f22304913c907b11307bca737141230cb"
dependencies = [
"heck 0.4.1",
"proc-macro-error",
]
[[package]] [[package]]
name = "ego-tree" name = "ego-tree"
version = "0.6.2" version = "0.6.2"
@ -1702,12 +1713,6 @@ dependencies = [
"either", "either",
] ]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.6" version = "1.0.6"
@ -2723,15 +2728,16 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "scraper" name = "scraper"
version = "0.13.0" version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5684396b456f3eb69ceeb34d1b5cb1a2f6acf7ca4452131efa3ba0ee2c2d0a70" checksum = "59e25654b5e9fd557a67dbaab5a5d36b8c448d0561beb4c041b6dbb902eddfa6"
dependencies = [ dependencies = [
"ahash 0.8.3",
"cssparser", "cssparser",
"ego-tree", "ego-tree",
"getopts", "getopts",
"html5ever", "html5ever",
"matches", "once_cell",
"selectors", "selectors",
"smallvec", "smallvec",
"tendril", "tendril",
@ -2928,22 +2934,20 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]] [[package]]
name = "selectors" name = "selectors"
version = "0.22.0" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cssparser", "cssparser",
"derive_more", "derive_more",
"fxhash", "fxhash",
"log", "log",
"matches",
"phf 0.8.0", "phf 0.8.0",
"phf_codegen 0.8.0", "phf_codegen 0.8.0",
"precomputed-hash", "precomputed-hash",
"servo_arc", "servo_arc",
"smallvec", "smallvec",
"thin-slice",
] ]
[[package]] [[package]]
@ -2993,7 +2997,7 @@ version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [ dependencies = [
"itoa 1.0.6", "itoa",
"ryu", "ryu",
"serde", "serde",
] ]
@ -3016,16 +3020,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"itoa 1.0.6", "itoa",
"ryu", "ryu",
"serde", "serde",
] ]
[[package]] [[package]]
name = "servo_arc" name = "servo_arc"
version = "0.1.1" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741"
dependencies = [ dependencies = [
"nodrop", "nodrop",
"stable_deref_trait", "stable_deref_trait",
@ -3210,7 +3214,7 @@ dependencies = [
"hkdf 0.12.3", "hkdf 0.12.3",
"hmac 0.12.1", "hmac 0.12.1",
"indexmap", "indexmap",
"itoa 1.0.6", "itoa",
"libc", "libc",
"log", "log",
"md-5", "md-5",
@ -3470,12 +3474,6 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thin-slice"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.40"
@ -3509,12 +3507,13 @@ dependencies = [
[[package]] [[package]]
name = "tildes-parser" name = "tildes-parser"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.bauke.xyz/tildes-community/tildes-parser.git?rev=08bf7ed#08bf7ed29e10ba6012afcd57cea263e9f0a707e9" source = "git+https://git.bauke.xyz/tildes-community/tildes-parser.git?rev=6f0d4d394d533a331b0c9cf19fe80d60f0865ca7#6f0d4d394d533a331b0c9cf19fe80d60f0865ca7"
dependencies = [ dependencies = [
"color-eyre", "duplicate",
"lazy_static", "lazy_static",
"regex", "regex",
"scraper", "scraper",
"thiserror",
] ]
[[package]] [[package]]
@ -3529,6 +3528,7 @@ dependencies = [
"dotenvy", "dotenvy",
"grass", "grass",
"plotters", "plotters",
"scraper",
"sea-orm", "sea-orm",
"sea-orm-migration", "sea-orm-migration",
"surf", "surf",
@ -3569,7 +3569,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [ dependencies = [
"itoa 1.0.6", "itoa",
"serde", "serde",
"time-core", "time-core",
"time-macros 0.2.9", "time-macros 0.2.9",

View File

@ -18,6 +18,7 @@ chrono = "0.4.22"
color-eyre = "0.6.2" color-eyre = "0.6.2"
dotenvy = "0.15.5" dotenvy = "0.15.5"
grass = "0.11.2" grass = "0.11.2"
scraper = "0.16.0"
sea-orm-migration = "0.11.3" sea-orm-migration = "0.11.3"
tracing = "0.1.36" tracing = "0.1.36"
@ -41,7 +42,7 @@ version = "2.3.2"
[dependencies.tildes-parser] [dependencies.tildes-parser]
git = "https://git.bauke.xyz/tildes-community/tildes-parser.git" git = "https://git.bauke.xyz/tildes-community/tildes-parser.git"
rev = "08bf7ed" rev = "6f0d4d394d533a331b0c9cf19fe80d60f0865ca7"
[dependencies.tracing-subscriber] [dependencies.tracing-subscriber]
features = ["env-filter"] features = ["env-filter"]

View File

@ -29,12 +29,9 @@ impl UserCountChart {
group_name: &str, group_name: &str,
render_point_circles: bool, render_point_circles: bool,
truncate: bool, truncate: bool,
output_dir: &str,
) -> Result<PathBuf> { ) -> Result<PathBuf> {
let parent = if truncate { let parent = parent.join(format!("{}/user-count", output_dir));
parent.join("charts/user-count")
} else {
parent.join("charts-untruncated/user-count")
};
create_dir_all(&parent).await?; create_dir_all(&parent).await?;
let (mut datapoints, mut min_count, mut max_count) = (vec![], i64::MAX, 0); let (mut datapoints, mut min_count, mut max_count) = (vec![], i64::MAX, 0);

View File

@ -115,9 +115,31 @@ pub async fn run() -> Result<()> {
groups: GroupDataModel::get_n_most_recent(&db, 31, &group.name) groups: GroupDataModel::get_n_most_recent(&db, 31, &group.name)
.await?, .await?,
}; };
chart
.render(&output, &group.name, true, true, "charts")
.await?;
chart
.render(&output, &group.name, true, false, "charts-untruncated")
.await?;
chart.render(&output, &group.name, true, true).await?; {
chart.render(&output, &group.name, true, false).await?; let total_chart = UserCountChart {
groups: GroupDataModel::get_all(&db, &group.name).await?,
};
total_chart
.render(&output, &group.name, false, true, "charts-total")
.await?;
total_chart
.render(
&output,
&group.name,
false,
false,
"charts-total-untruncated",
)
.await?;
}
GroupTemplate::new(group.description.clone(), &group.name) GroupTemplate::new(group.description.clone(), &group.name)
.await .await
@ -136,16 +158,12 @@ pub async fn run() -> Result<()> {
write_assets(&output).await?; write_assets(&output).await?;
if let Some(group) = user_count_group { if let Some(group) = user_count_group {
let path = for dir in ["charts", "charts-untruncated"] {
output.join(&format!("charts/user-count/{}.svg", &group.name)); let from_path =
copy(path, output.join("charts/main-user-count.svg")).await?; output.join(&format!("{}/user-count/{}.svg", dir, &group.name));
let to_path = output.join(format!("{}/main-user-count.svg", dir));
let path = output.join(&format!( copy(from_path, to_path).await?;
"charts-untruncated/user-count/{}.svg", }
&group.name
));
copy(path, output.join("charts-untruncated/main-user-count.svg"))
.await?;
} }
} }
}, },

View File

@ -42,6 +42,20 @@ impl GroupDataModel {
Ok(group) Ok(group)
} }
/// Get all the saved group datas from a given group name.
pub async fn get_all(
db: &DatabaseConnection,
name: &str,
) -> Result<Vec<Self>> {
Ok(
GroupDataEntity::find()
.order_by_asc(GroupDataColumn::SnapshotId)
.filter(GroupDataColumn::Name.eq(name))
.all(db)
.await?,
)
}
/// Get the N most recently saved group datas from a given group name. /// Get the N most recently saved group datas from a given group name.
pub async fn get_n_most_recent( pub async fn get_n_most_recent(
db: &DatabaseConnection, db: &DatabaseConnection,

View File

@ -65,3 +65,7 @@ details {
.underline { .underline {
text-decoration: underline; text-decoration: underline;
} }
.small {
font-size: 1rem;
}

View File

@ -44,7 +44,11 @@
<td> <td>
<a href="/{{ group.name }}">{{ group.name }}</a> <a href="/{{ group.name }}">{{ group.name }}</a>
</td> </td>
<td>{{ group.subscribers }}</td> <td>
{{ group.subscribers }}&nbsp;<span class="small"
title="Percentage of subscribers compared to the highest-subscribed group."
>({{ group.subscribers|percentage(user_count) }})</span>
</td>
<td> <td>
{% if let Some(description) = group.description %} {% if let Some(description) = group.description %}
{{ description }} {{ description }}

View File

@ -40,7 +40,7 @@ pub struct HomeTemplate {
pub today: NaiveDate, pub today: NaiveDate,
/// The user count from the group with the most subscribers. /// The user count from the group with the most subscribers.
pub user_count: String, pub user_count: i64,
} }
impl HomeTemplate { impl HomeTemplate {
@ -59,9 +59,7 @@ impl HomeTemplate {
groups, groups,
page_title: "Tildes Statistics".to_string(), page_title: "Tildes Statistics".to_string(),
today: today(), today: today(),
user_count: user_count user_count: user_count.unwrap_or(1),
.map(|n| n.to_string())
.unwrap_or_else(|| "unknown".to_string()),
} }
} }
@ -128,3 +126,10 @@ impl GroupTemplate {
Ok(()) Ok(())
} }
} }
mod filters {
pub fn percentage(a: &i64, b: &i64) -> askama::Result<String> {
let percentage = (*a as f64 / *b as f64) * 100_f64;
Ok(format!("{:.2}%", percentage))
}
}

View File

@ -9,9 +9,9 @@ use {
eyre::{eyre, WrapErr}, eyre::{eyre, WrapErr},
Result, Result,
}, },
scraper::Html,
sea_orm::{ConnectOptions, Database, DatabaseConnection}, sea_orm::{ConnectOptions, Database, DatabaseConnection},
surf::{Client, Config}, surf::{Client, Config},
tildes_parser::Html,
}; };
/// Creates the SeaQL [`DatabaseConnection`]. /// Creates the SeaQL [`DatabaseConnection`].