diff options
-rw-r--r-- | Cargo.lock | 22 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/atom.rs | 61 | ||||
-rw-r--r-- | src/query/issues.rs | 8 |
4 files changed, 82 insertions, 12 deletions
@@ -521,7 +521,9 @@ dependencies = [ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures-retry 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphql_client 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", "smol 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "sqlx 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,6 +1050,15 @@ dependencies = [ [[package]] name = "quick-xml" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_rs 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-xml" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ @@ -1174,6 +1185,15 @@ dependencies = [ ] [[package]] +name = "rss" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1951,6 +1971,7 @@ dependencies = [ "checksum proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" "checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" "checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" +"checksum quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0" "checksum quick-xml 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc440ee4802a86e357165021e3e255a9143724da31db1e2ea540214c96a0f82" "checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" @@ -1963,6 +1984,7 @@ dependencies = [ "checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2" +"checksum rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99979205510c60f80a119dedbabd0b8426517384edf205322f8bcd51796bcef9" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" "checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" @@ -18,7 +18,10 @@ sqlx = { version = "0.3", default-features = false, features = [ "runtime-tokio" anyhow = "1.0" +# sqlx pretty-prints all queries with sqlformat to log, which is very expensive +log = { version = "0.4", features = [ "max_level_off", "release_max_level_off" ] } tracing = "0.1" tracing-subscriber = "0.2.4" atom_syndication = "0.9" +rss = "1.9" diff --git a/src/atom.rs b/src/atom.rs index f431f42..e87901d 100644 --- a/src/atom.rs +++ b/src/atom.rs @@ -5,12 +5,13 @@ use std::{ use sqlx::prelude::*; use atom_syndication::*; -use anyhow::Result; +use anyhow::{ Result, Context }; use futures::{ Stream, StreamExt }; +use chrono::{ Utc, TimeZone }; use tracing::info; -use crate::{ Conn, query::repo_id }; +use crate::{ Conn, query::{ self, repo_id } }; #[allow(dead_code)] #[derive(sqlx::FromRow)] @@ -34,10 +35,40 @@ async fn query_issues_for_label<'conn>(conn: &'conn mut Conn, repo_id: i64, labe .fetch(conn) } -fn issue_to_entry(issue: Issue) -> Entry { - EntryBuilder::default() +async fn issue_to_entry(conn: &mut Conn, repo_id: i64, issue: Issue) -> Result<Entry> { + let state_label = query::issues::integer_to_state_desc(issue.state); + let labels_of_issue = sqlx::query_as::<_, (String,)>( + "SELECT labels.name FROM is_labeled + JOIN labels ON is_labeled.label=labels.id + JOIN issues ON (is_labeled.issue=issues.number AND is_labeled.repo=issues.repo) + WHERE is_labeled.repo=? AND is_labeled.issue=?" + ).bind(repo_id).bind(issue.number) + .fetch(&mut *conn); + + let all_labels = futures::stream::iter(state_label) + .chain(labels_of_issue + .filter_map(|row| async { row.ok() }) + .map(|(name,)| name)) + .map(|name| Category { + term: name, + scheme: None, + label: None + }) + .collect::<Vec<_>>() + .await; + + Ok(EntryBuilder::default() .title(issue.title) .id(issue.html_url.clone()) + .updated(Utc.timestamp(issue.updated_at, 0)) + .authors(vec![ + Person { + uri: Some(format!("https://github.com/{}", issue.user_login)), + name: issue.user_login, + email: None + } + ]) + .categories(all_labels) .links(vec![LinkBuilder::default() .href(issue.html_url) .build() @@ -48,7 +79,8 @@ fn issue_to_entry(issue: Issue) -> Entry { .build() .expect("Failed to build content")) .build() - .expect("Failed to build entry") + .map_err(|err_str| anyhow::anyhow!(err_str)) + .context("Failed to build atom entry")?) } pub async fn generate(mut conn: &mut Conn, (ref owner, ref name): (String, String), out_path: PathBuf, labels: Vec<String>) -> Result<()> { @@ -73,13 +105,18 @@ pub async fn generate(mut conn: &mut Conn, (ref owner, ref name): (String, Strin let mut feed = FeedBuilder::default(); feed.title(label.clone()); - let issues = query_issues_for_label(&mut conn, repo_id, &label).await; - feed.entries( - issues.filter_map(|issue| async { issue.ok() }) - .map(issue_to_entry) - .collect::<Vec<_>>() - .await - ); + let issues: Vec<Issue> = query_issues_for_label(&mut conn, repo_id, &label).await + .filter_map(|res| async { res.ok() }) + .collect().await; + + let entries: Vec<Entry> = { + let mut acc = Vec::new(); + for issue in issues.into_iter() { + acc.push(issue_to_entry(&mut conn, repo_id, issue).await?); + } + acc + }; + feed.entries(entries); let feed = feed.build().expect("Failed to build feed"); diff --git a/src/query/issues.rs b/src/query/issues.rs index c829a22..b9473d3 100644 --- a/src/query/issues.rs +++ b/src/query/issues.rs @@ -30,6 +30,14 @@ fn state_to_integer(state: issues_query::IssueState) -> i64 { } } +pub fn integer_to_state_desc(state: i64) -> Option<String> { + match state { + 0 => Some("open"), + 1 => Some("closed"), + _ => None + }.map(str::to_owned) +} + pub async fn update(mut conn: &mut Conn, github_api_token: &str, (ref owner, ref name): (String, String)) -> anyhow::Result<()> { let repo = repo_id(conn, owner, name).await?; |