Search in sources :

Example 1 with EventRecurrence

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());
}
Also used : Document(org.bson.Document) java.util(java.util) TextChannel(net.dv8tion.jda.core.entities.TextChannel) EventRecurrence(ws.nmathe.saber.core.schedule.EventRecurrence) Message(net.dv8tion.jda.core.entities.Message) Bson(org.bson.conversions.Bson) Filters(com.mongodb.client.model.Filters) DateTime(com.google.api.client.util.DateTime) java.time(java.time) Matcher(java.util.regex.Matcher) Permission(net.dv8tion.jda.core.Permission) JDA(net.dv8tion.jda.core.JDA) Calendar(com.google.api.services.calendar.Calendar) VerifyUtilities(ws.nmathe.saber.utils.VerifyUtilities) Logging(ws.nmathe.saber.utils.Logging) IOException(java.io.IOException) ScheduleEntry(ws.nmathe.saber.core.schedule.ScheduleEntry) Consumer(java.util.function.Consumer) com.google.api.services.calendar.model(com.google.api.services.calendar.model) DateTimeFormatter(java.time.format.DateTimeFormatter) EntryManager(ws.nmathe.saber.core.schedule.EntryManager) MessageUtilities(ws.nmathe.saber.utils.MessageUtilities) Main(ws.nmathe.saber.Main) Pattern(java.util.regex.Pattern) ParsingUtilities(ws.nmathe.saber.utils.ParsingUtilities) Message(net.dv8tion.jda.core.entities.Message) JDA(net.dv8tion.jda.core.JDA) Document(org.bson.Document) DateTime(com.google.api.client.util.DateTime) Bson(org.bson.conversions.Bson) EventRecurrence(ws.nmathe.saber.core.schedule.EventRecurrence) ScheduleEntry(ws.nmathe.saber.core.schedule.ScheduleEntry) IOException(java.io.IOException)

Aggregations

DateTime (com.google.api.client.util.DateTime)1 Calendar (com.google.api.services.calendar.Calendar)1 com.google.api.services.calendar.model (com.google.api.services.calendar.model)1 Filters (com.mongodb.client.model.Filters)1 IOException (java.io.IOException)1 java.time (java.time)1 DateTimeFormatter (java.time.format.DateTimeFormatter)1 java.util (java.util)1 Consumer (java.util.function.Consumer)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 JDA (net.dv8tion.jda.core.JDA)1 Permission (net.dv8tion.jda.core.Permission)1 Message (net.dv8tion.jda.core.entities.Message)1 TextChannel (net.dv8tion.jda.core.entities.TextChannel)1 Document (org.bson.Document)1 Bson (org.bson.conversions.Bson)1 Main (ws.nmathe.saber.Main)1 EntryManager (ws.nmathe.saber.core.schedule.EntryManager)1 EventRecurrence (ws.nmathe.saber.core.schedule.EventRecurrence)1