├── .gitattributes ├── src └── main │ └── java │ └── me │ └── alexander │ └── discordbot │ ├── SelfBot │ ├── Messages │ │ ├── IMessageSelfBot.java │ │ └── EmbeddedMessageUtil.java │ ├── ICommandSelfBot.java │ ├── SelfBot.java │ └── Utils.java │ └── Main.java ├── .gitignore ├── README.md └── pom.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/SelfBot/Messages/IMessageSelfBot.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot.SelfBot.Messages; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | import de.btobastian.javacord.entities.message.Message; 6 | import me.alexander.discordbot.SelfBot.ICommandSelfBot; 7 | import me.alexander.discordbot.SelfBot.SelfBot; 8 | 9 | public class IMessageSelfBot { 10 | 11 | /** 12 | * The command prefix used to trigger the bot 13 | */ 14 | private final static String commandPrefix = "/"; 15 | 16 | private IMessageSelfBot() {} 17 | 18 | /** 19 | * Executes the message processor 20 | * 21 | * @throws ExecutionException 22 | * @throws InterruptedException 23 | */ 24 | public static void execute(final Message message, final SelfBot bot) 25 | throws InterruptedException, ExecutionException { 26 | // Make sure the message is sent by the correct user 27 | if (message.getAuthor().equals(bot.getAPI().getYourself())) { 28 | // Handle command 29 | if (message.getContent().startsWith(commandPrefix)) { 30 | ICommandSelfBot.doCmd(message.getContent(), message, bot, bot.getAPI().getYourself()); 31 | } 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | # ========================= 15 | # Operating System Files 16 | # ========================= 17 | 18 | # OSX 19 | # ========================= 20 | 21 | .DS_Store 22 | .AppleDouble 23 | .LSOverride 24 | 25 | # Thumbnails 26 | ._* 27 | 28 | # Files that might appear in the root of a volume 29 | .DocumentRevisions-V100 30 | .fseventsd 31 | .Spotlight-V100 32 | .TemporaryItems 33 | .Trashes 34 | .VolumeIcon.icns 35 | 36 | # Directories potentially created on remote AFP share 37 | .AppleDB 38 | .AppleDesktop 39 | Network Trash Folder 40 | Temporary Items 41 | .apdisk 42 | 43 | # Windows 44 | # ========================= 45 | 46 | # Windows image file caches 47 | Thumbs.db 48 | ehthumbs.db 49 | 50 | # Folder config file 51 | Desktop.ini 52 | 53 | # Recycle Bin used on file shares 54 | $RECYCLE.BIN/ 55 | 56 | # Windows Installer files 57 | *.cab 58 | *.msi 59 | *.msm 60 | *.msp 61 | 62 | # Windows shortcuts 63 | *.lnk 64 | /target/ 65 | 66 | # Eclipse 67 | /.classpath 68 | /.project 69 | /.settings/ 70 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/Main.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import me.alexander.discordbot.SelfBot.SelfBot; 7 | 8 | public class Main { 9 | 10 | /** 11 | * The version of this bot 12 | */ 13 | public static final String version = "0.4"; 14 | 15 | /** 16 | * SelfBot instance 17 | */ 18 | private static SelfBot bot; 19 | 20 | /** 21 | * Logger instance 22 | */ 23 | private static Logger logger = LoggerFactory.getLogger(Main.class); 24 | 25 | /** 26 | * Main function, provide your discord account token as a CLI argument 27 | * 28 | * @param args 29 | * @throws InterruptedException 30 | */ 31 | public static void main(final String[] args) throws InterruptedException { 32 | if (args.length == 0) { 33 | Main.logger.error("Please provide your Discord account token as a command line argument."); 34 | return; 35 | } 36 | Main.logger.info("Starting SelfBot version " + version); 37 | Main.bot = new SelfBot(args[0]); 38 | Main.bot.setup(); 39 | } 40 | 41 | /** 42 | * Retrieves the logger 43 | * 44 | * @return Logger 45 | */ 46 | public static Logger getLogger() { 47 | return Main.logger; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiscordSelfBot 2 | A Java Discord selfbot that allows custom commands and rich messages (Embeds) based on [BtoBastian's JavaCord library](https://github.com/BtoBastian/Javacord). 3 | 4 | ### Retrieving your access token 5 | 6 | In your browser or desktop Discord, press `Ctrl-Shift-I` or `⌘-Shift-I` on Mac. Go to the Application section, Click on Storage > LocalStorage > discordapp.com. Find the token row at the bottom, your token will be the value in quotes. 7 | 8 | ⚠ Do not share this token with anyone ⚠ This token provides complete access to your Discord account, never share it! 9 | 10 | ### Installing and running 11 | 12 | First download the source and compile it into a .jar file, set the main class to `me.alexander.discordbot.Main` 13 | 14 | You can also download a precompiled version [here](https://github.com/Moudoux/DiscordSelfBot/releases/tag/v3). 15 | 16 | Now open a command prompt/terminal window and type `java -jar SelfBotv2.jar ` 17 | 18 | ### Commands 19 | 20 | ``` 21 | /shutdown - Will shutdown the bot 22 | /embed - Sends an embedded message 23 | ``` 24 | 25 | ### Embedded message format 26 | 27 | To send an embedded message you type `/embed `, in the message you can set the `title`, `body`, `footer` and an image (jpeg,jpg and png supported). 28 | 29 | To add a title you simply type `****`, to add a footer you type `--<Footer>--` and to add a image you just paste the url. 30 | 31 | An example message might look like this: 32 | 33 | `/embed **This is the title** This is a test of the SelfBot --This is the footer--` 34 | 35 | ![Embedded Message](http://image.prntscr.com/image/673b1abeaee94bdaa108375c8935ecc4.png) 36 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 | <modelVersion>4.0.0</modelVersion> 4 | <groupId>me.alexander.datbot</groupId> 5 | <artifactId>datdiscordbot</artifactId> 6 | <version>0.4.1</version> 7 | <properties> 8 | <maven.compiler.source>1.8</maven.compiler.source> 9 | <maven.compiler.target>1.8</maven.compiler.target> 10 | <discordselfbot.main>me.alexander.discordbot.Main</discordselfbot.main> 11 | </properties> 12 | <repositories> 13 | <repository> 14 | <id>javacord-repo</id> 15 | <url>http://repo.bastian-oppermann.de</url> 16 | </repository> 17 | </repositories> 18 | <dependencies> 19 | <dependency> 20 | <groupId>de.btobastian.javacord</groupId> 21 | <artifactId>javacord</artifactId> 22 | <version>2.0.17</version> 23 | <!-- This will use the shaded javacord which contains all required dependencies --> 24 | <classifier>shaded</classifier> 25 | </dependency> 26 | <dependency> 27 | <groupId>ch.qos.logback</groupId> 28 | <artifactId>logback-classic</artifactId> 29 | <version>1.1.3</version> 30 | </dependency> 31 | </dependencies> 32 | <build> 33 | <plugins> 34 | <plugin> 35 | <groupId>org.apache.maven.plugins</groupId> 36 | <artifactId>maven-shade-plugin</artifactId> 37 | <version>2.3</version> 38 | </plugin> 39 | <plugin> 40 | <groupId>org.apache.maven.plugins</groupId> 41 | <artifactId>maven-dependency-plugin</artifactId> 42 | <version>3.0.0</version> 43 | <executions> 44 | <execution> 45 | <id>copy-dependencies</id> 46 | <phase>prepare-package</phase> 47 | <goals> 48 | <goal>copy-dependencies</goal> 49 | </goals> 50 | <configuration> 51 | <outputDirectory>${project.build.directory}/lib</outputDirectory> 52 | <overWriteReleases>false</overWriteReleases> 53 | <overWriteSnapshots>false</overWriteSnapshots> 54 | <overWriteIfNewer>true</overWriteIfNewer> 55 | </configuration> 56 | </execution> 57 | </executions> 58 | </plugin> 59 | <plugin> 60 | <groupId>org.apache.maven.plugins</groupId> 61 | <artifactId>maven-jar-plugin</artifactId> 62 | <version>3.0.2</version> 63 | <configuration> 64 | <archive> 65 | <manifest> 66 | <addClasspath>true</addClasspath> 67 | <classpathPrefix>lib/</classpathPrefix> 68 | <mainClass>${discordselfbot.main}</mainClass> 69 | </manifest> 70 | </archive> 71 | </configuration> 72 | </plugin> 73 | </plugins> 74 | </build> 75 | </project> 76 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/SelfBot/ICommandSelfBot.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot.SelfBot; 2 | 3 | import static me.alexander.discordbot.SelfBot.Utils.deleteMessageLater; 4 | 5 | import java.awt.Color; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | import de.btobastian.javacord.entities.User; 10 | import de.btobastian.javacord.entities.message.Message; 11 | import de.btobastian.javacord.entities.message.embed.EmbedBuilder; 12 | import de.btobastian.javacord.entities.permissions.PermissionType; 13 | import me.alexander.discordbot.SelfBot.Messages.EmbeddedMessageUtil; 14 | 15 | /** 16 | * Takes input and interprets it 17 | * 18 | */ 19 | public class ICommandSelfBot { 20 | 21 | private ICommandSelfBot() {} 22 | 23 | /** 24 | * Executes the command processor 25 | * 26 | * @param in 27 | * @param message 28 | * @param bot 29 | * @param u 30 | * @throws ExecutionException 31 | * @throws InterruptedException 32 | */ 33 | public static void doCmd(final String in, final Message message, final SelfBot bot, final User u) 34 | throws InterruptedException, ExecutionException { 35 | final String cmd = in.contains(" ") ? in.split(" ")[0] : in; 36 | final String args = in.contains(" ") ? in.replace(in.split(" ")[0] + " ", "") : ""; 37 | switch (cmd.toLowerCase()) { 38 | case "/shutdown": 39 | message.delete().get(); 40 | bot.disconnect(); 41 | break; 42 | case "/ban": 43 | message.delete(); 44 | if (args.equals("")) { 45 | EmbedBuilder emb = EmbeddedMessageUtil.getEmbeddedMessage("Usage Warning", "Invalid argument", "", "", 46 | "", Color.RED); 47 | deleteMessageLater(message.reply("", emb), 2, TimeUnit.SECONDS); 48 | break; 49 | } 50 | User user = Utils.getUser(args, message.getChannelReceiver().getServer(), bot); 51 | if (user == null) { 52 | EmbedBuilder emb = EmbeddedMessageUtil.getEmbeddedMessage("Usage Warning", "User not found", "", "", "", 53 | Color.RED); 54 | deleteMessageLater(message.reply("", emb), 2, TimeUnit.SECONDS); 55 | break; 56 | } 57 | // Make sure we have permission to ban in this discord server 58 | if (!Utils.hasPermission(bot.getAPI().getYourself(), message.getChannelReceiver().getServer(), 59 | PermissionType.BAN_MEMBERS)) { 60 | EmbedBuilder emb = EmbeddedMessageUtil.getEmbeddedMessage("Usage Warning", 61 | "You are not permitted to ban others!", "", "", "", Color.RED); 62 | deleteMessageLater(message.reply("", emb), 2, TimeUnit.SECONDS); 63 | break; 64 | } 65 | // All checks passed, let's ban the user 66 | message.getChannelReceiver().getServer().banUser(user).get(); 67 | EmbedBuilder emb = EmbeddedMessageUtil.getEmbeddedMessage( 68 | ":hammer: **Banned:** " + user.getMentionTag() + " (" + user.getId() + ")", "", "", "", "", 69 | Color.YELLOW); 70 | message.reply("", emb); 71 | break; 72 | case "/user": 73 | case "/embed": 74 | message.delete(); 75 | EmbeddedMessageUtil.embed(message, bot); 76 | break; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/SelfBot/SelfBot.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot.SelfBot; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.google.common.util.concurrent.FutureCallback; 9 | 10 | import de.btobastian.javacord.DiscordAPI; 11 | import de.btobastian.javacord.Javacord; 12 | import de.btobastian.javacord.entities.message.Message; 13 | import de.btobastian.javacord.listener.message.MessageCreateListener; 14 | import de.btobastian.javacord.listener.message.MessageEditListener; 15 | import me.alexander.discordbot.SelfBot.Messages.IMessageSelfBot; 16 | 17 | /** 18 | * The SelfBot bot 19 | * 20 | */ 21 | public class SelfBot { 22 | 23 | /** 24 | * The current logger for this SelfBot 25 | */ 26 | private final Logger logger; 27 | 28 | /** 29 | * The current SelfBot instance 30 | */ 31 | private final SelfBot bot = this; 32 | 33 | /** 34 | * Token used 35 | */ 36 | private final String token; 37 | 38 | /** 39 | * Call System.exit(0); on disconnect. Default: true 40 | */ 41 | private final boolean exitOnDisconnect; 42 | 43 | /** 44 | * The DiscordAPI instance 45 | */ 46 | private DiscordAPI api = null; 47 | 48 | /** 49 | * SelfBot instance, provide the token to login 50 | * 51 | * @param token 52 | */ 53 | public SelfBot(final String token) { 54 | this(token, true); 55 | } 56 | 57 | /** 58 | * SelfBot instance, provide the token to login and whether or not to exit 59 | * on bot disconnect 60 | * 61 | * @param token 62 | * @param exitOnDisconnect 63 | */ 64 | public SelfBot(final String token, final boolean exitOnDisconnect) { 65 | this.token = token; 66 | this.exitOnDisconnect = exitOnDisconnect; 67 | this.logger = LoggerFactory.getLogger(SelfBot.class); 68 | } 69 | 70 | /** 71 | * Disconnects the bot and will shutdown the bot 72 | * 73 | */ 74 | public void disconnect() { 75 | api.setAutoReconnect(false); 76 | api.disconnect(); 77 | if (exitOnDisconnect) { 78 | System.exit(0); 79 | } 80 | } 81 | 82 | /** 83 | * Get's the current DiscordAPI instance 84 | * 85 | * @return DiscordAPI 86 | */ 87 | public DiscordAPI getAPI() { 88 | return api; 89 | } 90 | 91 | /** 92 | * Starts the bot, sets up all the hooks 93 | */ 94 | public void setup() { 95 | // Get the API, false = This is not a bot account 96 | api = Javacord.getApi(token, false); 97 | api.connect(new FutureCallback<DiscordAPI>() { 98 | @Override 99 | public void onSuccess(final DiscordAPI api) { 100 | api.registerListener(new MessageCreateListener() { 101 | @Override 102 | public void onMessageCreate(final DiscordAPI api, final Message message) { 103 | api.getThreadPool().getExecutorService().submit(() -> { 104 | try { 105 | IMessageSelfBot.execute(message, bot); 106 | } catch (InterruptedException | ExecutionException e) { 107 | logger.debug(e.getMessage()); 108 | } 109 | }); 110 | } 111 | }); 112 | api.registerListener(new MessageEditListener() { 113 | @Override 114 | public void onMessageEdit(final DiscordAPI api, final Message message, final String oldContent) { 115 | api.getThreadPool().getExecutorService().submit(() -> { 116 | try { 117 | IMessageSelfBot.execute(message, bot); 118 | } catch (InterruptedException | ExecutionException e) { 119 | logger.debug(e.getMessage()); 120 | } 121 | }); 122 | } 123 | }); 124 | api.setAutoReconnect(true); 125 | } 126 | 127 | @Override 128 | /** 129 | * Called when the bot is not able to connect to Discord 130 | */ 131 | public void onFailure(final Throwable t) { 132 | logger.debug("Failed to connect"); 133 | t.printStackTrace(); 134 | } 135 | }); 136 | } 137 | 138 | /** 139 | * Returns the logger for this SelfBot 140 | * 141 | * @return logger 142 | */ 143 | public Logger getLogger() { 144 | return logger; 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/SelfBot/Messages/EmbeddedMessageUtil.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot.SelfBot.Messages; 2 | 3 | import static me.alexander.discordbot.SelfBot.Utils.extractUrls; 4 | import static me.alexander.discordbot.SelfBot.Utils.getUser; 5 | 6 | import java.awt.Color; 7 | import java.security.SecureRandom; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Calendar; 10 | import java.util.concurrent.Future; 11 | 12 | import de.btobastian.javacord.entities.Channel; 13 | import de.btobastian.javacord.entities.User; 14 | import de.btobastian.javacord.entities.message.Message; 15 | import de.btobastian.javacord.entities.message.embed.EmbedBuilder; 16 | import me.alexander.discordbot.SelfBot.SelfBot; 17 | 18 | public class EmbeddedMessageUtil { 19 | 20 | private EmbeddedMessageUtil() {} 21 | 22 | /** 23 | * Random to get random RGB values for the color 24 | */ 25 | private static SecureRandom rand = new SecureRandom(); 26 | 27 | /** 28 | * Builds an embedded message 29 | * 30 | * @param title 31 | * @param description 32 | * @param footer 33 | * @param image 34 | * @param thumbnail 35 | * @param color 36 | * @return EmbedBuilder 37 | */ 38 | public static EmbedBuilder getEmbeddedMessage(final String title, final String description, final String footer, 39 | final String image, final String thumbnail, final Color color) { 40 | final EmbedBuilder emb = new EmbedBuilder(); 41 | emb.setTitle(title); 42 | emb.setDescription(description); 43 | emb.setFooter(footer); 44 | emb.setImage(image); 45 | emb.setThumbnail(thumbnail); 46 | emb.setColor(color); 47 | return emb; 48 | } 49 | 50 | /** 51 | * Sends an embedded message about a given user 52 | * 53 | * @param m 54 | * @param bot 55 | */ 56 | public static Future<Message> userInfo(final Message m, final SelfBot bot) { 57 | m.delete(); 58 | 59 | User user = getUser(m.getContent().replace("/user ", ""), bot); 60 | if (user == null) { 61 | user = bot.getAPI().getYourself(); 62 | } 63 | 64 | final EmbedBuilder emb = new EmbedBuilder(); 65 | 66 | emb.addField("Username", user.getName(), true); 67 | emb.addField("User ID", user.getId(), true); 68 | emb.addField("Mention Tag", user.getMentionTag(), true); 69 | emb.addField("Avatar", user.getAvatarUrl().toString(), true); 70 | emb.addField("Status", user.getStatus().name(), true); 71 | 72 | emb.setFooter( 73 | m.getAuthor().getName() + "'s Bot | Message sent " 74 | + new SimpleDateFormat("MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()), 75 | "https://avatars1.githubusercontent.com/u/6422482?v=3&s=400"); 76 | 77 | emb.setTitle("Profile of " + user.getName() + ":"); 78 | emb.setColor(Color.red); 79 | emb.setThumbnail(user.getAvatarUrl().toString()); 80 | 81 | return m.reply("", emb); 82 | } 83 | 84 | /** 85 | * The /embed message interpreter 86 | * 87 | * @param message 88 | * @param bot 89 | */ 90 | public static Future<Message> embed(final Message message, final SelfBot bot) { 91 | if (message.getContent().startsWith("/user")) { 92 | return EmbeddedMessageUtil.userInfo(message, bot); 93 | } 94 | if (!message.getContent().startsWith("/embed")) { 95 | return null; 96 | } 97 | 98 | String msg = message.getContent().replace("/embed ", ""); 99 | 100 | return message.reply("", generateEmbed(msg, bot)); 101 | } 102 | 103 | /** 104 | * The /embed message interpreter 105 | * 106 | * @param msg 107 | * @param bot 108 | * @param channel 109 | * @return 110 | */ 111 | public static Future<Message> embed(String msg, final SelfBot bot, final Channel channel) { 112 | return channel.sendMessage("", generateEmbed(msg, bot)); 113 | } 114 | 115 | public static EmbedBuilder generateEmbed(String msg, final SelfBot bot) { 116 | try { 117 | final EmbedBuilder emb = new EmbedBuilder(); 118 | emb.setColor(new Color(EmbeddedMessageUtil.rand.nextFloat(), EmbeddedMessageUtil.rand.nextFloat(), 119 | EmbeddedMessageUtil.rand.nextFloat()).brighter()); 120 | 121 | emb.setFooter( 122 | bot.getAPI().getYourself().getName() + "'s Bot | Message sent " 123 | + new SimpleDateFormat("MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()), 124 | "https://avatars1.githubusercontent.com/u/6422482?v=3&s=400"); 125 | 126 | for (final String url : extractUrls(msg)) { 127 | if (url.endsWith(".png") || url.endsWith(".jpeg") || url.endsWith(".jpg")) { 128 | emb.setImage(url); 129 | msg = msg.replace(url, ""); 130 | break; 131 | } 132 | } 133 | 134 | if (msg.contains("**")) { 135 | final String title = msg.split("\\*\\*")[1].split("\\*\\*")[0]; 136 | msg = msg.replace("**" + title + "**", ""); 137 | emb.setTitle(title); 138 | } else { 139 | emb.setAuthor(bot.getAPI().getYourself().getName() + " says:"); 140 | } 141 | 142 | if (msg.contains("--")) { 143 | final String footer = msg.split("\\-\\-")[1].split("\\-\\-")[0]; 144 | msg = msg.replace("--" + footer + "--", ""); 145 | emb.setFooter(footer); 146 | } 147 | 148 | emb.setDescription(msg); 149 | return emb; 150 | } catch (final Exception ex) { 151 | ex.printStackTrace(); 152 | return null; 153 | } 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/me/alexander/discordbot/SelfBot/Utils.java: -------------------------------------------------------------------------------- 1 | package me.alexander.discordbot.SelfBot; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.ExecutionException; 6 | import java.util.concurrent.Executors; 7 | import java.util.concurrent.Future; 8 | import java.util.concurrent.ScheduledExecutorService; 9 | import java.util.concurrent.TimeUnit; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import de.btobastian.javacord.entities.Channel; 17 | import de.btobastian.javacord.entities.Server; 18 | import de.btobastian.javacord.entities.User; 19 | import de.btobastian.javacord.entities.message.Message; 20 | import de.btobastian.javacord.entities.permissions.PermissionState; 21 | import de.btobastian.javacord.entities.permissions.PermissionType; 22 | import de.btobastian.javacord.entities.permissions.Permissions; 23 | import de.btobastian.javacord.entities.permissions.Role; 24 | 25 | /** 26 | * 27 | * A collection of functions used internally by the bot 28 | * 29 | * @author Deftware 30 | * 31 | */ 32 | public class Utils { 33 | 34 | private static final Logger logger = LoggerFactory.getLogger(Utils.class); 35 | 36 | /** 37 | * Schedule executor service (used for self-delete) 38 | */ 39 | private static final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1); 40 | 41 | private Utils() {} 42 | 43 | /** 44 | * Returns a user by a mention tag, id or name 45 | * 46 | * @param id 47 | * @param server 48 | * @return User 49 | * @throws ExecutionException 50 | * @throws InterruptedException 51 | */ 52 | public static User getUser(String id, Server server, SelfBot bot) throws InterruptedException, ExecutionException { 53 | User user = bot.getAPI().getUserById(id).get(); 54 | if (user == null) { 55 | // Not a user id, or invalid user id 56 | for (User u : server.getMembers()) { 57 | if (u.getMentionTag().equals(id)) { 58 | user = u; 59 | break; 60 | } else if (u.getName().equals(id)) { 61 | user = u; 62 | break; 63 | } else if (u.getNickname(server).equals(id)) { 64 | user = u; 65 | break; 66 | } else if (u.getId().equals(id)) { 67 | user = u; 68 | break; 69 | } 70 | } 71 | } 72 | return user; 73 | } 74 | 75 | /** 76 | * Checks if a given user has a permission 77 | * 78 | * @param user 79 | * @param permission 80 | * 81 | * @return Boolean 82 | */ 83 | public static boolean hasPermission(User user, Server server, PermissionType permission) { 84 | for (Role r : user.getRoles(server)) { 85 | Permissions p = r.getPermissions(); 86 | if (p.getState(permission).equals(PermissionState.ALLOWED)) { 87 | return true; 88 | } 89 | } 90 | return false; 91 | } 92 | 93 | /** 94 | * Returns an array with all URLs in a given string 95 | * 96 | * @param text 97 | * @return List<String> 98 | */ 99 | public static List<String> extractUrls(final String text) { 100 | final List<String> containedUrls = new ArrayList<String>(); 101 | final String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)"; 102 | final Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE); 103 | final Matcher urlMatcher = pattern.matcher(text); 104 | while (urlMatcher.find()) { 105 | containedUrls.add(text.substring(urlMatcher.start(0), urlMatcher.end(0))); 106 | } 107 | return containedUrls; 108 | } 109 | 110 | /** 111 | * Get's a user from their id or mentiontag 112 | * 113 | * @param tag 114 | * @param bot 115 | * @return User 116 | */ 117 | public static User getUser(final String tag, final SelfBot bot) { 118 | for (final Server c : bot.getAPI().getServers()) { 119 | for (final User u : c.getMembers()) { 120 | if (u.getMentionTag().equals(tag) || u.getId().equals(tag) || u.getName().startsWith(tag)) { 121 | return u; 122 | } 123 | } 124 | } 125 | return null; 126 | } 127 | 128 | /** 129 | * 130 | * Sends a message in a given channel and automatically deletes the message 131 | * after a set time 132 | * 133 | * @param message 134 | * @param time 135 | * @param channel 136 | * @throws ExecutionException 137 | * @throws InterruptedException 138 | */ 139 | public static void sendSelfDeletingMessage(String message, int time, Channel channel) 140 | throws InterruptedException, ExecutionException { 141 | final Future<Message> messageObj = channel.sendMessage(message); 142 | deleteMessageLater(messageObj, time, TimeUnit.SECONDS); 143 | } 144 | 145 | /** 146 | * Delete a message after a set amount of time 147 | * 148 | * @param message 149 | * @param time 150 | * @param unit 151 | */ 152 | public static void deleteMessageLater(Future<Message> message, int time, TimeUnit unit) { 153 | exec.schedule(() -> { 154 | try { 155 | message.get().delete(); 156 | } catch (InterruptedException | ExecutionException e) { 157 | logger.debug(e.getMessage()); 158 | } 159 | }, time, unit); 160 | } 161 | 162 | /** 163 | * Delete a message after a set amount of time 164 | * 165 | * @param message 166 | * @param time 167 | * @param unit 168 | */ 169 | public static void deleteMessageLater(Message message, int time, TimeUnit unit) { 170 | exec.schedule(() -> { 171 | message.delete(); 172 | }, time, unit); 173 | } 174 | 175 | } 176 | --------------------------------------------------------------------------------