1use worker::*;
25
26mod ai;
27mod crypto;
28mod handlers;
29mod helpers;
30mod instagram;
31mod landing;
32mod scheduled;
33mod storage;
34mod templates;
35mod types;
36mod whatsapp;
37
38pub use types::*;
39
40const LOGO_SVG: &str = include_str!("../assets/logo.svg");
42const WEBMANIFEST: &str = include_str!("../assets/site.webmanifest");
43const BROWSERCONFIG: &str = include_str!("../assets/browserconfig.xml");
44const FAVICON_16: &[u8] = include_bytes!("../assets/favicon-16.png");
45const FAVICON_32: &[u8] = include_bytes!("../assets/favicon-32.png");
46const APPLE_TOUCH_ICON: &[u8] = include_bytes!("../assets/apple-touch-icon.png");
47const LOGO_192: &[u8] = include_bytes!("../assets/logo-192.png");
48const LOGO_512: &[u8] = include_bytes!("../assets/logo-512.png");
49const MSTILE_150: &[u8] = include_bytes!("../assets/mstile-150x150.png");
50
51fn serve_text(body: &str, content_type: &str) -> Result<Response> {
52 let headers = Headers::new();
53 headers.set("Content-Type", content_type)?;
54 headers.set("Cache-Control", "public, max-age=31536000")?;
55 Ok(Response::ok(body)?.with_headers(headers))
56}
57
58fn serve_png(body: &[u8]) -> Result<Response> {
59 let headers = Headers::new();
60 headers.set("Content-Type", "image/png")?;
61 headers.set("Cache-Control", "public, max-age=31536000")?;
62 Ok(Response::from_bytes(body.to_vec())?.with_headers(headers))
63}
64
65#[event(fetch)]
66async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
67 console_error_panic_hook::set_once();
68
69 let url = req.url()?;
70 let path = url.path();
71 let method = req.method();
72
73 match path {
75 "/logo.svg" => return serve_text(LOGO_SVG, "image/svg+xml"),
76 "/site.webmanifest" => return serve_text(WEBMANIFEST, "application/manifest+json"),
77 "/browserconfig.xml" => return serve_text(BROWSERCONFIG, "application/xml"),
78 "/favicon-16.png" => return serve_png(FAVICON_16),
79 "/favicon-32.png" => return serve_png(FAVICON_32),
80 "/apple-touch-icon.png" => return serve_png(APPLE_TOUCH_ICON),
81 "/logo-192.png" => return serve_png(LOGO_192),
82 "/logo-512.png" => return serve_png(LOGO_512),
83 "/mstile-150x150.png" => return serve_png(MSTILE_150),
84 "/health" => return Response::ok("OK"),
85 _ => {}
86 }
87
88 if path == "/terms" {
90 let headers = Headers::new();
91 headers.set("Content-Type", "text/html; charset=utf-8")?;
92 headers.set("Cache-Control", "public, max-age=3600")?;
93 return Ok(Response::ok(landing::terms_of_service_html())?.with_headers(headers));
94 }
95
96 if path == "/privacy" {
98 let headers = Headers::new();
99 headers.set("Content-Type", "text/html; charset=utf-8")?;
100 headers.set("Cache-Control", "public, max-age=3600")?;
101 return Ok(Response::ok(landing::privacy_policy_html())?.with_headers(headers));
102 }
103
104 if path == "/data-deletion" {
106 return handlers::handle_data_deletion(req, env, method).await;
107 }
108
109 if path.starts_with("/auth/") {
111 return handlers::handle_auth(req, env, path, method).await;
112 }
113
114 if path.starts_with("/whatsapp/signup/") {
116 return handlers::handle_whatsapp_signup(req, env, path, method).await;
117 }
118
119 if path.starts_with("/admin") {
121 return handlers::handle_admin(req, env, path, method).await;
122 }
123
124 if path.starts_with("/lead/") {
126 return handlers::handle_lead_form(req, env, path, method).await;
127 }
128
129 if path.starts_with("/instagram/") {
131 return handlers::handle_instagram(req, env, path, method).await;
132 }
133
134 if path.starts_with("/webhook/") {
136 return handlers::handle_webhook(req, env, path, method).await;
137 }
138
139 if path == "/" || path == "/index.html" {
141 let headers = Headers::new();
142 headers.set("Content-Type", "text/html; charset=utf-8")?;
143 headers.set("Cache-Control", "public, max-age=3600")?;
144 return Ok(Response::ok(landing::landing_page_html())?.with_headers(headers));
145 }
146
147 Response::error("Not Found", 404)
148}
149
150#[event(scheduled)]
151async fn scheduled_handler(event: ScheduledEvent, env: Env, ctx: ScheduleContext) {
152 scheduled::handle_scheduled(event, env, ctx).await;
153}