From 16e278bc70ec58dc5dd2e90f5ff6f8bfa41b73be Mon Sep 17 00:00:00 2001 From: Ryeera <79052127+Ryeera@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:17:33 +0200 Subject: [PATCH 1/9] Updated Argus to 1.1.0 + Added a permission-checker. * Updated JDA to 4.3.0_310 * Changed Interval of resyncs from 1 to 6 hours * Now checks for missing permissions and alerts upon permission-errors * Bot now works without its own role * Bot now uses its own member instead of its role for overrides - Removed unnecessary Gateway Intents - Removed unnecessary CacheFlags - Disabled loading all members on startup since JDA 4.3 made this obsolete --- Discord - Argus/.settings/.gitignore | 1 + .../.settings/org.eclipse.jdt.core.prefs | 14 + Discord - Argus/pom.xml | 10 +- .../src/main/java/de/Ryeera/Argus/Argus.java | 340 +++++++++++++----- 4 files changed, 274 insertions(+), 91 deletions(-) create mode 100644 Discord - Argus/.settings/.gitignore diff --git a/Discord - Argus/.settings/.gitignore b/Discord - Argus/.settings/.gitignore new file mode 100644 index 0000000..8b807c2 --- /dev/null +++ b/Discord - Argus/.settings/.gitignore @@ -0,0 +1 @@ +/fr.kazejiyu.discord.rpc.integration.prefs diff --git a/Discord - Argus/.settings/org.eclipse.jdt.core.prefs b/Discord - Argus/.settings/org.eclipse.jdt.core.prefs index fd9afef..2876057 100644 --- a/Discord - Argus/.settings/org.eclipse.jdt.core.prefs +++ b/Discord - Argus/.settings/org.eclipse.jdt.core.prefs @@ -1,2 +1,16 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=15 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=15 diff --git a/Discord - Argus/pom.xml b/Discord - Argus/pom.xml index 57ce298..f795370 100644 --- a/Discord - Argus/pom.xml +++ b/Discord - Argus/pom.xml @@ -2,20 +2,20 @@ 4.0.0 de.Ryeera Argus - 1.0.1 + 1.1.0 Argus - jcenter - jcenter-bintray - https://jcenter.bintray.com + dv8tion + m2-dv8tion + https://m2.dv8tion.net/releases net.dv8tion JDA - 4.2.0_230 + 4.3.0_310 club.minnced diff --git a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java index a73d374..719990a 100644 --- a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java +++ b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java @@ -42,15 +42,15 @@ import net.dv8tion.jda.api.events.guild.GuildLeaveEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.requests.restaction.ChannelAction; -import net.dv8tion.jda.api.utils.MemberCachePolicy; import net.dv8tion.jda.api.utils.cache.CacheFlag; public class Argus extends ListenerAdapter { - private static final String VERSION = "1.0.1"; + private static final String VERSION = "1.1.0"; private static DragoLogger logger; @@ -59,6 +59,7 @@ public class Argus extends ListenerAdapter { private static JDA jda; private static final EnumSet readPerms = EnumSet.of(Permission.MESSAGE_READ); + private static final EnumSet selfPerms = EnumSet.of(Permission.MESSAGE_READ, Permission.MESSAGE_WRITE, Permission.MANAGE_CHANNEL, Permission.MESSAGE_EMBED_LINKS); private static SQLConnector sql; @@ -104,21 +105,15 @@ public static void main(String[] args) { + "COMMENT = 'Contains all current temporary voice channels';"); logger.log("INFO", "Setting up Discord-Connection..."); - JDABuilder builder = JDABuilder.create(GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_VOICE_STATES, GatewayIntent.GUILD_MEMBERS); - builder.enableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.ROLE_TAGS); - builder.disableCache(CacheFlag.ACTIVITY, CacheFlag.EMOTE, CacheFlag.CLIENT_STATUS); + JDABuilder builder = JDABuilder.create(GatewayIntent.GUILD_MESSAGES, GatewayIntent.GUILD_VOICE_STATES); + builder.enableCache(CacheFlag.MEMBER_OVERRIDES); + builder.disableCache(CacheFlag.ACTIVITY, CacheFlag.EMOTE, CacheFlag.CLIENT_STATUS, CacheFlag.ONLINE_STATUS, CacheFlag.ROLE_TAGS); builder.setToken(config.getString("token")); builder.setActivity(Activity.watching("the VoiceChannels")); - builder.setMemberCachePolicy(MemberCachePolicy.ALL); builder.addEventListeners(new Argus()); try { jda = builder.build(); jda.awaitReady(); - for (Guild guild : jda.getGuilds()) { - guild.loadMembers().onSuccess(m -> { - logger.log("INFO", "Loaded " + m.size() + " members for " + guild.getName()); - }); - } } catch (LoginException | InterruptedException e) { logger.logStackTrace(e); System.exit(1); @@ -127,13 +122,15 @@ public static void main(String[] args) { Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> { logger.log("INFO", "Resyncing..."); for (Guild guild : jda.getGuilds()) { - try { + logger.log("INFO", "Resyncing " + guild.getName() + " (" + guild.getId() + ")..."); + try { resync(guild); } catch (Exception e) { logger.logStackTrace(e); } } - }, 1, 60, TimeUnit.MINUTES); + logger.log("INFO", "Resync complete!"); + }, 1, 360, TimeUnit.MINUTES); logger.log("INFO", "Argus started! I'm watching..."); } @@ -159,7 +156,9 @@ public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { if (guild.getAfkChannel() == null || !joined.getId().equals(guild.getAfkChannel().getId())) { logger.log("INFO", "Processing join event for user \"" + member.getUser().getAsTag() + "\" in \"" + guild.getName() + " / " + joined.getName() + "\"..."); - tc.putPermissionOverride(member).grant(readPerms).queue(); + tc.putPermissionOverride(member).grant(readPerms).queue(success -> {}, failure -> { + tc.sendMessage("Yo I can't add Permission-Overrides to this channel! Please edit this channel so I explicitely have the `Manage Permissions` permission!").queue(); + }); if (guildConfig.getBoolean("Logging")) { tc.sendMessage("**" + member.getEffectiveName() + "** joined the channel.").queue(); } @@ -188,7 +187,9 @@ public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { if (guild.getAfkChannel() == null || !left.getId().equals(guild.getAfkChannel().getId())) { logger.log("INFO", "Processing leave event for user \"" + member.getUser().getAsTag() + "\" in \"" + guild.getName() + " / " + left.getName() + "\"..."); - tc.getPermissionOverride(member).delete().queue(); + try { + tc.getPermissionOverride(member).delete().queue(); + } catch (NullPointerException e) {} if (guildConfig.getBoolean("Logging")) { tc.sendMessage("**" + member.getEffectiveName() + "** left the channel.").queue(); } @@ -267,8 +268,9 @@ public void onTextChannelDelete(TextChannelDeleteEvent event) { try (ResultSet association = sql.executeQuery("SELECT * FROM `Associations` WHERE `tc` = " + tc.getId())) { if (association.first()) { VoiceChannel vc = guild.getVoiceChannelById(association.getLong("vc")); - logger.log("WARN", "Text Channel for the Voice Channel \"" + vc.getName() + "\" was deleted... Recreating..."); removeAssociation(vc.getId()); + if (guild.getAfkChannel() != null && vc.equals(guild.getAfkChannel())) return; + logger.log("WARN", "Text Channel for the Voice Channel \"" + vc.getName() + "\" was deleted... Recreating..."); if (createTextChannel(vc, guild, guildConfig)) { logger.log("INFO", "Text-Channel created!"); } else { @@ -285,26 +287,13 @@ public void onTextChannelDelete(TextChannelDeleteEvent event) { logger.logStackTrace(e); } } - - public static void register(Guild guild) { - sql.executeUpdate("INSERT INTO `Settings` (`GuildID`, `Initialized`, `Logging`, `Prefix`, `Names`, `Descriptions`) VALUES (" - + "'" + guild.getId() + "', " - + "'0', " - + "'0', " - + "'a!', " - + "'{vc}-text', " - + "'Text-Channel for everyone in the voice-channel [**{vc}**]')"); - guild.createTextChannel("argus").addPermissionOverride(guild.getBotRole(), readPerms, null).addPermissionOverride(guild.getPublicRole(), null, readPerms).queue(tc -> { - tc.sendMessage(guild.getOwner().getAsMention() + "\n__**Thanks for inviting me!**__\n\nTo start off, run the command `a!setup`!\n**I can't do anything until you do so!**").queueAfter(5, TimeUnit.SECONDS); - }); - } public static boolean createTextChannel(VoiceChannel vc, Guild guild, ResultSet guildConfig) { try { logger.log("INFO", "VC \"" + vc.getName() + "\" has no associated text-channel configured! Creating..."); ChannelAction action = guild.createTextChannel(guildConfig.getString("Names").replace("{vc}", vc.getName())); action.setTopic(guildConfig.getString("Descriptions").replace("{vc}", vc.getName())); - action.addPermissionOverride(guild.getBotRole(), readPerms, null); + action.addPermissionOverride(guild.getSelfMember(), selfPerms, null); action.addPermissionOverride(guild.getPublicRole(), null, readPerms); if (vc.getParent() != null) { action.setParent(vc.getParent()); @@ -322,10 +311,41 @@ public static boolean createTextChannel(VoiceChannel vc, Guild guild, ResultSet } } + public static void register(Guild guild) { + try { + guild.createTextChannel("argus").addPermissionOverride(guild.getSelfMember(), selfPerms, null).addPermissionOverride(guild.getPublicRole(), null, readPerms).queue(tc -> { + guild.retrieveOwner().queue(owner -> { + tc.sendMessage(owner.getAsMention() + "\n__**Thanks for inviting me!**__\n\nTo start off, run the command `a!setup`!\n**I can't do anything until you do so!**").queueAfter(5, TimeUnit.SECONDS); + }); + }); + } catch (InsufficientPermissionException e) { + e.printStackTrace(); + TextChannel tc = null; + for (TextChannel channel : guild.getTextChannels()) { + if (guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_WRITE)) { + tc = channel; + break; + } + } + if (tc == null) return; + final TextChannel tcf = tc; + guild.retrieveOwner().queue(owner -> { + tcf.sendMessage(owner.getAsMention() + "\n__**Thanks for inviting me!**__\n\nTo start off, run the command `a!setup`!\n**I can't do anything until you do so!**").queue(); + tcf.sendMessage("I just realized that I'm missing permissions! I can only do my job properly if I have the following permissions:\n- View Channels\n- Manage Channels\n- Manage Roles\n- Send Messages\n- Embed Links\n- Move Members\n\nIf you wanna know why I need these permissions, check !").queue(); + }); + } + sql.executeUpdate("INSERT INTO `Settings` (`GuildID`, `Initialized`, `Logging`, `Prefix`, `Names`, `Descriptions`) VALUES (" + + "'" + guild.getId() + "', " + + "'0', " + + "'0', " + + "'a!', " + + "'{vc}-text', " + + "'Text-Channel for everyone in the voice-channel [**{vc}**]')"); + } + public static void initialize(Guild guild) { try (ResultSet guildConfig = getGuildConfig(guild)) { for (VoiceChannel vc : guild.getVoiceChannels()) { - logger.log("INFO", "Checking VC \"" + guild.getName() + " / " + vc.getName() + "\"..."); String vcID = vc.getId(); ResultSet association = sql.executeQuery("SELECT * FROM `Associations` WHERE `vc` = " + vcID); try { @@ -359,15 +379,69 @@ public static void resync(Guild guild) { if (guild.getAfkChannel() != null && vc.equals(guild.getAfkChannel())) continue; try { TextChannel tc = guild.getTextChannelById(getAssociation(vc.getId())); + //TODO: Remove after a while + if (guild.getBotRole() != null) { + for (PermissionOverride perm : tc.getRolePermissionOverrides()) { + if (perm.getRole().equals(guild.getBotRole())) { + tc.putPermissionOverride(guild.getSelfMember()).grant(selfPerms).queue(); + perm.delete().queueAfter(10, TimeUnit.SECONDS); + break; + } + } + } for (PermissionOverride perm : tc.getMemberPermissionOverrides()) { Member permmember = perm.getMember(); - if (!vc.getMembers().contains(permmember)) { + if (!vc.getMembers().contains(permmember) && !permmember.equals(guild.getSelfMember())) { perm.delete().queue(); } } for (Member member : vc.getMembers()) { if (!tc.canTalk(member)) { - tc.putPermissionOverride(member).grant(readPerms).queue(); + tc.putPermissionOverride(member).grant(readPerms).queue(success -> {}, failure -> { + tc.sendMessage("Yo I can't add Permission-Overrides to this channel! Please edit this channel so I explicitely have the `Manage Permissions` permission!").queue(); + }); + } + } + boolean permswrong = false; + if (!guild.getSelfMember().hasPermission(tc, Permission.VIEW_CHANNEL)) { + permswrong = true; + } else if (!guild.getSelfMember().hasPermission(tc, Permission.MESSAGE_WRITE)) { + permswrong = true; + } else if (!guild.getSelfMember().hasPermission(tc, Permission.MANAGE_CHANNEL)) { + permswrong = true; + } else if (!guild.getSelfMember().hasPermission(tc, Permission.MANAGE_PERMISSIONS)) { + permswrong = true; + } else if (!guild.getSelfMember().hasPermission(tc, Permission.MESSAGE_EMBED_LINKS)) { + permswrong = true; + } + if (permswrong) { + try { + tc.upsertPermissionOverride(guild.getSelfMember()).grant(selfPerms).queue(); + } catch (InsufficientPermissionException e) { + try { + guild.createTextChannel("argus").addPermissionOverride(guild.getSelfMember(), selfPerms, null).addPermissionOverride(guild.getPublicRole(), null, readPerms).queue(nc -> { + String prefix = "a!"; + try { + prefix = guildConfig.getString("Prefix").replace("<@!655496558095237130>", "@Argus "); + } catch (SQLException e1) {} + nc.sendMessage("Hey there! I got permission-issues with " + tc.getAsMention() + "! Please run " + prefix + "debug permcheck to run a detailed permission-checkup on your server. Please readd all missing server- and channel-permissions! Thank youuuuu!").queue(); + }); + } catch (InsufficientPermissionException ex) { + TextChannel nc = null; + for (TextChannel channel : guild.getTextChannels()) { + if (guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_WRITE)) { + nc = channel; + break; + } + } + if (nc != null) { + String prefix = "a!"; + try { + prefix = guildConfig.getString("Prefix").replace("<@!655496558095237130>", "@Argus "); + } catch (SQLException e1) {} + nc.sendMessage("Hey there! I got permission-issues with " + tc.getAsMention() + "! Please run " + prefix + "debug permcheck to run a detailed permission-checkup on your server. Please readd all missing server- and channel-permissions! Thank youuuuu!").queue(); + } + } } } } catch (SQLException e) { @@ -387,9 +461,6 @@ public void onGuildJoin(GuildJoinEvent event) { Guild guild = event.getGuild(); logger.log("INFO", "Joined Guild \"" + guild.getName() + "\"! Sending setup-message..."); register(guild); - guild.loadMembers().onSuccess(m -> { - logger.log("INFO", "Loaded " + m.size() + " members for " + guild.getName()); - }); } @Override @@ -454,6 +525,11 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { Member sender = event.getMember(); String message = event.getMessage().getContentRaw(); try (ResultSet guildConfig = getGuildConfig(guild)) { + if (!guildConfig.first()) { + register(guild); + channel.sendMessage("Apparently your guild wasn't registered yet! This happens when you invite me while I'm offline. No problem though, I will do that for you now! Please wait a minute and then try your command again!").queue(); + return; + } if (message.startsWith(guildConfig.getString("Prefix"))) { message = message.substring(guildConfig.getString("Prefix").length()).trim(); if (message.startsWith("temp")) { @@ -470,63 +546,120 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { }); } } else if (message.equalsIgnoreCase("help")) { - channel.sendMessage(getHelpEmbed(guild)).queue(); - } else if (message.equalsIgnoreCase("fixperms")) { - channel.sendMessage("Fixing permissions to be able to work without Admin-Permissions...").queue(); - for (VoiceChannel vc : guild.getVoiceChannels()) { - if (guild.getAfkChannel() != null && vc.getId().equals(guild.getAfkChannel().getId())) continue; - try { - TextChannel tc = guild.getTextChannelById(getAssociation(vc.getId())); - tc.putPermissionOverride(guild.getBotRole()).grant(readPerms).queue(); - } catch (Exception e) { - logger.log("ERROR", guild.getName() + " / " + vc.getName() + "(" + guild.getId() + " / " + vc.getId() + " has no association!"); - logger.logStackTrace(e); - } - } - channel.sendMessage("Your server is now up-to-date and you can remove my Admin-Permissions! Remember to instead give me the following permissions:\n" - + "- View Channels\n" - + "- Manage Channels\n" - + "- Manage Roles\n" - + "- Send Messages\n" - + "- Embed Links\n" - + "- Move Members\n\n" - + "If you wanna know why I need these permissions, check !").queueAfter(10, TimeUnit.SECONDS); - } else if (message.equalsIgnoreCase("resync")) { - channel.sendMessage("Manually resyncing this server...").queue(); - resync(guild); - channel.sendMessage("Done resyncing!").queueAfter(5, TimeUnit.SECONDS); - } else if (message.startsWith("debug ")) { - message = message.substring(6); - if (message.equalsIgnoreCase("servercount")) { - channel.sendMessage("I am currently in **" + jda.getGuilds().size() + "** servers!").queue(); - } - } else if (message.startsWith("broadcast ") && sender.getId().equals("553576678186680340")) { - message = message.substring(10); - for (Guild g : jda.getGuilds()) { - String prefix = "a!"; - try (ResultSet conf = getGuildConfig(g)) { - prefix = conf.getString("Prefix").replace("<@!655496558095237130>", "@Argus "); - } catch (SQLException e) { - logger.log("ERROR", g.getName() + "(" + g.getId() + ") Config couldn't be loaded!"); - logger.logStackTrace(e); - } - final String mes = message.replace("[OWNER]", g.getOwner().getAsMention()).replace("[PREFIX]", prefix); - g.createTextChannel("argus").addPermissionOverride(g.getBotRole(), readPerms, null).addPermissionOverride(g.getPublicRole(), null, readPerms).queue(tc -> { - tc.sendMessage(mes).queue(m -> { - tc.sendMessage("You can delete this channel when you're done!").queue(); - }); - }); - } - channel.sendMessage("Broadcast sent!").queue(); + channel.sendMessageEmbeds(getHelpEmbed(guild)).queue(); } else if (sender.hasPermission(Permission.ADMINISTRATOR)) { if (message.equalsIgnoreCase("setup") && !guildConfig.getBoolean("Initialized")) { channel.sendMessage("Please edit the settings to your liking with `a!settings` and afterwards finish the setup with `a!initialize`!").queue(); + } else if (message.equalsIgnoreCase("fixperms")) { + channel.sendMessage("Fixing permissions to be able to work without Admin-Permissions...").queue(); + for (VoiceChannel vc : guild.getVoiceChannels()) { + if (guild.getAfkChannel() != null && vc.getId().equals(guild.getAfkChannel().getId())) continue; + try { + TextChannel tc = guild.getTextChannelById(getAssociation(vc.getId())); + tc.putPermissionOverride(guild.getSelfMember()).grant(selfPerms).queue(); + } catch (Exception e) { + logger.log("ERROR", guild.getName() + " / " + vc.getName() + "(" + guild.getId() + " / " + vc.getId() + " has no association!"); + logger.logStackTrace(e); + } + } + channel.sendMessage("Your server is now up-to-date and you can remove my Admin-Permissions! Remember to instead give me the following permissions:\n" + + "- View Channels\n" + + "- Manage Channels\n" + + "- Manage Roles\n" + + "- Send Messages\n" + + "- Embed Links\n" + + "- Move Members\n\n" + + "If you wanna know why I need these permissions, check !").queueAfter(10, TimeUnit.SECONDS); + } else if (message.equalsIgnoreCase("resync")) { + channel.sendMessage("Manually resyncing this server...").queue(); + resync(guild); + channel.sendMessage("Done resyncing!").queueAfter(5, TimeUnit.SECONDS); + } else if (message.startsWith("debug ")) { + message = message.substring(6); + if (message.equalsIgnoreCase("servercount")) { + channel.sendMessage("I am currently in **" + jda.getGuilds().size() + "** servers!").queue(); + } else if (message.equalsIgnoreCase("permcheck")) { + String send1 = "__**Server-Permissions:**__"; + if (guild.getSelfMember().hasPermission(Permission.VIEW_CHANNEL)) { + send1 += "\n✅ View Channels"; + } else { + send1 += "\n⛔ View Channels"; + } + if (guild.getSelfMember().hasPermission(Permission.MESSAGE_WRITE)) { + send1 += "\n✅ Send Messages"; + } else { + send1 += "\n⛔ Send Messages"; + } + if (guild.getSelfMember().hasPermission(Permission.MESSAGE_EMBED_LINKS)) { + send1 += "\n✅ Embed Links"; + } else { + send1 += "\n⛔ Embed Links"; + } + if (guild.getSelfMember().hasPermission(Permission.MANAGE_CHANNEL)) { + send1 += "\n✅ Manage Channels"; + } else { + send1 += "\n⛔ Manage Channels"; + } + if (guild.getSelfMember().hasPermission(Permission.MANAGE_ROLES)) { + send1 += "\n✅ Manage Roles"; + } else { + send1 += "\n⛔ Manage Roles"; + } + if (guild.getSelfMember().hasPermission(Permission.VOICE_MOVE_OTHERS)) { + send1 += "\n✅ Move Members"; + } else { + send1 += "\n⛔ Move Members"; + } + channel.sendMessage(send1).queue(m1 -> { + channel.sendMessage("__**Channel-Permissions:**__").queueAfter(3, TimeUnit.SECONDS, m2 -> { + for (VoiceChannel vc : guild.getVoiceChannels()) { + String send2 = "**Voice-Channel:** " + vc.getAsMention(); + try { + TextChannel tc = guild.getTextChannelById(getAssociation(vc.getId())); + if (tc == null) { + send2 += "\nNo associated Text-Channel found!"; + } else { + send2 += "\nAssociated text-channel: " + tc.getAsMention(); + if (guild.getSelfMember().hasPermission(tc, Permission.VIEW_CHANNEL)) { + send2 += "\n✅ View Channel"; + } else { + send2 += "\n⛔ View Channel"; + } + if (guild.getSelfMember().hasPermission(tc, Permission.MESSAGE_WRITE)) { + send2 += "\n✅ Send Messages"; + } else { + send2 += "\n⛔ Send Messages"; + } + if (guild.getSelfMember().hasPermission(tc, Permission.MANAGE_CHANNEL)) { + send2 += "\n✅ Manage Channel"; + } else { + send2 += "\n⛔ Manage Channel"; + } + if (guild.getSelfMember().hasPermission(tc, Permission.MANAGE_PERMISSIONS)) { + send2 += "\n✅ Manage Permissions"; + } else { + send2 += "\n⛔ Manage Permissions"; + } + if (guild.getSelfMember().hasPermission(tc, Permission.MESSAGE_EMBED_LINKS)) { + send2 += "\n✅ Embed Links"; + } else { + send2 += "\n⛔ Embed Links"; + } + } + } catch (SQLException e) { + send2 += "\nNo associated Text-Channel found!"; + } + channel.sendMessage(send2).queue(); + } + }); + }); + } } else if (message.equalsIgnoreCase("initialize") && !guildConfig.getBoolean("Initialized")) { channel.sendMessage("Initialization in progress...").queue(); initialize(guild); - channel.sendMessage("Setup complete! You can now delete this channel!").queueAfter(6, TimeUnit.SECONDS); + channel.sendMessage("Setup complete!").queueAfter(6, TimeUnit.SECONDS); } else if (message.equalsIgnoreCase("settings")) { - channel.sendMessage(getSettingsEmbed(guild)).queue(); + channel.sendMessageEmbeds(getSettingsEmbed(guild)).queue(); } else if (message.startsWith("settings ")) { message = message.substring(9); if (message.equalsIgnoreCase("prefix")) { @@ -570,6 +703,41 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { } } } + } else if (message.startsWith("broadcast ") && sender.getId().equals("553576678186680340")) { + message = message.substring(10); + for (Guild g : jda.getGuilds()) { + String prefix = "a!"; + try (ResultSet conf = getGuildConfig(g)) { + prefix = conf.getString("Prefix").replace("<@!655496558095237130>", "@Argus "); + } catch (SQLException e) { + logger.log("ERROR", g.getName() + "(" + g.getId() + ") Config couldn't be loaded!"); + logger.logStackTrace(e); + } + final String messagef = message; + final String prefixf = prefix; + guild.retrieveOwner().queue(owner -> { + final String mes = messagef.replace("[OWNER]", owner.getAsMention()).replace("[PREFIX]", prefixf); + try { + g.createTextChannel("argus").addPermissionOverride(g.getSelfMember(), selfPerms, null).addPermissionOverride(g.getPublicRole(), null, readPerms).queue(tc -> { + tc.sendMessage(mes).queue(m -> { + tc.sendMessage("You can delete this channel when you're done!").queue(); + }); + }); + } catch (InsufficientPermissionException e) { + TextChannel tc = null; + for (TextChannel c : guild.getTextChannels()) { + if (guild.getSelfMember().hasPermission(c, Permission.MESSAGE_WRITE)) { + tc = c; + break; + } + } + if (tc != null) { + tc.sendMessage(mes).queue(); + } + } + }); + } + channel.sendMessage("Broadcast sent!").queue(); } } } catch (SQLException e) { From 7ab645349f23263e2dc6b34f39040f337ec30362 Mon Sep 17 00:00:00 2001 From: Ryeera Lunala <79052127+Ryeera@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:28:29 +0200 Subject: [PATCH 2/9] Updated Readme to explain use of Admin-Permissions --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a5f4911..3700a93 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@ When you add me to your server, I will add a text-channel for each voice-channel But here comes the catch: These text-channels are invisible until you actually join the voice-channel! This has the upside, that nobody can see or write in the text-channel, unless they are in the corresponding voice-channel (or unless you're an admin, sorry I can't do anything about that ^^"). -And if that wasn't enough yet, I can also create temporary voice-channels with just one command and optionally log the joins and leaves! +And if that wasn't enough yet, I can also create temporary voice-channels with just one command and log the joins and leaves in the text-channel! + +## Why Admin-permissions? -## Add me! -You can add me to your Discord-Server by clicking [here](https://discord.com/api/oauth2/authorize?client_id=655496558095237130&permissions=285232144&scope=bot) ## Setup When you invite me to your server, I will make a new channel, which only admins can see, and explain everything there. Don't worry, you can delete it when we're done. @@ -26,6 +26,9 @@ All commands need to be preceded with the prefix you set. If you haven't set one `a!resync` - manually resyncs your server. Use this if you notice that someone is missing their permissions to see the text-channel they should see. ## FAQ +**Why does Argus need Administrator permissions?** +Discord's permissions are REALLY weird. If I try to add a permission-override in a channel that is in a hidden category, I need explicit "Manage Permissions"-permission in this text-channel. And I can only give me that permission if I already have it. Or have admin-permissions. So you don't have to give me admin-permissions, you unfortunately have to manually edit every text-channel I create. If you don't want to give me admin-permissions and are still wondering why I need the other permissions, keep reading! + **Why does Argus need the Manage Roles permission?** Manage Roles allows me to change permission-overrides in Text-Channels. I won't change anything in your role-system, and if you don't trust me, you can move my role all the way to the bottom, I'll still do my thing but I can't change any roles above mine ^^ @@ -38,13 +41,11 @@ Although this feature is not implemented yet, I will be able to move members int **Why does Argus not work with some channels?** If that happens, please join my Discord-Server below, so Ryeera can help you. It shouldn't happen, but if it does, please tell him. -## Support -If you have any feature-requests, bug-reports or change-requests, feel free to drop by at my [Discord-Server](https://discord.gg/ffrArfErfH)! - ## Planned Features - Private Voice-Channels -- Command to make it so a voice-channel doesn't have an associated text-channel anymore +- Command to make it so a voice-channel doesn't have an associated text-channel anymore / blacklist - More Options - Instead of assigning permissions to an existing text-channel, create a new text-channel (more organized for admins) - Format Logging - Create Master-text-channel for copying permissions (for example so that mods can always see the text-channels) +- Support for bots like Server Stats that use voice-channels in a way that means that Argus shouldn't create a text-channel for them. From 727e9328e9020093a539b2ae268d6bf7fa343701 Mon Sep 17 00:00:00 2001 From: Ryeera Lunala <79052127+Ryeera@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:44:43 +0200 Subject: [PATCH 3/9] Updated readme to include a link to invite the bot --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3700a93..336bf67 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ But here comes the catch: These text-channels are invisible until you actually j And if that wasn't enough yet, I can also create temporary voice-channels with just one command and log the joins and leaves in the text-channel! -## Why Admin-permissions? - +## Invite +You can invite me to your server using this link: [INVITE](https://discord.com/oauth2/authorize?client_id=709749978326630410&permissions=285232152&scope=bot) ## Setup When you invite me to your server, I will make a new channel, which only admins can see, and explain everything there. Don't worry, you can delete it when we're done. From 321c755826f3f67e2e1d8922afc91a513aef15b6 Mon Sep 17 00:00:00 2001 From: Ryeera Lunala <79052127+Ryeera@users.noreply.github.com> Date: Thu, 2 Sep 2021 18:48:03 +0200 Subject: [PATCH 4/9] Wrong link who dis? --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 336bf67..7bfe8b8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ But here comes the catch: These text-channels are invisible until you actually j And if that wasn't enough yet, I can also create temporary voice-channels with just one command and log the joins and leaves in the text-channel! ## Invite -You can invite me to your server using this link: [INVITE](https://discord.com/oauth2/authorize?client_id=709749978326630410&permissions=285232152&scope=bot) +You can invite me to your server using this link: [INVITE](https://discord.com/api/oauth2/authorize?client_id=655496558095237130&permissions=285232152&scope=bot) ## Setup When you invite me to your server, I will make a new channel, which only admins can see, and explain everything there. Don't worry, you can delete it when we're done. From 63b6ffa1d4fe6423e80f33dc332e2aa9714d1d4c Mon Sep 17 00:00:00 2001 From: Siiriiks Date: Fri, 3 Sep 2021 00:55:59 +0100 Subject: [PATCH 5/9] Small Feature and Typo Fix * Change to ID-based Category Management Helps to reduce errors and provides the ability for the user to change the category name for temporary channels. * Fix small typo Provides correct response to command. Co-authored-by: Ryeera <79052127+Ryeera@users.noreply.github.com> --- .../src/main/java/de/Ryeera/Argus/Argus.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java index 719990a..65e67e7 100644 --- a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java +++ b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java @@ -92,6 +92,7 @@ public static void main(String[] args) { + "`Prefix` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'a!' , " + "`Names` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '{vc}-text' , " + "`Descriptions` VARCHAR(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'Text-Channel for everyone in the voice-channel [**{vc}**]' , " + + "`TempCatID` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' , " + "PRIMARY KEY (`GuildID`)) " + "COMMENT = 'Contains all Settings for Argus';"); sql.executeUpdate("CREATE TABLE IF NOT EXISTS `Associations` ( " @@ -534,12 +535,13 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { message = message.substring(guildConfig.getString("Prefix").length()).trim(); if (message.startsWith("temp")) { final String name = message.substring(5); - if (guild.getCategoriesByName("Temp", true).size() > 0) { - guild.getCategoriesByName("Temp", true).get(0).createVoiceChannel(name).queue(v -> { + if (guild.getCategoryById(guildConfig.getString("TempCatID")) != null) { + guild.getCategoryById(guildConfig.getString("TempCatID")).createVoiceChannel(name).queue(v -> { addTemporaryVC(v.getId()); }); } else { - guild.createCategory("Temp").queue(c -> { + guild.createCategory("Temp Channels").queue(c -> { + sql.executeUpdate("UPDATE `Settings` SET `TempCatID` = '" + c.getIdLong() + "' WHERE `GuildID` = " + guild.getId()); c.createVoiceChannel(name).queue(v -> { addTemporaryVC(v.getId()); }); @@ -699,7 +701,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { channel.sendMessage("The maximum length for a channel-description is 1024 characters! Your description was " + message.length() + " characters long.").queue(); } else { sql.executeUpdate("UPDATE `Settings` SET `Descriptions` = '" + message + "' WHERE `GuildID` = " + guild.getId()); - channel.sendMessage("Name for new Text-Channels set to `" + message + "`.").queue(); + channel.sendMessage("Description for new Text-Channels set to `" + message + "`.").queue(); } } } From 10f85b3901e2b0bfd3dce8d5a4ae93ee0e1c4ebd Mon Sep 17 00:00:00 2001 From: Ryeera <79052127+Ryeera@users.noreply.github.com> Date: Fri, 3 Sep 2021 02:03:13 +0200 Subject: [PATCH 6/9] Updated Argus to 1.2.0 * Category for temp-channels now saves as an ID, allows for renaming - Fixed a typo --- Discord - Argus/pom.xml | 2 +- Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Discord - Argus/pom.xml b/Discord - Argus/pom.xml index f795370..de26761 100644 --- a/Discord - Argus/pom.xml +++ b/Discord - Argus/pom.xml @@ -2,7 +2,7 @@ 4.0.0 de.Ryeera Argus - 1.1.0 + 1.2.0 Argus diff --git a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java index 65e67e7..e9d4fb8 100644 --- a/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java +++ b/Discord - Argus/src/main/java/de/Ryeera/Argus/Argus.java @@ -50,7 +50,7 @@ public class Argus extends ListenerAdapter { - private static final String VERSION = "1.1.0"; + private static final String VERSION = "1.2.0"; private static DragoLogger logger; From 9f8cf5ed6894eaf30b2e0ef5721f93b4423d2941 Mon Sep 17 00:00:00 2001 From: Ryeera <79052127+Ryeera@users.noreply.github.com> Date: Fri, 3 Sep 2021 02:05:49 +0200 Subject: [PATCH 7/9] Update Eclipse Settings to use Java 16 --- Discord - Argus/.settings/org.eclipse.jdt.core.prefs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Discord - Argus/.settings/org.eclipse.jdt.core.prefs b/Discord - Argus/.settings/org.eclipse.jdt.core.prefs index 2876057..4881ff3 100644 --- a/Discord - Argus/.settings/org.eclipse.jdt.core.prefs +++ b/Discord - Argus/.settings/org.eclipse.jdt.core.prefs @@ -1,9 +1,9 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=15 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=16 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=15 +org.eclipse.jdt.core.compiler.compliance=16 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -13,4 +13,4 @@ org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=15 +org.eclipse.jdt.core.compiler.source=16 From 4644a4395f8c7e3fc976f282dc2715d3b1f5e27e Mon Sep 17 00:00:00 2001 From: Ryeera Lunala <79052127+Ryeera@users.noreply.github.com> Date: Tue, 19 Oct 2021 18:12:37 +0200 Subject: [PATCH 8/9] Update README.md --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7bfe8b8..5f4ad3c 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,8 @@ Although this feature is not implemented yet, I will be able to move members int **Why does Argus not work with some channels?** If that happens, please join my Discord-Server below, so Ryeera can help you. It shouldn't happen, but if it does, please tell him. +**Can I have my data deleted?** +Of course! Open a new Data Deletion Request by clicking on "Issues" up top! We will try to get to it as quickly as possible and all your data will be deleted completely. + ## Planned Features -- Private Voice-Channels -- Command to make it so a voice-channel doesn't have an associated text-channel anymore / blacklist -- More Options - - Instead of assigning permissions to an existing text-channel, create a new text-channel (more organized for admins) - - Format Logging - - Create Master-text-channel for copying permissions (for example so that mods can always see the text-channels) -- Support for bots like Server Stats that use voice-channels in a way that means that Argus shouldn't create a text-channel for them. +See the Issues-page for planned features and to request more or report bugs! From 410e67ac3d45d7d03a25a7a1eb73f8d3b5df85a8 Mon Sep 17 00:00:00 2001 From: Ryeera Lunala <79052127+Ryeera@users.noreply.github.com> Date: Wed, 20 Oct 2021 16:48:04 +0200 Subject: [PATCH 9/9] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..0228ccd --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: ryeera +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']