diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/atom.rs | 61 | ||||
-rw-r--r-- | src/query/issues.rs | 8 |
2 files changed, 57 insertions, 12 deletions
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?; |