use of net.dv8tion.jda.api.entities.TextChannel in project Saber-Bot by notem.
the class SyncCommand method action.
@Override
public void action(String head, String[] args, MessageReceivedEvent event) {
// get user Google credentials (if they exist)
Credential credential = GoogleAuth.getCredential(event.getAuthor().getId());
Calendar service = GoogleAuth.getCalendarService(credential);
int index = 0;
String cId = args[index].replaceAll("[^\\d]", "");
TextChannel channel = event.getGuild().getTextChannelById(cId);
index++;
boolean importFlag = true;
String address;
if (args.length == 1) {
address = Main.getScheduleManager().getAddress(cId);
} else {
if (args[index].equalsIgnoreCase("export")) {
importFlag = false;
index++;
} else if (args[index].equalsIgnoreCase("import")) {
index++;
}
address = args[index];
if (importFlag) {
// enable auto-sync'ing timezone
Main.getDBDriver().getScheduleCollection().updateOne(eq("_id", cId), set("timezone_sync", true));
// set user who has authorized the sync
if (GoogleAuth.authorize(event.getAuthor().getId()) != null)
Main.getDBDriver().getScheduleCollection().updateOne(eq("_id", cId), set("sync_user", event.getAuthor().getId()));
else
Main.getDBDriver().getScheduleCollection().updateOne(eq("_id", cId), set("sync_user", null));
}
}
if (importFlag) {
Main.getCalendarConverter().importCalendar(address, channel, service);
Main.getScheduleManager().setAddress(cId, address);
String content = "I have finished syncing <#" + cId + ">!";
MessageUtilities.sendMsg(content, event.getChannel(), null);
} else {
boolean success = Main.getCalendarConverter().exportCalendar(address, channel, service);
String content;
if (success) {
content = "I have finished exporting <#" + cId + ">!";
} else {
content = "I was unable to export <#" + cId + "> to " + address + "!\n" + "Please make sure I am authorized to edit that calendar!\n" + "You can provide me access through the ``oauth`` command.";
}
MessageUtilities.sendMsg(content, event.getChannel(), null);
}
}
use of net.dv8tion.jda.api.entities.TextChannel 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().isSchedule(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()) {
try // convert the list of Google Events into discord event entries
{
// 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();
Logging.info(this.getClass(), comment);
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 = ZonedDateTime.of(ParsingUtilities.parseDate(tmp, zone), LocalTime.MAX, 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);
}
} catch (Exception e) {
Logging.exception(this.getClass(), e);
}
}
// 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.getManager().setTopic(calLink).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());
}
use of net.dv8tion.jda.api.entities.TextChannel in project Saber-Bot by notem.
the class EntryManager method newEntry.
/**
* Create a new entry on a schedule
* @param se (ScheduleEntry) the base ScheduleEntry object to use
*/
public Integer newEntry(ScheduleEntry se, boolean sort) {
// identify which shard is responsible for the schedule
String guildId = se.getGuildId();
String channelId = se.getChannelId();
JDA jda = Main.getShardManager().getJDA(guildId);
// generate the reminders
se.reloadReminders(Main.getScheduleManager().getReminders(se.getChannelId())).reloadEndReminders(Main.getScheduleManager().getEndReminders(se.getChannelId()));
// process expiration date
Date expire = null;
if (se.getExpire() != null) {
expire = Date.from(se.getExpire().toInstant());
}
// process deadline
Date deadline = null;
if (se.getDeadline() != null) {
deadline = Date.from(se.getDeadline().toInstant());
}
// is rsvp enabled on the channel set empty rsvp lists
if (Main.getScheduleManager().isRSVPEnabled(se.getChannelId())) {
for (String type : Main.getScheduleManager().getRSVPOptions(se.getChannelId()).values()) {
se.setRsvpMembers(type, new ArrayList<>());
}
}
// generate event display message
se.setId(this.newId());
Message message = MessageGenerator.generate(se);
// send message to schedule
TextChannel channel = jda.getTextChannelById(channelId);
Date finalExpire = expire;
Date finalDeadline = deadline;
MessageUtilities.sendMsg(message, channel, msg -> {
try {
// add reaction options if rsvp is enabled
if (Main.getScheduleManager().isRSVPEnabled(channelId)) {
Map<String, String> map = Main.getScheduleManager().getRSVPOptions(channelId);
addRSVPReactions(map, Main.getScheduleManager().getRSVPClear(channelId), msg, se);
}
// add new document
Document entryDocument = new Document("_id", se.getId()).append("title", se.getTitle()).append("start", Date.from(se.getStart().toInstant())).append("end", Date.from(se.getEnd().toInstant())).append("comments", se.getComments()).append("recurrence", se.getRepeat()).append("reminders", se.getReminders()).append("end_reminders", se.getEndReminders()).append("url", se.getTitleUrl()).append("hasStarted", se.hasStarted()).append("messageId", msg.getId()).append("channelId", se.getChannelId()).append("googleId", se.getGoogleId()).append("rsvp_members", se.getRsvpMembers()).append("rsvp_limits", se.getRsvpLimits()).append("image", se.getImageUrl()).append("thumbnail", se.getThumbnailUrl()).append("orig_start", Date.from(se.getRecurrence().getOriginalStart().toInstant())).append("count", se.getRecurrence().getCount()).append("start_disabled", false).append("end_disabled", false).append("reminders_disabled", false).append("expire", finalExpire).append("deadline", finalDeadline).append("guildId", se.getGuildId()).append("location", se.getLocation()).append("description", se.getDescription()).append("color", se.getColor());
Main.getDBDriver().getEventCollection().insertOne(entryDocument);
// auto-sort the schedule if configured
autoSort(sort, channelId);
} catch (Exception e) {
Logging.exception(EntryManager.class, e);
}
});
return se.getId();
}
use of net.dv8tion.jda.api.entities.TextChannel in project Saber-Bot by notem.
the class ScheduleSyncer method run.
public void run() {
Logging.info(this.getClass(), "Running schedule syncer. . .");
Bson query = and(ne("sync_address", "off"), lte("sync_time", new Date()));
Main.getDBDriver().getScheduleCollection().find(query).projection(fields(include("_id", "sync_time", "sync_address", "sync_user", "guildId"))).forEach((Consumer<? super Document>) document -> {
executor.execute(() -> {
try {
String guildId = document.getString("guildId");
JDA jda = Main.getShardManager().getJDA(guildId);
if (jda == null)
return;
if (JDA.Status.valueOf("CONNECTED") != jda.getStatus())
return;
String scheduleId = document.getString("_id");
Date syncTime = Date.from(ZonedDateTime.ofInstant(document.getDate("sync_time").toInstant(), Main.getScheduleManager().getTimeZone(scheduleId)).plusDays(1).toInstant());
Main.getDBDriver().getScheduleCollection().updateOne(eq("_id", scheduleId), set("sync_time", syncTime));
String address = document.getString("sync_address");
Credential credential = document.get("sync_user") == null ? GoogleAuth.authorize() : GoogleAuth.getCredential(document.getString("sync_user"));
Calendar service = GoogleAuth.getCalendarService(credential);
TextChannel channel = jda.getTextChannelById(document.getString("_id"));
if (channel == null)
return;
if (Main.getCalendarConverter().checkValidAddress(address, service)) {
Main.getCalendarConverter().importCalendar(address, channel, service);
Logging.info(this.getClass(), "Synchronized schedule #" + channel.getName() + " [" + document.getString("_id") + "] on '" + channel.getGuild().getName() + "' [" + channel.getGuild().getId() + "]");
} else {
GuildSettingsManager.GuildSettings gs = Main.getGuildSettingsManager().getGuildSettings(guildId);
TextChannel control = Main.getShardManager().getJDA(guildId).getTextChannelById(gs.getCommandChannelId());
String content = "**Warning:** I failed to auto-sync <#" + scheduleId + "> to *" + address + "*!\n" + "Please make sure that the calendar address is still correct and that the calendar privacy settings have not changed!";
MessageUtilities.sendMsg(content, control, null);
Logging.warn(this.getClass(), "Failed to synchronize schedule #" + channel.getName() + " [" + document.getString("_id") + "] on '" + channel.getGuild().getName() + "' [" + channel.getGuild().getId() + "]");
}
} catch (Exception e) {
Logging.exception(this.getClass(), e);
}
});
});
}
use of net.dv8tion.jda.api.entities.TextChannel in project Saber-Bot by notem.
the class Pruner method run.
@Override
public void run() {
Logging.info(this.getClass(), "Running database pruner. . .");
// purge guild setting entries for any guild not connected to the bot
Bson query = new Document();
Main.getDBDriver().getGuildCollection().find(query).projection(fields(include("_id"))).forEach((Consumer<? super Document>) document -> {
try {
String guildId = document.getString("_id");
JDA jda = Main.getShardManager().getShard(guildId);
if (jda == null)
return;
if (JDA.Status.valueOf("CONNECTED") != jda.getStatus())
return;
Guild guild = jda.getGuildById(guildId);
if (guild == null) {
Main.getDBDriver().getGuildCollection().deleteOne(eq("_id", guildId));
Main.getDBDriver().getEventCollection().deleteMany(eq("guildId", guildId));
Main.getDBDriver().getScheduleCollection().deleteMany(eq("guildId", guildId));
Logging.info(this.getClass(), "Pruned guild with ID: " + guildId);
}
} catch (Exception e) {
Logging.exception(this.getClass(), e);
}
});
// purge schedules that the bot cannot connect to
query = new Document();
Main.getDBDriver().getScheduleCollection().find(query).projection(fields(include("_id", "guildId"))).forEach((Consumer<? super Document>) document -> {
try {
String guildId = document.getString("guildId");
JDA jda = Main.getShardManager().getShard(guildId);
if (jda == null)
return;
if (JDA.Status.valueOf("CONNECTED") != jda.getStatus())
return;
String chanId = document.getString("_id");
MessageChannel channel = jda.getTextChannelById(chanId);
if (channel == null) {
Main.getDBDriver().getEventCollection().deleteMany(eq("channeldId", chanId));
Main.getDBDriver().getScheduleCollection().deleteMany(eq("_id", chanId));
Logging.info(this.getClass(), "Pruned schedule with channel ID: " + chanId);
}
} catch (Exception e) {
Logging.exception(this.getClass(), e);
}
});
// purge events for which the bot cannot access the message
query = new Document();
Main.getDBDriver().getEventCollection().find(query).projection(fields(include("_id", "messageId", "channelId", "guildId"))).forEach((Consumer<? super Document>) document -> {
try {
String guildId = document.getString("guildId");
JDA jda = Main.getShardManager().getShard(guildId);
if (jda == null)
return;
if (JDA.Status.valueOf("CONNECTED") != jda.getStatus())
return;
Integer eventId = document.getInteger("_id");
String messageId = document.getString("messageId");
if (messageId == null) {
Main.getDBDriver().getEventCollection().deleteOne(eq("_id", eventId));
Logging.info(this.getClass(), "Pruned event with ID: " + eventId);
return;
}
String channelId = document.getString("channelId");
TextChannel channel = jda.getTextChannelById(channelId);
if (channel == null) {
return;
}
channel.retrieveMessageById(messageId).queue(message -> {
if (message == null) {
Main.getDBDriver().getEventCollection().deleteOne(eq("_id", eventId));
Logging.info(this.getClass(), "Pruned event with ID: " + eventId + " on channel with ID: " + channelId);
}
}, throwable -> {
Main.getDBDriver().getEventCollection().deleteOne(eq("_id", eventId));
Logging.info(this.getClass(), "Pruned event with ID: " + eventId + " on channel with ID: " + channelId);
});
} catch (Exception e) {
Logging.exception(this.getClass(), e);
}
});
}
Aggregations