Skip to main content

max / makenotwork

4.6 KB · 138 lines History Blame Raw
1 //! Thread tracking handlers — track, untrack, tracked threads list.
2
3 use axum::{
4 extract::Path,
5 http::StatusCode,
6 response::{IntoResponse, Redirect, Response},
7 };
8 use tower_sessions::Session;
9
10 use crate::auth::MaybeUser;
11 use crate::csrf;
12 use crate::templates::*;
13 use crate::AppState;
14
15 use super::{parse_uuid, template_user};
16
17 /// POST /p/{slug}/{cat}/{thread_id}/track
18 #[tracing::instrument(skip_all)]
19 pub(super) async fn track_thread_handler(
20 axum::extract::State(state): axum::extract::State<AppState>,
21 Path((slug, category_slug, thread_id_str)): Path<(String, String, String)>,
22 MaybeUser(session_user): MaybeUser,
23 ) -> Result<Redirect, Response> {
24 let user = session_user
25 .ok_or_else(|| Redirect::to("/auth/login").into_response())?;
26
27 let thread_id = parse_uuid(&thread_id_str)?;
28
29 mt_db::mutations::track_thread(&state.db, user.user_id, thread_id)
30 .await
31 .map_err(|e| {
32 tracing::error!(error = ?e, "db error tracking thread");
33 StatusCode::INTERNAL_SERVER_ERROR.into_response()
34 })?;
35
36 Ok(Redirect::to(&format!(
37 "/p/{slug}/{category_slug}/{thread_id_str}?toast=Thread+tracked"
38 )))
39 }
40
41 /// POST /p/{slug}/{cat}/{thread_id}/untrack
42 #[tracing::instrument(skip_all)]
43 pub(super) async fn untrack_thread_handler(
44 axum::extract::State(state): axum::extract::State<AppState>,
45 Path((slug, category_slug, thread_id_str)): Path<(String, String, String)>,
46 MaybeUser(session_user): MaybeUser,
47 ) -> Result<Redirect, Response> {
48 let user = session_user
49 .ok_or_else(|| Redirect::to("/auth/login").into_response())?;
50
51 let thread_id = parse_uuid(&thread_id_str)?;
52
53 mt_db::mutations::untrack_thread(&state.db, user.user_id, thread_id)
54 .await
55 .map_err(|e| {
56 tracing::error!(error = ?e, "db error untracking thread");
57 StatusCode::INTERNAL_SERVER_ERROR.into_response()
58 })?;
59
60 Ok(Redirect::to(&format!(
61 "/p/{slug}/{category_slug}/{thread_id_str}?toast=Thread+untracked"
62 )))
63 }
64
65 /// POST /tracked/stop-all
66 #[tracing::instrument(skip_all)]
67 pub(super) async fn untrack_all_handler(
68 axum::extract::State(state): axum::extract::State<AppState>,
69 MaybeUser(session_user): MaybeUser,
70 ) -> Result<Redirect, Response> {
71 let user = session_user
72 .ok_or_else(|| Redirect::to("/auth/login").into_response())?;
73
74 mt_db::mutations::untrack_all(&state.db, user.user_id)
75 .await
76 .map_err(|e| {
77 tracing::error!(error = ?e, "db error untracking all");
78 StatusCode::INTERNAL_SERVER_ERROR.into_response()
79 })?;
80
81 Ok(Redirect::to("/tracked?toast=Stopped+tracking+all"))
82 }
83
84 /// GET /about/tracking — privacy/tracking info page
85 #[tracing::instrument(skip_all)]
86 pub(super) async fn tracking_info_page(
87 axum::extract::State(state): axum::extract::State<AppState>,
88 session: Session,
89 MaybeUser(session_user): MaybeUser,
90 ) -> impl IntoResponse {
91 let csrf_token = Some(csrf::get_or_create_token(&session).await);
92 let session_user = session_user.as_ref().map(|u| template_user(u, state.config.platform_admin_id));
93 TrackingInfoTemplate {
94 csrf_token,
95 session_user,
96 mnw_base_url: state.config.mnw_base_url.clone(),
97 }
98 }
99
100 /// GET /tracked — tracked threads page
101 #[tracing::instrument(skip_all)]
102 pub(super) async fn tracked_threads_page(
103 axum::extract::State(state): axum::extract::State<AppState>,
104 session: Session,
105 MaybeUser(session_user): MaybeUser,
106 ) -> Result<impl IntoResponse, Response> {
107 let csrf_token = Some(csrf::get_or_create_token(&session).await);
108 let user = session_user
109 .ok_or_else(|| Redirect::to("/auth/login").into_response())?;
110
111 let db_tracked = mt_db::queries::list_tracked_threads(&state.db, user.user_id)
112 .await
113 .map_err(|e| {
114 tracing::error!(error = ?e, "db error listing tracked threads");
115 StatusCode::INTERNAL_SERVER_ERROR.into_response()
116 })?;
117
118 let threads = db_tracked
119 .into_iter()
120 .map(|t| TrackedThreadViewRow {
121 thread_id: t.thread_id.to_string(),
122 thread_title: t.thread_title,
123 community_name: t.community_name,
124 community_slug: t.community_slug,
125 category_slug: t.category_slug,
126 unread_count: t.unread_count.max(0) as u32,
127 has_mention: t.has_mention,
128 })
129 .collect();
130
131 Ok(TrackedThreadsTemplate {
132 csrf_token,
133 session_user: Some(template_user(&user, state.config.platform_admin_id)),
134 mnw_base_url: state.config.mnw_base_url.clone(),
135 threads,
136 })
137 }
138