Skip to main content

max / makenotwork

3.6 KB · 145 lines History Blame Raw
1 //! The row writers every content module goes through: one function per table,
2 //! each returning the id it wrote so the caller can hang children off it.
3
4 use mt_core::types::CommunityRole;
5 use sqlx::PgPool;
6 use uuid::Uuid;
7
8 pub(super) async fn seed_community(
9 pool: &PgPool,
10 name: &str,
11 slug: &str,
12 description: Option<&str>,
13 ) -> Uuid {
14 sqlx::query_scalar(
15 "INSERT INTO communities (name, slug, description)
16 VALUES ($1, $2, $3)
17 ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name
18 RETURNING id",
19 )
20 .bind(name)
21 .bind(slug)
22 .bind(description)
23 .fetch_one(pool)
24 .await
25 .expect("failed to seed community")
26 }
27
28 pub(super) async fn seed_category(
29 pool: &PgPool,
30 community_id: Uuid,
31 name: &str,
32 slug: &str,
33 sort_order: i32,
34 description: Option<&str>,
35 ) -> Uuid {
36 sqlx::query_scalar(
37 "INSERT INTO categories (community_id, name, slug, description, sort_order)
38 VALUES ($1, $2, $3, $4, $5)
39 ON CONFLICT (community_id, slug) DO UPDATE SET name = EXCLUDED.name
40 RETURNING id",
41 )
42 .bind(community_id)
43 .bind(name)
44 .bind(slug)
45 .bind(description)
46 .bind(sort_order)
47 .fetch_one(pool)
48 .await
49 .expect("failed to seed category")
50 }
51
52 pub(super) async fn seed_membership(
53 pool: &PgPool,
54 user_id: Uuid,
55 community_id: Uuid,
56 role: CommunityRole,
57 ) {
58 sqlx::query(
59 "INSERT INTO memberships (user_id, community_id, role)
60 VALUES ($1, $2, $3)
61 ON CONFLICT (user_id, community_id) DO NOTHING",
62 )
63 .bind(user_id)
64 .bind(community_id)
65 .bind(role.as_str())
66 .execute(pool)
67 .await
68 .expect("failed to seed membership");
69 }
70
71 pub(super) async fn seed_membership_upsert(
72 pool: &PgPool,
73 user_id: Uuid,
74 community_id: Uuid,
75 role: CommunityRole,
76 ) {
77 sqlx::query(
78 "INSERT INTO memberships (user_id, community_id, role)
79 VALUES ($1, $2, $3)
80 ON CONFLICT (user_id, community_id) DO UPDATE SET role = EXCLUDED.role",
81 )
82 .bind(user_id)
83 .bind(community_id)
84 .bind(role.as_str())
85 .execute(pool)
86 .await
87 .expect("failed to seed membership");
88 }
89
90 pub(super) async fn seed_thread(
91 pool: &PgPool,
92 category_id: Uuid,
93 author_id: Uuid,
94 title: &str,
95 pinned: bool,
96 locked: bool,
97 ) -> Uuid {
98 sqlx::query_scalar(
99 "INSERT INTO threads (category_id, author_id, title, pinned, locked)
100 VALUES ($1, $2, $3, $4, $5)
101 RETURNING id",
102 )
103 .bind(category_id)
104 .bind(author_id)
105 .bind(title)
106 .bind(pinned)
107 .bind(locked)
108 .fetch_one(pool)
109 .await
110 .expect("failed to seed thread")
111 }
112
113 pub(super) async fn seed_post(
114 pool: &PgPool,
115 thread_id: Uuid,
116 author_id: Uuid,
117 body_markdown: &str,
118 ) -> Uuid {
119 // Render through the same strict markdown path production uses so seeded
120 // posts render identically to real ones (previously a hand-rolled escape
121 // diverged from docengine output).
122 let body_html = crate::routes::helpers::render_markdown(body_markdown);
123
124 let post_id: Uuid = sqlx::query_scalar(
125 "INSERT INTO posts (thread_id, author_id, body_markdown, body_html)
126 VALUES ($1, $2, $3, $4)
127 RETURNING id",
128 )
129 .bind(thread_id)
130 .bind(author_id)
131 .bind(body_markdown)
132 .bind(&body_html)
133 .fetch_one(pool)
134 .await
135 .expect("failed to seed post");
136
137 sqlx::query("UPDATE threads SET last_activity_at = now() WHERE id = $1")
138 .bind(thread_id)
139 .execute(pool)
140 .await
141 .expect("failed to update thread activity");
142
143 post_id
144 }
145