import 'dart:convert'; import 'package:icalserver/icalendar.dart'; import 'package:jiffy/jiffy.dart'; import 'package:supabase/supabase.dart'; import 'package:shelf/shelf.dart'; class CalendarHandler { SupabaseClient getSupabaseClient(Request request) { // final supabaseUrl = request.headers['supabase-url']; // final authHeader = request.headers['authorization']; // final token = authHeader!.substring(7); // Remove 'Bearer ' prefix final supabaseUrl = 'http://baas.fares.cyou:8000'; final token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"; return SupabaseClient( supabaseUrl, token, ); } // Handler for the /link route Future getCalendar(Request request) async { final credentials = _getBasicAuthCredentials(request); if (credentials == null) { return Response.unauthorized('Invalid credentials'); } final (username, password) = credentials; if (username != password) { return Response.unauthorized('Invalid credentials'); } final supabase = getSupabaseClient(request); //print(licencesCsv); // Execute the query final rosterlist = await supabase.rpc('get_roster_ical', params: {'__tlc': username}); // Handle the response final requester = (await supabase.from('licences').select().eq('tlc', username)); print( 'TLC: $username ... EVENTS: ${rosterlist.length} ... Name: ${requester[0]['lname']}, ${requester[0]['fname']}'); // Create an iCalendar object final ical = ICalendar(); if (rosterlist is List) { for (var i = 0; i < rosterlist.length; i++) { final event = rosterlist[i]; switch (event["_dutytype"]) { case "flight": ical.addEvent( summary: "${event["dep"]}-${event["des"]}", description: """ Flight ${event["al"]}${event["fnum"]} from ${event["dep"]} to ${event["des"]} A/C: ${event["_reg"] ?? "---"}/${event["actype"]} ${event["_version"] != null ? "Ver: ${event["_version"]}" : ""} ${(event["_paxy"] != null || event["_paxc"] != null) ? "/ PAX: ${event["_paxc"] != null ? "C${event["_paxc"]}" : ""} Y${event["_paxy"] ?? "0"}" : ""} Dep/Arr time: ${Jiffy.parse(event["_hdep"], isUtc: true).Hm} - ${Jiffy.parse(event["_hdes"], isUtc: true).Hm} ${event["_hdep_sched"] != null ? "Sched Dep time: ${Jiffy.parse(event["_hdep_sched"], isUtc: true).format(pattern: "dd MMM yyyy HH:mm")}" : ""} ${event["_delay"] != null ? "Delay codes: ${(event["_delay"] as List).map((e) { final f = (e ?? "") .split('|') .map((j) => j == "" ? null : j) .toList(); return "${(f[1]) ?? (f[0]) ?? '--'}:${((f[2]) ?? '0000').padLeft(4, '0')}"; })}" : ""} Crew: ${(event["crew"] as List).map((e) { final f = (e ?? "").split('|').toList(); return " ${f[0]}: ${f[2]}, ${f[3]} (${f[1]})"; }).join("\n")} """ .replaceAll("\n", "\\n"), startTime: Jiffy.parse(event["_hdep"], isUtc: true).dateTime, endTime: Jiffy.parse(event["_hdes"]).dateTime, attendees: [], ); break; case "dhflight" || "dhlimo": ical.addEvent( summary: "DH ${event["dep"]}-${event["des"]}", description: """ DH ${event["_dutytype"] == "dhflight" ? "Flight" : "Limo"} ${event["al"]}${event["fnum"]} from ${event["dep"]} to ${event["des"]} ${event["_dutytype"] == "dhflight" ? "A/C: ${event["_reg"] ?? "---"}/${event["actype"]}" : ""} ${event["_version"] != null ? "Ver: ${event["_version"]}" : ""} ${(event["_paxy"] != null || event["_paxc"] != null) ? "/ PAX: ${event["_paxc"] != null ? "C${event["_paxc"]}" : ""} Y${event["_paxy"] ?? "0"}" : ""} Dep/Arr time: ${Jiffy.parse(event["_hdep"], isUtc: true).Hm} - ${Jiffy.parse(event["_hdes"], isUtc: true).Hm} ${event["_hdep_sched"] != null ? "Sched Dep time: ${Jiffy.parse(event["_hdep_sched"], isUtc: true).format(pattern: "dd MMM yyyy HH:mm")}" : ""} ${event["_delay"] != null ? "Delay codes: ${(event["_delay"] as List).map((e) { final f = (e ?? "") .split('|') .map((j) => j == "" ? null : j) .toList(); return "${(f[1]) ?? (f[0]) ?? '--'}:${((f[2]) ?? '0000').padLeft(4, '0')}"; })}" : ""} Crew: ${(event["crew"] as List).map((e) { final f = (e ?? "").split('|').toList(); return " ${f[0]}: ${f[2]}, ${f[3]} (${f[1]})"; }).join("\n")} """ .replaceAll("\n", "\\n"), startTime: Jiffy.parse(event["_hdep"], isUtc: true).dateTime, endTime: Jiffy.parse(event["_hdes"]).dateTime, attendees: [], ); break; case "standby" || "ground": ical.addEvent( summary: "${event["_dutytype"] == "standby" ? "STDBY" : ""} ${event["label"]}", description: """ ${event["_dutytype"] == "standby" ? "STDBY" : ""} ${event["label"]} @ ${event["dep"]} Start/End time: ${Jiffy.parse(event["_hdep"], isUtc: true).Hm} - ${Jiffy.parse(event["_hdes"], isUtc: true).Hm} Attendee: ${(event["crew"] as List).map((e) { final f = (e ?? "").split('|').toList(); return " ${f[0]}: ${f[2]}, ${f[3]} (${f[1]})"; }).join("\n")} """ .replaceAll("\n", "\\n"), startTime: Jiffy.parse(event["_hdep"], isUtc: true).dateTime, endTime: Jiffy.parse(event["_hdes"]).dateTime, attendees: [], ); break; case "day": ical.addEvent( summary: "${event["label"]}", description: """ ${event["label"]} @ ${event["dep"] ?? ""} """ .replaceAll("\n", "\\n"), startTime: Jiffy.parse(event["_hdep"]).dateTime, endTime: Jiffy.parse(event["_hdep"]).dateTime, attendees: [], allday: true, ); break; default: } } } // Return the response with the iCalendar content await supabase.dispose(); return Response.ok( ical.serialize(), headers: {'Content-Type': 'text/calendar; charset=utf-8'}, ); } (String, String)? _getBasicAuthCredentials(Request request) { // Get Authorization header if (!request.headers.containsKey('authorization')) { return null; } String authHeader = request.headers['authorization'] ?? ""; if (!authHeader.startsWith('Basic ')) { return null; } // Extract and decode credentials try { String base64Credentials = authHeader.substring('Basic '.length); String credentials = utf8.decode(base64.decode(base64Credentials)); List userPass = credentials.split(':'); if (userPass.length != 2) return null; return (userPass[0], userPass[1]); } catch (e) { return null; } } }