1use super::Post;
2use crate::{
3 W,
4 error::{AppError, Result},
5};
6
7pub enum PostSource {
8 Draft,
9 Post(String),
10}
11
12pub fn all(conn: &W) -> Result<Vec<Post>> {
13 let conn = conn.lock()?;
14
15 let mut stmt = conn.prepare("SELECT title, contents, slug, subtitle, category, bsky_uri, creation_datetime FROM post")
16 .map_err(AppError::from)?;
17
18 let posts_result: rusqlite::Result<Vec<Post>> = stmt
19 .query_map([], |row| {
20 Ok(Post {
21 title: row.get(0)?,
22 contents: row.get(1)?,
23 slug: row.get(2)?,
24 subtitle: row.get(3)?,
25 category: row.get(4)?,
26 bsky_uri: row.get(5)?,
27 creation_datetime: row.get(6)?,
28 })
29 })?
30 .collect();
31
32 let mut posts = posts_result.map_err(AppError::from)?;
33 posts.sort_by(|a, b| {
34 a.creation_datetime
35 .partial_cmp(&b.creation_datetime)
36 .unwrap_or(std::cmp::Ordering::Equal)
37 .reverse()
38 });
39 Ok(posts)
40}
41
42pub fn one(slug: String, conn: &W) -> Result<Post> {
43 fetch_post_inner(&PostSource::Post(slug), conn)
44}
45
46pub fn one_draft(conn: &W) -> Result<Post> {
47 fetch_post_inner(&PostSource::Draft, conn)
48}
49
50fn fetch_post_inner(source: &PostSource, conn: &W) -> Result<Post> {
51 let conn = conn.lock()?;
52
53 let (query, params): (&str, Vec<&dyn rusqlite::ToSql>) = match source {
54 PostSource::Post(slug) => (
55 "SELECT title, contents, slug, subtitle, category, bsky_uri, creation_datetime FROM post WHERE slug = ?1",
56 vec![slug],
57 ),
58 PostSource::Draft => (
59 "SELECT title, contents, slug, subtitle, category, bsky_uri, creation_datetime FROM draft",
60 vec![],
61 ),
62 };
63
64 let mut stmt = conn.prepare(query).map_err(AppError::from)?;
65
66 let post = stmt
67 .query_one(params.as_slice(), |row| {
68 Ok(Post {
69 title: row.get(0)?,
70 contents: row.get(1)?,
71 slug: row.get(2)?,
72 subtitle: row.get(3)?,
73 category: row.get(4)?,
74 bsky_uri: row.get(5)?,
75 creation_datetime: row.get(6)?,
76 })
77 })
78 .map_err(AppError::from)?;
79
80 Ok(post)
81}