package com.fpghoti.biscuit.guild; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Properties; import java.util.Timer; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.fpghoti.biscuit.Main; import com.fpghoti.biscuit.PluginCore; import com.fpghoti.biscuit.audio.AudioScheduler; import com.fpghoti.biscuit.config.BiscuitConfig; import com.fpghoti.biscuit.config.BiscuitProperties; import com.fpghoti.biscuit.logging.BColor; import com.fpghoti.biscuit.logging.BiscuitLogger; import com.fpghoti.biscuit.rest.MessageText; import com.fpghoti.biscuit.rss.YTFeed; import com.fpghoti.biscuit.rss.YTFeedConfig; import com.fpghoti.biscuit.timer.BiscuitTimer; import com.fpghoti.biscuit.timer.task.ChatCountTimer; import com.fpghoti.biscuit.timer.task.DecrementTimer; import com.fpghoti.biscuit.timer.task.SoftMuteTimer; import com.fpghoti.biscuit.user.CaptchaUser; import com.fpghoti.biscuit.user.PreUser; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Invite; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.User; public class BiscuitGuild { public static BiscuitGuild getBiscuitGuild(Guild g) { for(BiscuitGuild b : Main.getBiscuits()) { if(b.getGuild().getId().equals(g.getId())) { return b; } } return null; } public static BiscuitGuild getBiscuitGuild(String guildcode) { for(BiscuitGuild b : Main.getBiscuits()) { if(b.getProperties().getGuildCode().equalsIgnoreCase(guildcode)) { return b; } } return null; } public static ArrayList getPreUsers(User u) { ArrayList pres = new ArrayList(); for(Guild g : Main.getJDA().getGuilds()) { if(g.isMember(u)){ BiscuitGuild b = getBiscuitGuild(g); if(b.preUserExists(u)) { pres.add(b.getPreUser(u)); } } } return pres; } public static BiscuitGuild loadGuild(Guild g) { BiscuitGuild biscuit = new BiscuitGuild(Main.getJDA(), g, Main.getLogger()); biscuit.addTimer(new ChatCountTimer(biscuit)); biscuit.addTimer(new SoftMuteTimer(biscuit)); biscuit.addTimer(new DecrementTimer(biscuit)); biscuit.loadTimers(); Main.registerBiscuit(biscuit); return biscuit; } private boolean isMain; private JDA jda; private BiscuitLogger logger; private Timer timer; private List timers; private File captchaDir; private File ytFeedDir; //private Cage cage; private Guild guild; private HashMap inviteUses; private HashMap ytfeeds; private BiscuitConfig config; private BiscuitProperties properties; private GuildMessageStore messageStore; private AudioPlayer player; private AudioScheduler scheduler; private CopyOnWriteArrayList users = new CopyOnWriteArrayList(); private HashMap rolequeue; public BiscuitGuild(JDA jda, Guild guild, BiscuitLogger log) { this.jda = jda; this.guild = guild; this.logger = log; this.isMain = guild == null; this.messageStore = new GuildMessageStore(this); this.config = new BiscuitConfig(this); config.generateConfig(); this.properties = new BiscuitProperties(this); this.rolequeue = new HashMap(); this.player = Main.getPlayerManager().createPlayer(); this.ytfeeds = new HashMap(); scheduler = new AudioScheduler(this); player.addListener(scheduler); timer = new Timer(); timers = new ArrayList(); if(!Main.isPlugin) { captchaDir = new File("captcha"); captchaDir.mkdir(); if(guild != null) { File f = new File("ytchannels"); f.mkdir(); ytFeedDir = new File(f, guild.getId()); ytFeedDir.mkdir(); } }else { captchaDir = new File(PluginCore.plugin.getDataFolder(), "captcha"); captchaDir.mkdir(); if(guild != null) { ytFeedDir = new File(PluginCore.plugin.getDataFolder(), "ytchannels\\" + guild.getId()); ytFeedDir.mkdirs(); } } if(isMain) { wipeCaptchaDir(); } if(!isMain) { loadPreUsers(); inviteUses = new HashMap(); if(canManageServer() && properties.checkJoinInvite()) { guild.retrieveInvites().queue((invs) -> { indexInvites(invs); }); } } if(guild != null) { loadYoutubeFeeds(); Runnable post = () -> { try { log("Updating Youtube feeds..."); postYoutubeFeeds(); } catch (IOException e) { e.printStackTrace(); } }; ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(post, 0, 1, TimeUnit.MINUTES); } } public BiscuitConfig getConfig() { return config; } public BiscuitProperties getProperties() { return properties; } public GuildMessageStore getMessageStore() { return messageStore; } public Guild getGuild() { return guild; } public boolean canManageServer() { return guild.getSelfMember().hasPermission(Permission.MANAGE_SERVER); } public AudioPlayer getAudioPlayer() { return player; } public AudioScheduler getAudioScheduler() { return scheduler; } public YTFeedConfig loadYouTubeFeedConfig(String alias) { alias = alias.toLowerCase(); String channelID = "null"; String youTubeChannelURL = "null"; String message = "null"; String lastVideo = "null"; Properties prop = new Properties(); InputStream input = null; File config = new File(ytFeedDir, alias); if(!config.exists()) { logger.error("Could not locate YouTube feed config."); return null; } try { input = new FileInputStream(config); prop.load(input); channelID = prop.getProperty("TextChannelID"); youTubeChannelURL = prop.getProperty("YouTubeChannelURL"); message = prop.getProperty("Message"); lastVideo = prop.getProperty("LastVideo"); } catch (IOException ex) { ex.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } TextChannel textChannel = jda.getTextChannelById(channelID); if(textChannel == null) { logger.error("Error retrieving Text Channel from YouTube feed file."); return null; } YTFeed feed = new YTFeed(alias, textChannel, youTubeChannelURL, message); feed.setLastVideo(lastVideo); return new YTFeedConfig(this, feed); } public void loadYoutubeFeeds() { ytfeeds.clear(); File[] files = ytFeedDir.listFiles(); for(File f : files) { String alias = f.getName().toLowerCase(); ytfeeds.put(alias, loadYouTubeFeedConfig(alias)); } } public boolean addYoutubeFeed(String alias, TextChannel channel, String channelURL, String message) { alias = alias.toLowerCase(); if(guild == null || ytfeeds.containsKey(alias)) { return false; } YTFeed feed = new YTFeed(alias, channel, channelURL, message); //Generate a file for the feed new YTFeedConfig(this, feed); //Loads all feeds from files into hash map loadYoutubeFeeds(); return true; } public void postYoutubeFeeds() throws IOException { for(String s : ytfeeds.keySet()) { YTFeedConfig config = ytfeeds.get(s); YTFeed feed = config.getFeed(); feed.post(); config.setLastPosted(feed.getLastVideo()); } } public File getYTFeedDir() { return ytFeedDir; } public void log(String message) { if(properties == null) { logger.info(message); return; } logger.info("[" + BColor.CYAN + properties.getGuildCode().toUpperCase() + BColor.RESET + "]: " + message); } public void warn(String message) { if(properties == null) { logger.warn(message); return; } logger.warn("[" + properties.getGuildCode().toUpperCase() + "]: " + message); } public void error(String message) { if(properties == null) { logger.error(message); return; } logger.error("[" + properties.getGuildCode().toUpperCase() + "]: " + message); } public JDA getJDA() { return jda; } public void say(TextChannel channel, String message) { MessageText.send(channel, message); } public void loadTimers() { timer.cancel(); timer = new Timer(); for(BiscuitTimer t : timers) { timer.schedule(t,t.getDelay(), t.getPeriod()); } } public void addTimer(BiscuitTimer bt) { timers.add(bt); } public void removeTimer(BiscuitTimer bt) { timers.remove(bt); } public void wipeCaptchaDir() { log("Wiping captcha files..."); boolean good = true; File[] files = captchaDir.listFiles(); for (File file : files){ if (!file.delete()){ good = false; error("Could not remove captcha file: " + file); } } if(good) { log("All captcha files successfully removed!"); }else { error("Some captcha file(s) could not be removed!"); } } public ArrayList getCaptchaLogChannels() { ArrayList ch = new ArrayList(); for(TextChannel t : guild.getTextChannels()) { if(t.getName().equalsIgnoreCase(properties.getEventLogChannel())) { ch.add(t); } } return ch; } public void eventLog(String msg) { if(properties.logEvents()) { for(TextChannel t : getCaptchaLogChannels()) { MessageText.send(t, msg); } } } public Role getDefaultRole() { for(Role r : guild.getRoles()) { if(r.getName().toLowerCase().contains(properties.getDefaultRole().toLowerCase())) { return r; } } return null; } public Role getCaptchaRewardRole() { for(Role r : guild.getRoles()) { if(r.getName().toLowerCase().contains(properties.getCaptchaReward().toLowerCase())) { return r; } } return null; } private void loadPreUsers() { if(!properties.captchaEnabled()) { return; } for(Member m : guild.getMembers()) { User u = m.getUser(); if(!preUserExists(u)) { if(m.getRoles().size() == 1) { for(Role role : m.getRoles()){ if(role.getName().equalsIgnoreCase(properties.getDefaultRole())){ log(BColor.MAGENTA_BOLD + "Adding pre-join check for user " + u.getName() + " (" + u.getAsMention() + ")..."); users.add(PreUser.getPreUser(CaptchaUser.getCaptchaUser(u), this)); } } } } } } private void indexInvites(List invs) { for(Invite i : invs) { String code = i.getCode(); int uses = i.getUses(); inviteUses.put(code, uses); } } public HashMap getInviteUses(){ return inviteUses; } public void setInviteUses(HashMap c) { inviteUses = c; } public void clearInviteUses() { inviteUses.clear(); } public void addPreUser(PreUser user) { if(!users.contains(user)) { users.add(user); }else { error("CAPTCHA ERROR: Tried to add PreUser when one already exists"); } } public void removePreUser(PreUser user) { ArrayList temp = new ArrayList(users); for(PreUser u : temp) { if(u.getUser().getId().equals(user.getUser().getId())) { user.setDone(); users.remove(u); } } } public CopyOnWriteArrayList getPreUsers(){ return users; } public PreUser getPreUser(User user) { for(PreUser u : users) { if(u.getUser().getId().equals(user.getId())) { return u; } } return null; } public boolean preUserExists(User user) { return getPreUser(user) != null; } public File getConfigDir() { boolean isMain = guild == null; if(isMain) { if(Main.isPlugin) { PluginCore.plugin.getDataFolder().mkdir(); return PluginCore.plugin.getDataFolder(); }else { return new File("").getAbsoluteFile(); } }else { File dir; if(!Main.isPlugin) { dir = new File("guilds"); }else { dir = new File(PluginCore.plugin.getDataFolder(), "guilds"); } dir.mkdir(); return dir; } } public HashMap getRoleQueue() { return rolequeue; } public void remove() { log("Removing guild biscuit..."); for(BiscuitTimer t : timers) { t.cancel(); } for(PreUser p : users) { p.remove(); } Main.unregisterBiscuit(this); } }