1pub mod account;
7pub mod auth;
8pub mod error;
9pub mod routes;
10pub mod state;
11pub mod ws;
12
13use std::sync::Arc;
14
15use axum::middleware;
16use axum::routing::{delete, get, patch, post};
17use axum::Router;
18use tower_http::cors::CorsLayer;
19use tower_http::trace::TraceLayer;
20
21use crate::state::AppState;
22
23pub fn build_router(state: Arc<AppState>) -> Router {
25 let api = Router::new()
26 .route("/health", get(routes::health::health))
27 .route("/health/detailed", get(routes::health::health_detailed))
28 .route("/analytics/summary", get(routes::analytics::summary))
30 .route("/analytics/followers", get(routes::analytics::followers))
31 .route(
32 "/analytics/performance",
33 get(routes::analytics::performance),
34 )
35 .route("/analytics/topics", get(routes::analytics::topics))
36 .route(
37 "/analytics/recent-performance",
38 get(routes::analytics::recent_performance),
39 )
40 .route("/approval/export", get(routes::approval::export_items))
42 .route("/approval", get(routes::approval::list_items))
43 .route("/approval/stats", get(routes::approval::stats))
44 .route("/approval/approve-all", post(routes::approval::approve_all))
45 .route(
46 "/approval/{id}/history",
47 get(routes::approval::get_edit_history),
48 )
49 .route("/approval/{id}", patch(routes::approval::edit_item))
50 .route(
51 "/approval/{id}/approve",
52 post(routes::approval::approve_item),
53 )
54 .route("/approval/{id}/reject", post(routes::approval::reject_item))
55 .route("/activity/export", get(routes::activity::export_activity))
57 .route("/activity", get(routes::activity::list_activity))
58 .route(
59 "/activity/rate-limits",
60 get(routes::activity::rate_limit_usage),
61 )
62 .route("/replies", get(routes::replies::list_replies))
64 .route(
66 "/content/tweets",
67 get(routes::content::list_tweets).post(routes::content::compose_tweet),
68 )
69 .route(
70 "/content/threads",
71 get(routes::content::list_threads).post(routes::content::compose_thread),
72 )
73 .route("/content/calendar", get(routes::content::calendar))
74 .route("/content/schedule", get(routes::content::schedule))
75 .route("/content/compose", post(routes::content::compose))
76 .route(
77 "/content/scheduled/{id}",
78 patch(routes::content::edit_scheduled).delete(routes::content::cancel_scheduled),
79 )
80 .route(
82 "/content/drafts",
83 get(routes::content::list_drafts).post(routes::content::create_draft),
84 )
85 .route(
86 "/content/drafts/{id}",
87 patch(routes::content::edit_draft).delete(routes::content::delete_draft),
88 )
89 .route(
90 "/content/drafts/{id}/schedule",
91 post(routes::content::schedule_draft),
92 )
93 .route(
94 "/content/drafts/{id}/publish",
95 post(routes::content::publish_draft),
96 )
97 .route(
99 "/targets",
100 get(routes::targets::list_targets).post(routes::targets::add_target),
101 )
102 .route(
103 "/targets/{username}/timeline",
104 get(routes::targets::target_timeline),
105 )
106 .route(
107 "/targets/{username}/stats",
108 get(routes::targets::target_stats),
109 )
110 .route(
111 "/targets/{username}",
112 delete(routes::targets::remove_target),
113 )
114 .route("/strategy/current", get(routes::strategy::current))
116 .route("/strategy/history", get(routes::strategy::history))
117 .route("/strategy/refresh", post(routes::strategy::refresh))
118 .route("/strategy/inputs", get(routes::strategy::inputs))
119 .route("/costs/summary", get(routes::costs::summary))
121 .route("/costs/daily", get(routes::costs::daily))
122 .route("/costs/by-model", get(routes::costs::by_model))
123 .route("/costs/by-type", get(routes::costs::by_type))
124 .route("/costs/x-api/summary", get(routes::costs::x_api_summary))
126 .route("/costs/x-api/daily", get(routes::costs::x_api_daily))
127 .route(
128 "/costs/x-api/by-endpoint",
129 get(routes::costs::x_api_by_endpoint),
130 )
131 .route("/assist/tweet", post(routes::assist::assist_tweet))
133 .route("/assist/reply", post(routes::assist::assist_reply))
134 .route("/assist/thread", post(routes::assist::assist_thread))
135 .route("/assist/improve", post(routes::assist::assist_improve))
136 .route("/assist/topics", get(routes::assist::assist_topics))
137 .route(
138 "/assist/optimal-times",
139 get(routes::assist::assist_optimal_times),
140 )
141 .route("/assist/mode", get(routes::assist::get_mode))
142 .route("/discovery/feed", get(routes::discovery::feed))
144 .route("/discovery/keywords", get(routes::discovery::keywords))
145 .route(
146 "/discovery/{tweet_id}/compose-reply",
147 post(routes::discovery::compose_reply),
148 )
149 .route(
150 "/discovery/{tweet_id}/queue-reply",
151 post(routes::discovery::queue_reply),
152 )
153 .route("/media/upload", post(routes::media::upload))
155 .route("/media/file", get(routes::media::serve_file))
156 .route("/settings/status", get(routes::settings::config_status))
158 .route("/settings/init", post(routes::settings::init_settings))
159 .route(
160 "/settings/validate",
161 post(routes::settings::validate_settings),
162 )
163 .route("/settings/defaults", get(routes::settings::get_defaults))
164 .route("/settings/test-llm", post(routes::settings::test_llm))
165 .route(
166 "/settings",
167 get(routes::settings::get_settings).patch(routes::settings::patch_settings),
168 )
169 .route(
171 "/mcp/policy",
172 get(routes::mcp::get_policy).patch(routes::mcp::patch_policy),
173 )
174 .route("/mcp/policy/templates", get(routes::mcp::list_templates))
175 .route(
176 "/mcp/policy/templates/{name}",
177 post(routes::mcp::apply_template),
178 )
179 .route(
180 "/mcp/telemetry/summary",
181 get(routes::mcp::telemetry_summary),
182 )
183 .route(
184 "/mcp/telemetry/metrics",
185 get(routes::mcp::telemetry_metrics),
186 )
187 .route("/mcp/telemetry/errors", get(routes::mcp::telemetry_errors))
188 .route("/mcp/telemetry/recent", get(routes::mcp::telemetry_recent))
189 .route("/runtime/status", get(routes::runtime::status))
191 .route("/runtime/start", post(routes::runtime::start))
192 .route("/runtime/stop", post(routes::runtime::stop))
193 .route(
195 "/accounts",
196 get(routes::accounts::list_accounts).post(routes::accounts::create_account),
197 )
198 .route(
199 "/accounts/{id}/roles",
200 get(routes::accounts::list_roles)
201 .post(routes::accounts::set_role)
202 .delete(routes::accounts::remove_role),
203 )
204 .route(
205 "/accounts/{id}",
206 get(routes::accounts::get_account)
207 .patch(routes::accounts::update_account)
208 .delete(routes::accounts::delete_account),
209 )
210 .route("/ws", get(ws::ws_handler))
212 .layer(middleware::from_fn_with_state(
214 state.clone(),
215 auth::auth_middleware,
216 ));
217
218 Router::new()
219 .nest("/api", api)
220 .layer(CorsLayer::permissive())
221 .layer(TraceLayer::new_for_http())
222 .with_state(state)
223}