four entire seconds

This commit is contained in:
lda committed 2025-05-16 02:59:28 +07:00
1 parent 0b44c6afe2
commit c55867a6ee
3 files changed
+234 -23

No files matched your search

+68 -18
View File
@@ -1,27 +1,78 @@
use actix_cors::Cors;
use actix_web::{App, HttpResponse, HttpServer, Responder, get, http::header};
use icalendar::{
Calendar, CalendarComponent, Component,
parser::{read_calendar, read_calendar_simple},
};
use regex::Regex;
use reqwest::Client;
#[get("/fetch-ics")]
async fn fetch_ics() -> impl Responder {
println!("pinged");
let client = Client::new();
let ics_url = "https://calendar.google.com/calendar/ical/i7p4ol56gi8sqe0dq7uc3m0o4c%40group.calendar.google.com/public/basic.ics";
const ICS_URL: &str = "https://calendar.google.com/calendar/ical/i7p4ol56gi8sqe0dq7uc3m0o4c%40group.calendar.google.com/public/basic.ics";
const REGEX_PATTERN: &str = r"(CLASS 1|G1)";
match client.get(ics_url).send().await {
Ok(response) => {
if let Ok(body) = response.text().await {
HttpResponse::Ok()
.insert_header((header::CONTENT_TYPE, "text/calendar"))
.body(body)
} else {
HttpResponse::InternalServerError().body("Failed to read response body")
}
}
Err(_) => HttpResponse::BadGateway().body("Failed to fetch ICS file"),
#[get("/filtered-ics")]
async fn filtered_ics() -> impl Responder {
match fetch_and_filter_calendar(ICS_URL, REGEX_PATTERN).await {
Ok(ics_content) => HttpResponse::Ok()
.content_type("text/calendar")
.body(ics_content),
Err(err_msg) => HttpResponse::InternalServerError().body(err_msg),
}
}
async fn fetch_and_filter_calendar(url: &str, pattern: &str) -> Result<String, String> {
let body = fetch_ics_content(url).await?;
let calendar = parse_calendar(&body)?;
let filtered_calendar = filter_events(calendar, pattern)?;
Ok(serialize_calendar(filtered_calendar))
}
async fn fetch_ics_content(url: &str) -> Result<String, &str> {
let client = Client::new();
let response = client
.get(url)
.send()
.await
.map_err(|_| "Failed to fetch ICS file")?;
response
.text()
.await
.map_err(|_| "Failed to read response body")
}
fn parse_calendar(content: &str) -> Result<Calendar, &str> {
read_calendar(content)
.map(Calendar::from)
.map_err(|_| "Failed to parse ICS file")
}
fn filter_events(calendar: Calendar, pattern: &str) -> Result<Calendar, String> {
let summary_filter = Regex::new(pattern).map_err(|_| "Invalid regex pattern")?;
let filtered_components: Vec<CalendarComponent> = calendar
.components
.into_iter()
.filter_map(|component| match component {
CalendarComponent::Event(event)
if event
.get_summary()
.is_some_and(|s| summary_filter.is_match(s)) =>
{
Some(CalendarComponent::Event(event))
}
_ => None,
})
.collect();
Ok(Calendar {
components: filtered_components,
..Default::default()
})
}
fn serialize_calendar(calendar: Calendar) -> String {
calendar.to_string()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
@@ -30,8 +81,7 @@ async fn main() -> std::io::Result<()> {
.allowed_methods(vec!["GET"])
.allowed_headers(vec![header::CONTENT_TYPE])
.max_age(3600);
App::new().wrap(cors).service(fetch_ics)
App::new().wrap(cors).service(filtered_ics)
})
.bind(("127.0.0.1", 8080))?
.run()