use of ws.nmathe.saber.core.schedule.EventRecurrence in project Saber-Bot by notem.
the class CalendarConverter method importCalendar.
/**
* Purges a schedule from entries and adds events (after conversion)
* from the next 7 day span of a Google Calendar
* @param address (String) valid address of calendar
* @param channel (MessageChannel) channel to sync with
* @param service connected calendar service with user credentials
*/
public void importCalendar(String address, TextChannel channel, Calendar service) {
// sanity checks
if (channel == null || address == null)
return;
if (!Main.getScheduleManager().isASchedule(channel.getId()))
return;
// query the google calendar address for the list of events
Events events;
try {
ZonedDateTime min = ZonedDateTime.now();
ZonedDateTime max = min.plusDays(Main.getScheduleManager().getSyncLength(channel.getId()));
events = service.events().list(address).setTimeMin(new DateTime(min.format(EventRecurrence.RFC3339_FORMATTER))).setTimeMax(new DateTime(max.format(EventRecurrence.RFC3339_FORMATTER))).setOrderBy("startTime").setSingleEvents(true).setMaxResults(Main.getBotSettingsManager().getMaxEntries()).execute();
} catch (Exception e) {
Logging.exception(this.getClass(), e);
return;
}
try // convert the list of Google Events into discord event entries
{
// send 'is typing' while the sync is in progress
channel.sendTyping().queue();
/* lock the schedule for syncing; schedule is unlocked in finally block */
Main.getScheduleManager().lock(channel.getId());
// change the zone to match the calendar
// only if the zone has not been manually set for that schedule
ZoneId zone = ZoneId.of(events.getTimeZone());
Boolean syncZone = Main.getDBDriver().getScheduleCollection().find(eq("_id", channel.getId())).first().getBoolean("timezone_sync", false);
if (syncZone) {
Main.getScheduleManager().setTimeZone(channel.getId(), zone);
}
// a set of all unique (not child of a recurring event) events
HashSet<String> uniqueEvents = new HashSet<>();
// process events
for (Event event : events.getItems()) {
// continue to send 'is typing'
channel.sendTyping().queue();
// if the unique google event ID does not appear in the already processed events
// convert the event and add it to the schedule
String recurrenceId = event.getRecurringEventId();
String googleId = recurrenceId == null ? event.getId() : recurrenceId;
if (!uniqueEvents.contains(googleId)) {
// declare and initialize event parameters
ZonedDateTime start, end;
String title;
ArrayList<String> comments = new ArrayList<>();
int repeat = 0;
ZonedDateTime expire = null;
String imageUrl = null;
String thumbnailUrl = null;
ZonedDateTime rsvpDeadline = null;
String titleUrl = null;
Map<String, Integer> rsvpLimits = new HashMap<>();
if (event.getStart().getDateTime() == null) {
/* parse start and end dates for all day events */
start = ZonedDateTime.of(LocalDate.parse(event.getStart().getDate().toStringRfc3339()), LocalTime.MIN, zone);
end = ZonedDateTime.of(LocalDate.parse(event.getEnd().getDate().toStringRfc3339()), LocalTime.MIN, zone);
} else {
/* parse start and end times for normal events */
start = ZonedDateTime.parse(event.getStart().getDateTime().toStringRfc3339(), EventRecurrence.RFC3339_FORMATTER).withZoneSameInstant(zone);
end = ZonedDateTime.parse(event.getEnd().getDateTime().toStringRfc3339(), EventRecurrence.RFC3339_FORMATTER).withZoneSameInstant(zone);
}
// get event title
if (event.getSummary() == null)
title = "(No title)";
else
title = event.getSummary();
// process event description into event comments or other settings
if (event.getDescription() != null) {
// process the description line by line
String description = HTMLStripper.cleanDescription(event.getDescription().replace("\n", "<br>"));
for (String comment : description.split("\n")) {
comment = comment.trim();
String lowerCase = comment.toLowerCase();
// image
if (lowerCase.startsWith("image:")) {
// split to limit:
String[] tmp = comment.split(":", 2);
if (tmp.length > 1) {
imageUrl = tmp[1].trim().replaceAll(" ", "");
if (!VerifyUtilities.verifyUrl(imageUrl))
imageUrl = null;
}
} else // thumbnail
if (lowerCase.startsWith("thumbnail:")) {
String[] tmp = comment.split(":", 2);
if (tmp.length > 1) {
thumbnailUrl = tmp[1].trim().trim().replaceAll(" ", "");
if (!VerifyUtilities.verifyUrl(thumbnailUrl))
thumbnailUrl = null;
}
} else // limit
if (lowerCase.startsWith("limit:")) {
// split to limit:
String[] tmp = comment.split(":", 2);
if (tmp.length > 1) {
// split into white space separated segments
String[] str = tmp[1].trim().split("[^\\S\n\r]+");
if (str.length >= 2) {
// rebuild the rsvp group name
StringBuilder name = new StringBuilder();
for (int i = 0; i < str.length - 1; i++) {
name.append(str[i]);
if (i != str.length - 2)
name.append(" ");
}
// parse the limit
Integer limit = -1;
if (VerifyUtilities.verifyInteger(str[str.length - 1]))
limit = Integer.parseInt(str[str.length - 1]);
rsvpLimits.put(name.toString(), limit);
}
}
} else // title url
if (lowerCase.startsWith("url:")) {
String[] tmp = comment.split(":", 2);
if (tmp.length > 1 && VerifyUtilities.verifyUrl(tmp[1].trim().replaceAll(" ", "")))
titleUrl = tmp[1].trim().replaceAll(" ", "");
} else // deadline
if (lowerCase.startsWith("deadline:")) {
String tmp = lowerCase.replace("deadline:", "").trim().replaceAll(" ", "");
if (VerifyUtilities.verifyDate(tmp))
rsvpDeadline = ParsingUtilities.parseDate(tmp, zone);
} else // plaintext comment
if (!comment.trim().isEmpty()) {
comments.add(comment);
}
}
}
// get the event recurrence information
List<String> recurrence = event.getRecurrence();
if (recurrenceId != null)
recurrence = service.events().get(address, recurrenceId).execute().getRecurrence();
// parse the event recurrence information
if (recurrence != null) {
// determine the start date
ZonedDateTime dtStart = // if orig is null, use start
event.getOriginalStartTime() == null ? // if orig is null, use start
start : (event.getOriginalStartTime().getDateTime() == null ? start : ZonedDateTime.parse(event.getOriginalStartTime().getDateTime().toStringRfc3339(), EventRecurrence.RFC3339_FORMATTER).withZoneSameInstant(zone));
EventRecurrence eventRecurrence = new EventRecurrence(recurrence, dtStart);
expire = eventRecurrence.getExpire();
repeat = eventRecurrence.getRepeat();
}
// if the google event already exists as a saber event on the schedule, update it
// otherwise add as a new saber event
Document doc = Main.getDBDriver().getEventCollection().find(and(eq("channelId", channel.getId()), eq("googleId", googleId))).first();
// should the event be flagged as already started?
boolean hasStarted = start.isBefore(ZonedDateTime.now());
if (doc != null && (new ScheduleEntry(doc)).getMessageObject() != null) {
/* update an existing event */
ScheduleEntry se = (new ScheduleEntry(doc)).setTitle(title).setStart(start).setEnd(end).setRepeat(repeat).setGoogleId(googleId).setExpire(expire).setStarted(hasStarted).setComments(comments).setLocation(event.getLocation());
// set special attributes if not null
if (titleUrl != null)
se.setTitleUrl(titleUrl);
if (imageUrl != null)
se.setImageUrl(imageUrl);
if (thumbnailUrl != null)
se.setThumbnailUrl(thumbnailUrl);
if (rsvpDeadline != null)
se.setRsvpDeadline(rsvpDeadline);
if (rsvpLimits.keySet().size() > 0)
se.setRsvpLimits(rsvpLimits);
// update event reminders using schedule default settings
se.reloadReminders(Main.getScheduleManager().getReminders(se.getChannelId())).reloadEndReminders(Main.getScheduleManager().getEndReminders(se.getChannelId())).regenerateAnnouncementOverrides();
Main.getEntryManager().updateEntry(se, false);
} else {
/* create a new event */
ScheduleEntry se = (new ScheduleEntry(channel, title, start, end)).setTitleUrl(titleUrl != null ? titleUrl : event.getHtmlLink()).setRepeat(repeat).setGoogleId(googleId).setExpire(expire).setStarted(hasStarted).setComments(comments).setLocation(event.getLocation());
// set special attributes if not null
if (imageUrl != null)
se.setImageUrl(imageUrl);
if (thumbnailUrl != null)
se.setThumbnailUrl(thumbnailUrl);
if (rsvpDeadline != null)
se.setRsvpDeadline(rsvpDeadline);
if (rsvpLimits.keySet().size() > 0)
se.setRsvpLimits(rsvpLimits);
Main.getEntryManager().newEntry(se, false);
}
// add to google ID to unique event mapping
uniqueEvents.add(recurrenceId == null ? event.getId() : recurrenceId);
}
}
// purge channel of all entries on schedule that aren't in uniqueEvents
Bson query = and(eq("channelId", channel.getId()), nin("googleId", uniqueEvents));
Main.getDBDriver().getEventCollection().find(query).forEach((Consumer<? super Document>) document -> {
ScheduleEntry entry = Main.getEntryManager().getEntry((Integer) document.get("_id"));
Message msg = entry.getMessageObject();
if (msg == null)
return;
Main.getEntryManager().removeEntry((Integer) document.get("_id"));
MessageUtilities.deleteMsg(msg, null);
});
// set channel topic
JDA jda = Main.getShardManager().getJDA(channel.getGuild().getId());
String calLink = "https://calendar.google.com/calendar/embed?src=" + address;
boolean hasPerms = channel.getGuild().getMember(jda.getSelfUser()).hasPermission(channel, Permission.MANAGE_CHANNEL);
if (hasPerms)
channel.getManagerUpdatable().getTopicField().setValue(calLink).update().queue();
} catch (Exception e) {
Logging.exception(this.getClass(), e);
} finally {
// syncing done, unlock the channel
Main.getScheduleManager().unlock(channel.getId());
}
// auto-sort
EntryManager.autoSort(true, channel.getId());
}
Aggregations