Skip to content

Commit

Permalink
feat: creating timer
Browse files Browse the repository at this point in the history
  • Loading branch information
yaansz committed Oct 29, 2023
1 parent fe62631 commit d03aa66
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.softawii.capivara.core;

import com.softawii.capivara.entity.Calendar;
import com.softawii.capivara.exceptions.DuplicatedKeyException;
import com.softawii.capivara.services.CalendarService;
import com.softawii.capivara.threads.CalendarSubscriptionThread;
import net.dv8tion.jda.api.JDA;
Expand All @@ -24,7 +25,7 @@ public CalendarManager(JDA jda, CalendarService service, CalendarSubscriptionThr
this.subscriber = subscriber;
}

public void createCalendar(String googleCalendarId, String name, GuildChannelUnion channel, Role role) {
public void createCalendar(String googleCalendarId, String name, GuildChannelUnion channel, Role role) throws DuplicatedKeyException {
Long guildId = channel.getGuild().getIdLong();
Long channelId = channel.getIdLong();
Long roleId = role != null ? role.getIdLong() : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.softawii.capivara.entity.internal;

import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.api.services.calendar.model.Events;
import com.softawii.capivara.core.CalendarManager;
import com.softawii.capivara.entity.Calendar;
import com.softawii.capivara.utils.CalendarUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.text.ParseException;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

public class CalendarSubscriber {
private final Logger LOGGER = LogManager.getLogger(CalendarSubscriber.class);
private String googleCalendarId;
private List<Calendar.CalendarKey> consumers;
private com.google.api.services.calendar.Calendar calendarService;
private HashMap<String, EventWrapper> events;

private class EventWrapper extends TimerTask {
private Event event;
private final Timer timer;

public EventWrapper(Event event) {
this.event = event;
this.timer = new Timer();
setTimer();
}

private void setTimer() {
EventDateTime eventStart = this.event.getStart();
EventDateTime eventEnd = this.event.getEnd();
Instant now = Instant.now();
DateTime dateStart;
DateTime dateEnd;
boolean isAllDayEvent = eventStart.getDate() != null && eventEnd.getDate() != null;

if (isAllDayEvent) {
dateStart = eventStart.getDate();
dateEnd = eventEnd.getDate();
} else {
dateStart = eventStart.getDateTime();
dateEnd = eventEnd.getDateTime();
}

boolean alreadyStarted = dateStart.getValue() <= now.toEpochMilli();
boolean alreadyEnded = dateEnd.getValue() <= now.toEpochMilli();

if(!alreadyEnded && !alreadyStarted) {
Date scheduled = new Date(dateStart.getValue());
LOGGER.info("Event scheduled: " + this.event.getSummary() + ", date: " + scheduled);
this.timer.schedule(this, scheduled);
}
}

public void setEvent(Event event) {
if(this.event.getStart() != event.getStart()) {
this.timer.cancel();
this.timer.purge();
setTimer();
}

this.event = event;
}

@Override
public void run() {
LOGGER.info("Event started: " + this.event.getSummary());
}
}

public CalendarSubscriber(String googleCalendarId, com.google.api.services.calendar.Calendar calendarService, Calendar.CalendarKey consumer) {
this.googleCalendarId = googleCalendarId;
this.calendarService = calendarService;
this.events = new HashMap<>();
this.consumers = new ArrayList<>();
this.consumers.add(consumer);
update();
}

public void subscribe(Calendar.CalendarKey consumer) {
if (!this.consumers.contains(consumer)) {
this.consumers.add(consumer);
}
}

public void unsubscribe(Calendar.CalendarKey consumer) {
this.consumers.remove(consumer);
}

private List<Event> getEvents() {
List<Event> items = new ArrayList<>();
String pageToken = null;
do {
try {
Events events = calendarService
.events()
.list(googleCalendarId)
.setSingleEvents(true)
.setTimeMin(CalendarUtil.getMinDateTime(-1))
.setTimeMax(CalendarUtil.getMaxDateTime(1))
.setOrderBy("startTime")
.setPageToken(pageToken)
.execute();
items.addAll(events.getItems());
pageToken = events.getNextPageToken();
} catch (GoogleJsonResponseException e) {
if ((e.getStatusCode() == 403 && !e.getStatusMessage().equals("Forbidden")) || e.getStatusCode() == 429) {
LOGGER.error(e.getDetails().getMessage() + " - rate limit - " + e.getDetails().getCode());
return null;
} else {
LOGGER.error(e.getDetails().getMessage());
return null;
}
} catch (IOException e) {
LOGGER.error(e.getMessage());
return null;
}
} while (pageToken != null);

return items;
}

private void checkForUpdates(List<Event> events) {
// Removing events
Set<String> localKeys = this.events.keySet();
Set<String> remoteKeys = events.stream().map(Event::getId).collect(Collectors.toSet());
localKeys.removeAll(remoteKeys);

// Removing events
for (String key : localKeys) {
EventWrapper eventWrapper = this.events.get(key);
LOGGER.info("Event removed: " + eventWrapper.event.getSummary());
eventWrapper.cancel();
eventWrapper.timer.purge();
this.events.remove(key);
}

// Updating events
for (Event event : events) {
String eventId = event.getId();
EventWrapper eventWrapper = this.events.get(eventId);
if (eventWrapper == null) {
this.events.put(eventId, new EventWrapper(event));
LOGGER.info("Event added: " + event.getSummary());
} else {
eventWrapper.setEvent(event);
}
}
}

public void update() {
List<Event> events = getEvents();
if (events != null) {
checkForUpdates(events);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.softawii.capivara.exceptions;

public class DuplicatedKeyException extends Exception {

public DuplicatedKeyException() {
}

public DuplicatedKeyException(String message) {
super(message);
}

public DuplicatedKeyException(String message, Throwable cause) {
super(message, cause);
}

public DuplicatedKeyException(Throwable cause) {
super(cause);
}

public DuplicatedKeyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.softawii.capivara.services;

import com.softawii.capivara.entity.Calendar;
import com.softawii.capivara.exceptions.DuplicatedKeyException;
import com.softawii.capivara.repository.CalendarRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -25,10 +26,10 @@ public Optional<Calendar> find(Calendar.CalendarKey calendarKey) {
return repository.findById(calendarKey);
}

public void create(Calendar calendar) {
public void create(Calendar calendar) throws DuplicatedKeyException {
if (repository.existsById(calendar.getCalendarKey())) {
// TODO: create new exception
throw new RuntimeException("Calendar already exists with this name and guild");
throw new DuplicatedKeyException("Calendar already exists with this name and guild, use update instead");
}
repository.save(calendar);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.Events;
import com.softawii.capivara.entity.Calendar;
import com.softawii.capivara.entity.internal.CalendarSubscriber;
import com.softawii.capivara.services.CalendarService;
import net.dv8tion.jda.api.JDA;
import org.apache.logging.log4j.LogManager;
Expand Down Expand Up @@ -38,43 +39,34 @@ public class CalendarSubscriptionThread implements Runnable {
private final JDA jda;
private final com.google.api.services.calendar.Calendar googleCalendarService;
private final CalendarService calendarService;
// private final HashMap<String, >

public CalendarSubscriptionThread(JDA jda, CalendarService calendarService, com.google.api.services.calendar.Calendar googleCalendarService) {
this.jda = jda;
this.googleCalendarService = googleCalendarService;
this.queue = new LinkedBlockingQueue<>();
this.scheduler = Executors.newScheduledThreadPool(1);
this.calendarService = calendarService;

startupSubscriber();

Thread thread = new Thread(this);
thread.start();
LOGGER.info("CalendarSubscriptionThread started");
}

public void niceName() {
private void startupSubscriber() {
PageRequest request = PageRequest.of(0, 100);
Page<Calendar> calendarPage = this.calendarService.findAll(request);
while (calendarPage.hasContent()) {
calendarPage.forEach(calendar -> {
Calendar.CalendarKey calendarKey = calendar.getCalendarKey();
String name = calendarKey.getCalendarName();
Long guildId = calendarKey.getGuildId();
});

calendarPage.forEach(this::subscribe);
request = request.next();
calendarPage = this.calendarService.findAll(request);
}
}

private void subscribe(Calendar calendar) throws IOException {
String pageToken = null;
do {
Events events = googleCalendarService.events()
.list(calendar.getGoogleCalendarId())
.setPageToken(pageToken)
.execute();
List<Event> items = events.getItems();
for (Event event : items) {
LOGGER.info(event.getSummary());
}
pageToken = events.getNextPageToken();
} while (pageToken != null);
private void subscribe(Calendar calendar) {
new CalendarSubscriber(calendar.getGoogleCalendarId(), this.googleCalendarService, calendar.getCalendarKey());
}

@Override
Expand Down

0 comments on commit d03aa66

Please sign in to comment.