Files
SDKmuta/lib/services/google_calendar_service.dart
T

174 lines
4.7 KiB
Dart

import 'package:http/http.dart' as http;
class CalendarEvent {
final String? summary;
final String? description;
final String? location;
final DateTime? startTime;
final DateTime? endTime;
final bool isAllDay;
CalendarEvent({
this.summary,
this.description,
this.location,
this.startTime,
this.endTime,
this.isAllDay = false,
});
}
class GoogleCalendarService {
static const String calendarId =
'b9c267252d5be63d5cdc880be499885a88421eefd0e34e1392890daba0d8471e@group.calendar.google.com';
final http.Client _httpClient = http.Client();
Future<List<CalendarEvent>> getEvents({
DateTime? startDate,
DateTime? endDate,
}) async {
try {
// Use the public iCal feed URL
final url = Uri.parse(
'https://calendar.google.com/calendar/ical/$calendarId/public/basic.ics');
final response = await _httpClient.get(url);
if (response.statusCode == 200) {
final allEvents = _parseICalendar(response.body);
// Filter events by date range if provided
if (startDate != null || endDate != null) {
return allEvents.where((event) {
if (event.startTime == null) return false;
if (startDate != null && event.startTime!.isBefore(startDate)) {
return false;
}
if (endDate != null && event.startTime!.isAfter(endDate)) {
return false;
}
return true;
}).toList();
}
return allEvents;
} else {
throw Exception('Failed to load calendar: ${response.statusCode}');
}
} catch (e) {
throw Exception('Error fetching events: $e');
}
}
List<CalendarEvent> _parseICalendar(String icalData) {
final events = <CalendarEvent>[];
final lines = icalData.split('\n');
String? summary;
String? description;
String? location;
DateTime? startTime;
DateTime? endTime;
bool isAllDay = false;
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
// Handle line continuations
while (i + 1 < lines.length && lines[i + 1].startsWith(' ')) {
i++;
line += lines[i].trim();
}
if (line.startsWith('BEGIN:VEVENT')) {
summary = null;
description = null;
location = null;
startTime = null;
endTime = null;
isAllDay = false;
} else if (line.startsWith('SUMMARY:')) {
summary = _unescapeText(line.substring(8));
} else if (line.startsWith('DESCRIPTION:')) {
description = _unescapeText(line.substring(12));
} else if (line.startsWith('LOCATION:')) {
location = _unescapeText(line.substring(9));
} else if (line.startsWith('DTSTART')) {
final dateStr = line.split(':')[1];
if (line.contains('VALUE=DATE')) {
isAllDay = true;
startTime = _parseDate(dateStr);
} else {
startTime = _parseDateTime(dateStr);
}
} else if (line.startsWith('DTEND')) {
final dateStr = line.split(':')[1];
if (line.contains('VALUE=DATE')) {
endTime = _parseDate(dateStr);
} else {
endTime = _parseDateTime(dateStr);
}
} else if (line.startsWith('END:VEVENT')) {
events.add(CalendarEvent(
summary: summary,
description: description,
location: location,
startTime: startTime,
endTime: endTime,
isAllDay: isAllDay,
));
}
}
return events;
}
String _unescapeText(String text) {
return text
.replaceAll('\\n', '\n')
.replaceAll('\\,', ',')
.replaceAll('\\;', ';')
.replaceAll('\\\\', '\\');
}
DateTime? _parseDate(String dateStr) {
try {
// Format: YYYYMMDD
final year = int.parse(dateStr.substring(0, 4));
final month = int.parse(dateStr.substring(4, 6));
final day = int.parse(dateStr.substring(6, 8));
return DateTime(year, month, day);
} catch (e) {
return null;
}
}
DateTime? _parseDateTime(String dateStr) {
try {
// Format: YYYYMMDDTHHMMSSZ or YYYYMMDDTHHMMSS
final year = int.parse(dateStr.substring(0, 4));
final month = int.parse(dateStr.substring(4, 6));
final day = int.parse(dateStr.substring(6, 8));
final hour = int.parse(dateStr.substring(9, 11));
final minute = int.parse(dateStr.substring(11, 13));
final second = int.parse(dateStr.substring(13, 15));
if (dateStr.endsWith('Z')) {
return DateTime.utc(year, month, day, hour, minute, second);
} else {
return DateTime(year, month, day, hour, minute, second);
}
} catch (e) {
return null;
}
}
void dispose() {
_httpClient.close();
}
}