diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3833ff5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +.* +!/.gitignore +out/ +downloads/ +databases/ +credentials/ +configs/ +build/ +gradlew +gradlew.bat +bobot.log diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..52faf03 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.vegazsdev.bobobot.Main + diff --git a/README.md b/README.md new file mode 100644 index 0000000..fb32414 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# Bo³+t Bot + +Just a other Telegram Bot made using [TelegramBots](https://github.com/rubenlagus/TelegramBots) Java Library + +### What are the Current Supported Commands? + +Default Commands: + + - ChangeHotkey: Changes hotkey on current chat (!chkey) + - ChangeLang: Change language on current chat (!chlang) + - ListAllCommands: Show all commands avaiable (!comm) + - About: Shows a About info (!about) + +Other Commands: + + - Hello: Says a Hello! (!hello) + - Chat2Shell: Run shell commands on host computer via chat (!shell) + - SetupGDrive: Setup your Google Drive Account to send files (!setupgdrive) + - Download2GDrive: Download any directlink and send to your Google Drive (!d2gdrive) + - ErfanGSIs: Can port GSIs using [ErfanGSIs Tool](https://github.com/erfanoabdi/ErfanGSIs) (!jurl2gsi) + +*More commands will be added in future, any suggestion or contributions are welcome :)* + +### How to setup this bot? + +Ill always offer a jar file of this bot on GitHub Releases, so, if you want to use this, without any changes, just using your bot "credentials" and other things, yeap, you can! + +1. Get this bot (You can download the on Releases tab or Build it by yourself) + +2. Run jar file by +``` +java -jar Bobobot.jar +``` + +_First time you will get a error, because your bot token and bot username are not set_ + +3. Open config.prop (inside configs folder), and fit with your information, like that: + +``` +#BoboBot config file +#Wed Oct 30 15:17:09 BRT 2019 +bot-token=Put your Telegram Bot Token here +bot-username=Put your Telegram Bot Username here +bot-master=You are the master of this bot, put your Telegram ID here +``` + +4. Run again and voila! + +### Some good information + +**! is ALWAYS the DEFAULT HOTKEY** (You can change this hotkey using !chkey) + +**EN is ALWAYS the DEFAULT LANGUAGE** (You can change this language using !chlang) + +To use anything that send files to Google Drive (like !jurl2gsi or !d2gdrive), YOU NEED TO SETUP YOUR ACCOUNT USING !setupgdrive + +Strings by now are not "fully translatable", ill try to do something good in future + +### How to build? + +I Wrote this bot using IntelliJ IDEA, so, just git clone that repo and open this project on IDEA, and well, edit haha, good luck :) + +Also, the META-INF folder is included on root of this project (may be useful while you creating artefact) + +### How to create a new command? + +This bot tries to be most modular as possible, so, we use Reflection on Main class to "track" for all classes inside Command package, so, open Hello.java, see how it works and make a other class (inside Commands package), extends Command and start your new command :) + +### About + +This is just mine "personal" bot for telegram haha + +### Credits and Libraries + +[TelegramBots (by rubenlagus)](https://github.com/rubenlagus/TelegramBots) + +[Apache Commons](https://commons.apache.org/) + +[Apache Log4j 2 (API/Core)](https://logging.apache.org/log4j/) + +[Google API Client](https://developers.google.com/api-client-library) + +[Google OAuth Client](https://developers.google.com/api-client-library/java/google-oauth-java-client) + +[Google Drive API](https://developers.google.com/drive) + +[Google Guava](https://github.com/google/guava) + +[SQLite JDBC Driver (by xerial)](https://github.com/xerial/sqlite-jdbc) + +### Also: + +[Java Quickstart](https://developers.google.com/drive/api/v3/quickstart/java) + +[Manipulating files.. on Google Drive using Java by o7planning](https://o7planning.org/en/11889/manipulating-files-and-folders-on-google-drive-using-java) diff --git a/build.gradle b/build.gradle new file mode 100755 index 0000000..d11c1c5 --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' +} + +group 'com.vegazsdev.bobobot' +version '1' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + compile group: 'org.telegram', name: 'telegrambots', version: '4.4.0.1' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0' + compile group: 'com.google.api-client', name: 'google-api-client', version: '1.30.5' + compile group: 'com.google.oauth-client', name: 'google-oauth-client-jetty', version: '1.30.4' + compile group: 'com.google.apis', name: 'google-api-services-drive', version: 'v3-rev173-1.25.0' + compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.12.1' + compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.1' + compile group: 'com.google.guava', name: 'guava', version: '11.0.2' + compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.28.0' + compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100755 index 0000000..87b738c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 0000000..f943ce2 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Oct 30 03:23:02 BRT 2019 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle new file mode 100755 index 0000000..50c2fef --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'BoboBot' + diff --git a/src/META-INF/ECLIPSEF.RSA b/src/META-INF/ECLIPSEF.RSA new file mode 100644 index 0000000..e69de29 diff --git a/src/META-INF/ECLIPSEF.SF b/src/META-INF/ECLIPSEF.SF new file mode 100644 index 0000000..e69de29 diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..52faf03 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.vegazsdev.bobobot.Main + diff --git a/src/main/java/com/vegazsdev/bobobot/Main.java b/src/main/java/com/vegazsdev/bobobot/Main.java new file mode 100755 index 0000000..9297a5b --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/Main.java @@ -0,0 +1,104 @@ +package com.vegazsdev.bobobot; + +import com.google.common.reflect.ClassPath; +import com.vegazsdev.bobobot.core.Bot; +import com.vegazsdev.bobobot.db.DbThings; +import com.vegazsdev.bobobot.utils.Config; +import com.vegazsdev.bobobot.utils.FileTools; +import com.vegazsdev.bobobot.utils.XMLs; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.telegram.telegrambots.ApiContextInitializer; +import org.telegram.telegrambots.meta.TelegramBotsApi; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Objects; + +public class Main { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(Main.class); + + public static String DEF_CORE_STRINGS_XML = "core-strings.xml"; + + public static void main(String[] args) { + + LOGGER.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "bot_init")); + + // detect config file + + if (!new FileTools().checkFileExistsCurPath("configs/" + XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file"))) { + LOGGER.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_not_found")); + new Config().createDefConfig(); + LOGGER.warn(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_info")); + System.exit(0); + } + + // initialize all commands inside commands package + + ArrayList commandClasses = new ArrayList<>(); + + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + + try { + for (final ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) { + if (info.getName().startsWith("com.vegazsdev.bobobot.commands")) { + final Class clazz = info.load(); + try { + Object instance = ((Class) clazz).getDeclaredConstructor().newInstance(); + Method method = ((Class) clazz).getSuperclass().getDeclaredMethod("getAlias"); + method.invoke(instance); + commandClasses.add(clazz); + LOGGER.info(Objects.requireNonNull( + XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "cc_init_cmd")) + .replace("%1", clazz.getSimpleName())); + } catch (Exception e) { + // by now, ignoring exceptions here + // LOGGER.error(e.getMessage(), e); + } + } + } + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + + // create a bot object + + if ((Config.getDefConfig("bot-token") != null && Objects.requireNonNull(Config.getDefConfig("bot-token")).contains(" ")) + || (Config.getDefConfig("bot-username") != null && Objects.requireNonNull(Config.getDefConfig("bot-username")).contains(" "))) { + LOGGER.warn(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_info")); + System.exit(0); + } + + Bot bot = + new Bot( + Config.getDefConfig("bot-token"), + Config.getDefConfig("bot-username")); + + // database + // create a new database if current one doesn't exists + + if (!new FileTools().checkFileExistsCurPath("databases/prefs.db")) { + DbThings.createNewDatabase("prefs.db"); + DbThings.createTable("prefs.db", + "CREATE TABLE IF NOT EXISTS chat_prefs (" + + "group_id real UNIQUE PRIMARY KEY," + + "hotkey text DEFAULT '!'," + + "lang text DEFAULT 'strings-en.xml'" + + ");"); + } + + ApiContextInitializer.init(); + TelegramBotsApi botsApi = new TelegramBotsApi(); + + try { + botsApi.registerBot(new TelegramBot(bot, commandClasses)); + LOGGER.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "bot_started")); + } catch (Exception e) { + LOGGER.error(e.toString(), e); + } + + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/TelegramBot.java b/src/main/java/com/vegazsdev/bobobot/TelegramBot.java new file mode 100755 index 0000000..544aed2 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/TelegramBot.java @@ -0,0 +1,190 @@ +package com.vegazsdev.bobobot; + +import com.vegazsdev.bobobot.core.Bot; +import com.vegazsdev.bobobot.core.CommandWithClass; +import com.vegazsdev.bobobot.db.DbThings; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.XMLs; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.telegram.telegrambots.bots.TelegramLongPollingBot; +import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatMember; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText; +import org.telegram.telegrambots.meta.api.objects.ChatMember; +import org.telegram.telegrambots.meta.api.objects.Update; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Objects; + +public class TelegramBot extends TelegramLongPollingBot { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(TelegramBot.class); + + private Bot bot; + private ArrayList commandClasses; + + TelegramBot(Bot bot, ArrayList commandClasses) { + this.bot = bot; + this.commandClasses = commandClasses; + } + + public TelegramBot(Bot bot) { + this.bot = bot; + } + + @Override + public void onUpdateReceived(Update update) { + new Thread(new Runnable() { + private TelegramBot tBot; + + Runnable init(TelegramBot tBot) { + this.tBot = tBot; + return this; + } + + @Override + public void run() { + if (update.hasMessage() && update.getMessage().getText() != null + && !update.getMessage().getText().equals("") + && Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "possible_hotkeys")) + .indexOf(update.getMessage().getText().charAt(0)) >= 0) { + + String msg = update.getMessage().getText(); + int usrId = update.getMessage().getFrom().getId(); + PrefObj chatPrefs = getPrefs(update); + + if (chatPrefs == null) { + chatPrefs = new PrefObj(0, "strings-en.xml", "!"); + } + + if (msg.startsWith(Objects.requireNonNull(chatPrefs.getHotkey()))) { + + for (CommandWithClass cmds : getActiveCommandsAsCmdObject()) { + + String adjustCommand = msg.replace(Objects.requireNonNull(chatPrefs.getHotkey()), ""); + + if (adjustCommand.contains(" ")) { + adjustCommand = adjustCommand.split(" ")[0]; + } + + if (cmds.getAlias().equals(adjustCommand)) { + try { + runMethod(cmds.getClazz(), update, tBot, chatPrefs); + LOGGER.info(Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "command_ok")) + .replace("%1", String.valueOf(usrId)) + .replace("%2", adjustCommand)); + } catch (Exception e) { + LOGGER.error(Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "command_failure")) + .replace("%1", cmds.getAlias()) + .replace("%2", e.getMessage()), e); + } + } + } + } + } + } + }.init(this)).start(); + } + + public int sendMessage(String msg, Update update) { + SendMessage sndmsg = new SendMessage().setText(msg).setChatId(update.getMessage().getChatId()) + .enableMarkdown(true) + .disableWebPagePreview(); + try { + return execute(sndmsg).getMessageId(); + } catch (TelegramApiException e) { + LOGGER.error(e.getMessage(), e); + } + return 0; + } + + public void editMessage(String msg, Update update, int id) { + EditMessageText editMessageText = new EditMessageText().setText(msg) + .setChatId(update.getMessage().getChatId()) + .setMessageId(id) + .enableMarkdown(true); + try { + execute(editMessageText); + } catch (TelegramApiException e) { + // ignoring errors on edit, keep caution + //LOGGER.error(e.getMessage(), e); + } + } + + public boolean isUserAdminOrPV(Update update) { + String id1 = update.getMessage().getFrom().getId().toString(); + String id2 = update.getMessage().getChat().getId().toString(); + if (id1.equals(id2)) { + // private chat + return true; + } else { + try { + GetChatMember z = new GetChatMember(); + z.setChatId(update.getMessage().getChatId()); + z.setUserId(update.getMessage().getFrom().getId()); + ChatMember cx = execute(z); + switch (cx.getStatus()) { + case "administrator": + case "creator": + return true; + default: + return false; + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return false; + } + } + } + + private void runMethod(Class aClass, Update update, TelegramBot tBot, PrefObj prefs) { + try { + Object instance = ((Class) aClass).getDeclaredConstructor().newInstance(); + Method method = ((Class) aClass).getDeclaredMethod("botReply", Update.class, TelegramBot.class, PrefObj.class); + method.invoke(instance, update, tBot, prefs); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + public ArrayList getActiveCommandsAsCmdObject() { + ArrayList allCommandsArObj = new ArrayList<>(); + for (Class clazz : commandClasses) { + try { + Object instance = ((Class) clazz).getDeclaredConstructor().newInstance(); + Method methodAli = ((Class) clazz).getSuperclass().getDeclaredMethod("getAlias"); + Method methodInf = ((Class) clazz).getSuperclass().getDeclaredMethod("getCommandInfo"); + String alias = (String) methodAli.invoke(instance); + String desc = (String) methodInf.invoke(instance); + CommandWithClass c = new CommandWithClass(clazz, alias, desc); + allCommandsArObj.add(c); + } catch (Exception e) { + e.printStackTrace(); + } + } + return allCommandsArObj; + } + + private PrefObj getPrefs(Update update) { + long chatId = update.getMessage().getChatId(); + PrefObj prefObj = DbThings.selectIntoPrefsTable(chatId); + if (prefObj == null) { + DbThings.insertIntoPrefsTable(chatId); + } + return prefObj; + } + + @Override + public String getBotUsername() { + return bot.getUsername(); + } + + @Override + public String getBotToken() { + return bot.getToken(); + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/Chat2Shell.java b/src/main/java/com/vegazsdev/bobobot/commands/Chat2Shell.java new file mode 100755 index 0000000..94a757d --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/Chat2Shell.java @@ -0,0 +1,47 @@ +package com.vegazsdev.bobobot.commands; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.Config; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.telegram.telegrambots.meta.api.objects.Update; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Objects; + +public class Chat2Shell extends Command { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(Chat2Shell.class); + + public Chat2Shell() { + super("shell", "Run shell (bash) commands via chat"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) { + String msg = update.getMessage().getText().substring(7); + try { + StringBuilder text = new StringBuilder(); + ProcessBuilder pb; + pb = new ProcessBuilder("/bin/bash", "-c", msg); + pb.redirectErrorStream(true); + Process process = pb.start(); + InputStream is = process.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line; + while ((line = reader.readLine()) != null) { + text.append(line).append("\n"); + } + bot.sendMessage("`" + text.toString() + "`", update); + } catch (Exception e) { + bot.sendMessage(prefs.getString("something_went_wrong"), update); + LOGGER.error(e.getMessage(), e); + } + } + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/Download2GDrive.java b/src/main/java/com/vegazsdev/bobobot/commands/Download2GDrive.java new file mode 100644 index 0000000..ced029d --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/Download2GDrive.java @@ -0,0 +1,75 @@ +package com.vegazsdev.bobobot.commands; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.Config; +import com.vegazsdev.bobobot.utils.GDrive; +import org.apache.commons.io.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.telegram.telegrambots.meta.api.objects.Update; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Objects; +import java.util.stream.Stream; + +public class Download2GDrive extends Command { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(Download2GDrive.class); + + public Download2GDrive() { + super("d2gdrive", "Download and Send a File to your own Google Drive" + + " *only direct links are supported by now" + + " *download are made using aria2c"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) { + try { + String msg = update.getMessage().getText().split(" ")[1]; + ProcessBuilder pb; + bot.sendMessage(prefs.getString("d2g_downloading"), update); + pb = new ProcessBuilder("/bin/bash", "-c", "aria2c " + msg + " -d 'downloads/'"); + try { + FileUtils.deleteDirectory(new File("downloads")); + Process process = pb.start(); + process.waitFor(); + } catch (Exception e) { + throw new Exception(e); + } + + ArrayList var = new ArrayList<>(); + try (Stream paths = Files.walk(Paths.get("downloads/"))) { + paths + .filter(Files::isRegularFile) + .forEach(a -> var.add(a.toString())); + } catch (IOException e) { + throw new Exception(e); + } + try { + for (String sendFile : var) { + String fileTrim = sendFile.split("downloads/")[1]; + File uploadFile = new File(sendFile); + GDrive.createGoogleFile(null, "application/octet-stream", fileTrim, uploadFile); + bot.sendMessage(prefs.getString("d2g_file_sent"), update); + } + } catch (Exception e) { + throw new Exception(e); + } + } catch (Exception e) { + bot.sendMessage(prefs.getString("something_went_wrong"), update); + LOGGER.error(e.getMessage(), e); + } + + } else { + bot.sendMessage(prefs.getString("only_master_can_run"), update); + } + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/ErfanGSIs.java b/src/main/java/com/vegazsdev/bobobot/commands/ErfanGSIs.java new file mode 100755 index 0000000..381bfa0 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/ErfanGSIs.java @@ -0,0 +1,469 @@ +package com.vegazsdev.bobobot.commands; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.Config; +import com.vegazsdev.bobobot.utils.FileTools; +import com.vegazsdev.bobobot.utils.GDrive; +import com.vegazsdev.bobobot.utils.JSONs; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.telegram.telegrambots.meta.api.objects.Update; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.time.ZonedDateTime; +import java.util.*; +import java.util.stream.Stream; + +public class ErfanGSIs extends Command { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(ErfanGSIs.class); + + private static boolean isPorting = false; + private static ArrayList queue = new ArrayList<>(); + private final String toolPath = "ErfanGSIs/"; + private File[] supportedGSIs9 = new File(toolPath + "roms/9").listFiles(File::isDirectory); + private File[] supportedGSIs10 = new File(toolPath + "roms/10").listFiles(File::isDirectory); + private String infoGSI = ""; + + public ErfanGSIs() { + super("jurl2gsi", "Can port gsi"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + + String msg = update.getMessage().getText(); + String idAsString = update.getMessage().getFrom().getId().toString(); + + if (msg.contains(" allowuser") && Objects.equals(Config.getDefConfig("bot-master"), idAsString)) { + if (update.getMessage().getReplyToMessage() != null) { + String userid = update.getMessage().getReplyToMessage().getFrom().getId().toString(); + if (addPortPerm(userid)) { + bot.sendMessage(prefs.getString("egsi_allowed").replace("%1", userid), update); + } + } else if (msg.contains(" ")) { + String userid = msg.split(" ")[2]; + if (userid != null && userid.trim().equals("") && addPortPerm(userid)) { + bot.sendMessage(prefs.getString("egsi_allowed").replace("%1", userid), update); + } + } else { + bot.sendMessage(prefs.getString("egsi_allow_by_reply").replace("%1", prefs.getHotkey()) + .replace("%2", this.getAlias()), update); + } + } else if (msg.contains(" queue")) { + if (!queue.isEmpty()) { + StringBuilder v = new StringBuilder(); + for (int i = 0; i < queue.size(); i++) { + v.append("#").append(i + 1).append(": ").append(queue.get(i).getGsi()).append("\n"); + } + bot.sendMessage(prefs.getString("egsi_current_queue") + .replace("%2", v.toString()) + .replace("%1", String.valueOf(queue.size())), update); + } else { + bot.sendMessage(prefs.getString("egsi_no_ports_queue"), update); + } + } else if (msg.contains(" cancel")) { + + // cancel by now, maybe work, not tested + // will exit only on when porting is "active" (when url2gsi.sh is running) + // after that when port already already finished (eg. uploading, zipping) + // so this cancel needs more things to fully work + + ProcessBuilder pb; + pb = new ProcessBuilder("/bin/bash", "-c", "kill -TERM -- -$(ps ax | grep url2GSI.sh | grep -v grep | awk '{print $1;}')"); + try { + pb.start(); + } catch (IOException ex) { + //Logger.getLogger(BotTelegram.class.getName()).log(Level.SEVERE, null, ex); + } + } else { + + boolean userHasPermissions = userHasPortPermissions(idAsString); + + if (userHasPermissions) { + GSICmdObj gsiCommand = isCommandValid(update); + if (gsiCommand != null) { + boolean isGSITypeValid = isGSIValid(gsiCommand.getGsi()); + if (isGSITypeValid) { + if (!isPorting) { + isPorting = true; + createGSI(gsiCommand, bot); + while (queue.size() != 0) { + GSICmdObj portNow = queue.get(0); + queue.remove(0); + createGSI(portNow, bot); + } + isPorting = false; + } else { + queue.add(gsiCommand); + bot.sendMessage(prefs.getString("egsi_added_to_queue"), update); + } + } else { + bot.sendMessage(prefs.getString("egsi_supported_types") + .replace("%1", + Arrays.toString(supportedGSIs9).replace(toolPath + "roms/9/", "") + .replace("[", "") + .replace("]", "")) + .replace("%2", + Arrays.toString(supportedGSIs10).replace(toolPath + "roms/10/", "") + .replace("[", "") + .replace("]", "")), update); + } + } + + + } else { + // no perm + bot.sendMessage("No Permissions", update); + } + + } + } + + + private String try2AvoidCodeInjection(String parameters) { + try { + parameters = parameters.replace("&", "") + .replace("\\", "").replace(";", "").replace("<", "") + .replace(">", ""); + } catch (Exception e) { + return parameters; + } + return parameters; + } + + private GSICmdObj isCommandValid(Update update) { + GSICmdObj gsiCmdObj = new GSICmdObj(); + String msg = update.getMessage().getText().replace(Config.getDefConfig("bot-hotkey") + this.getAlias() + " ", ""); + String url; + String gsi; + String param; + try { + url = msg.split(" ")[1]; + gsiCmdObj.setUrl(url); + gsi = msg.split(" ")[2]; + gsiCmdObj.setGsi(gsi); + param = msg.replace(url + " ", "").replace(gsi, "").trim(); + param = try2AvoidCodeInjection(param); + gsiCmdObj.setParam(param); + gsiCmdObj.setUpdate(update); + return gsiCmdObj; + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return null; + } + } + + private boolean isGSIValid(String gsi) { + File[] supportedGSIs = ArrayUtils.addAll(supportedGSIs9, supportedGSIs10); + try { + String gsi2 = null; + if (gsi.contains(":")) { + gsi2 = gsi.split(":")[0]; + } + for (File supportedGSI : supportedGSIs) { + if (gsi2 != null) { + if (gsi2.equals(supportedGSI.getName())) { + return true; + } + } else { + if (gsi.equals(supportedGSI.getName())) { + return true; + } + } + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return false; + } + return false; + } + + private boolean userHasPortPermissions(String idAsString) { + if (Objects.equals(Config.getDefConfig("bot-master"), idAsString)) { + return true; + } + String portConfigFile = "configs/allowed2port.json"; + return Arrays.asList(Objects.requireNonNull(JSONs.getArrayFromJSON(portConfigFile)).toArray()).contains(idAsString); + } + + private void createGSI(GSICmdObj gsiCmdObj, TelegramBot bot) { + Update update = gsiCmdObj.getUpdate(); + ProcessBuilder pb; + pb = new ProcessBuilder("/bin/bash", "-c", + "cd " + toolPath + " ; ./url2GSI.sh '" + gsiCmdObj.getUrl() + "' " + gsiCmdObj.getGsi() + " " + gsiCmdObj.getParam() + ); + boolean success = false; + StringBuilder fullLogs = new StringBuilder(); + fullLogs.append("Starting process!"); + int id = bot.sendMessage(fullLogs.toString(), update); + try { + pb.redirectErrorStream(true); + Process process = pb.start(); + InputStream is = process.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line; + boolean weDontNeedAria2Logs = true; + while ((line = reader.readLine()) != null) { + System.out.println(line); + line = "`" + line + "`"; + if (line.contains("Downloading firmware to:")) { + weDontNeedAria2Logs = false; + fullLogs.append("\n").append(line); + bot.editMessage(fullLogs.toString(), update, id); + } + if (line.contains("Create Temp and out dir") || line.equals("Create Temp and out dir")) { + weDontNeedAria2Logs = true; + } + if (weDontNeedAria2Logs) { + fullLogs.append("\n").append(line); + bot.editMessage(fullLogs.toString(), update, id); + if (line.contains("GSI done on:")) { + success = true; + } + } + } + + if (success) { + + // gzip files! + + fullLogs.append("\n").append("Creating gzip..."); + bot.editMessage(fullLogs.toString(), update, id); + + String[] gzipFiles = listFilesForFolder(new File("ErfanGSIs" + "/output")); + for (String gzipFile : gzipFiles) { + new FileTools().gzipFile(gzipFile, gzipFile + ".gz"); + } + + // send to google drive + + ArrayList arr = new ArrayList<>(); + + try (Stream paths = Files.walk(Paths.get("ErfanGSIs/output/"))) { + paths + .filter(Files::isRegularFile) + .forEach(a -> { + if (!a.toString().endsWith(".img")) { + arr.add(a.toString()); + } + if (a.toString().contains(".txt")) { + infoGSI = a.toString(); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + + fullLogs.append("\n").append("Sending files to Google Drive..."); + bot.editMessage(fullLogs.toString(), update, id); + + GDriveGSI links = new GSIUpload().enviarGSI(gsiCmdObj.getGsi(), arr); + + if (gsiCmdObj.getGsi().contains(":")) { + gsiCmdObj.setGsi(gsiCmdObj.getGsi().split(":")[1]); + } + + StringBuilder generateLinks = new StringBuilder(); + + if (links.getA() != null && !links.getA().trim().equals("")) { + generateLinks.append("\n*Download A-Only:* [Google Drive](https://drive.google.com/uc?export=download&id=").append(links.getA()).append(")"); + } + if (links.getAb() != null && !links.getAb().trim().equals("")) { + generateLinks.append("\n*Download A/B:* [Google Drive](https://drive.google.com/uc?export=download&id=").append(links.getAb()).append(")"); + } + if (links.getFolder() != null && !links.getFolder().trim().equals("")) { + generateLinks.append("\n*View:* [Google Drive Folder](https://drive.google.com/drive/folders/").append(links.getFolder()).append(")"); + } + + String descGSI = "" + new FileTools().readFile(infoGSI).trim(); + + bot.sendMessage("*GSI: " + gsiCmdObj.getGsi() + "*\n\n" + + "*Firmware Base: *" + "[URL](" + gsiCmdObj.getUrl() + ")" + + "\n\n*Information:*\n`" + descGSI + + "`\n" + generateLinks.toString() + + "\n\n*Thanks to:* [Contributors List](https://github.com/erfanoabdi/ErfanGSIs/graphs/contributors)" + + "\n\n[Ported using ErfanGSIs Tool](https://github.com/erfanoabdi/ErfanGSIs)", update); + + fullLogs.append("\n").append("Finished!"); + bot.editMessage(fullLogs.toString(), update, id); + FileUtils.deleteDirectory(new File(toolPath + "output")); + } else { + throw new Exception("Task finished without generating a valid GSI"); + } + } catch (Exception ex) { + LOGGER.error(fullLogs); + } + } + + private static String[] listFilesForFolder(final File folder) { + StringBuilder paths = new StringBuilder(); + for (final File fileEntry : Objects.requireNonNull(folder.listFiles())) { + if (fileEntry.isDirectory()) { + listFilesForFolder(fileEntry); + } else { + if (fileEntry.getName().contains(".img")) { + paths.append(fileEntry.getAbsolutePath()).append("\n"); + } + } + } + return paths.toString().split("\n"); + } + + private boolean addPortPerm(String id) { + try { + if (new FileTools().checkFileExistsCurPath("configs/allowed2port.json")) { + ArrayList z = JSONs.getArrayFromJSON("configs/allowed2port.json"); + if (z != null) { + z.add(id); + } + JSONs.writeArrayToJSON(z, "configs/allowed2port.json"); + } else { + ArrayList z = new ArrayList<>(); + z.add(id); + JSONs.writeArrayToJSON(z, "configs/allowed2port.json"); + } + return true; + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return false; + } + } + +} + +class GSIUpload { + + GDriveGSI enviarGSI(String gsi, ArrayList var) { + String rand = RandomStringUtils.randomAlphabetic(8); + String date = new SimpleDateFormat("dd/MM/yyyy HH:mm z").format(Calendar.getInstance().getTime()); + try { + String uid = gsi + " GSI " + date + " " + rand; + GDrive.createGoogleFolder(null, uid); + List googleRootFolders = GDrive.getGoogleRootFolders(); + String folderId = ""; + for (com.google.api.services.drive.model.File folder : googleRootFolders) { + if (folder.getName().equals(uid)) { + folderId = folder.getId(); + //System.out.println("Folder ID: " + folder.getId() + " --- Name: " + folder.getName()); + } + } + for (String sendFile : var) { + String fileTrim = sendFile.split("output/")[1]; + File uploadFile = new File(sendFile); + GDrive.createGoogleFile(folderId, "application/gzip", fileTrim, uploadFile); + } + String aonly = ""; + String ab = ""; + List arquivosNaPasta = GDrive.showFiles(folderId); + for (com.google.api.services.drive.model.File f : arquivosNaPasta) { + if (!f.getName().contains(".txt")) { + if (f.getName().contains("Aonly")) { + aonly = f.getId(); + } else if (f.getName().contains("AB")) { + ab = f.getId(); + } + } + } + GDriveGSI links = new GDriveGSI(); + if (ab != null && !ab.trim().equals("")) { + links.setAb(ab); + } + if (aonly != null && !aonly.trim().equals("")) { + links.setA(aonly); + } + links.setFolder(folderId); + GDrive.createPublicPermission(folderId); + return links; + } catch (Exception e) { + return null; + } + } + +} + +class GSICmdObj { + + private String url; + private String gsi; + private String param; + private Update update; + + GSICmdObj() { + } + + String getUrl() { + return url; + } + + void setUrl(String url) { + this.url = url; + } + + String getGsi() { + return gsi; + } + + void setGsi(String gsi) { + this.gsi = gsi; + } + + String getParam() { + return param; + } + + void setParam(String param) { + this.param = param; + } + + public Update getUpdate() { + return update; + } + + public void setUpdate(Update update) { + this.update = update; + } +} + +class GDriveGSI { + + private String ab; + private String a; + private String folder; + + GDriveGSI() { + } + + String getAb() { + return ab; + } + + void setAb(String ab) { + this.ab = ab; + } + + String getA() { + return a; + } + + void setA(String a) { + this.a = a; + } + + String getFolder() { + return folder; + } + + void setFolder(String folder) { + this.folder = folder; + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/Hello.java b/src/main/java/com/vegazsdev/bobobot/commands/Hello.java new file mode 100755 index 0000000..61d66b0 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/Hello.java @@ -0,0 +1,19 @@ +package com.vegazsdev.bobobot.commands; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import org.telegram.telegrambots.meta.api.objects.Update; + +public class Hello extends Command { + + public Hello() { + super("hello", "Says hello!"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + bot.sendMessage(prefs.getString("hello").replace("%1", update.getMessage().getText()), update); + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/SetupGDrive.java b/src/main/java/com/vegazsdev/bobobot/commands/SetupGDrive.java new file mode 100755 index 0000000..da765d7 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/SetupGDrive.java @@ -0,0 +1,132 @@ +package com.vegazsdev.bobobot.commands; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.core.CustomConfigFileObj; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.Config; +import com.vegazsdev.bobobot.utils.FileTools; +import com.vegazsdev.bobobot.utils.GDrive; +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.json.JSONObject; +import org.telegram.telegrambots.meta.api.objects.Update; + +import java.io.*; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Objects; + +public class SetupGDrive extends Command { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(SetupGDrive.class); + + private String configFile = "gdrive.config"; + + private String validateURL = "https://accounts.google.com/o/oauth2/auth?access_type=offline&" + + "client_id=$CLIENT_ID$" + + "&redirect_uri=http://localhost:8888/Callback&response_type=code&scope=https://www.googleapis.com/auth/drive"; + + public SetupGDrive() { + super("setupgdrive", "Tests and Setup Google Drive connection"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + + // allow configuration only in master's private chat + + if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) { + if (update.getMessage().getText().contains("http") && !update.getMessage().getText().contains("json")) { + String callback = update.getMessage().getText(); + if (callback.contains(" url http")) { + callback = callback.split(" ")[2]; + } else { + callback = callback.split(" ")[1]; + } + try { + boolean success = false; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(callback).openStream(), StandardCharsets.UTF_8))) { + for (String line; (line = reader.readLine()) != null; ) { + if (line.contains(prefs.getString("gdrive_recv_ver_code"))) { + success = true; + } + } + } + if (success) { + bot.sendMessage(prefs.getString("gdrive_setup_complete"), update); + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } else if (update.getMessage().getText().contains("mykey")) { + String apikey = update.getMessage().getText().trim().split(" ")[2]; + if (!new FileTools().checkFileExistsCurPath(configFile)) { + createConfigFile(apikey, prefs); + bot.sendMessage(prefs.getString("gdrive_config_file_make").replace("%1", prefs.getHotkey()), update); + } else { + if (new File(configFile).delete()) { + bot.sendMessage(prefs.getString("gdrive_old_conf"), update); + } + } + } else if (update.getMessage().getText().contains("json")) { + try { + String msg = update.getMessage().getText().trim().split(" ")[2]; + PrintWriter writer = new PrintWriter(prefs.getString("gdrive_credentials_file")); + writer.println(msg); + writer.close(); + bot.sendMessage(prefs.getString("gdrive_credentials_created") + .replace("%1", prefs.getHotkey()), update); + } catch (Exception e) { + bot.sendMessage(prefs.getString("something_went_wrong"), update); + } + } else { + switch (update.getMessage().getText().replace(prefs.getHotkey(), "")) { + case "setupgdrive curltoken": + bot.sendMessage(prefs.getString("gdrive_localcurlinfo").replace("%1", prefs.getHotkey()), update); + break; + case "setupgdrive": + if (FileTools.createFolder("credentials")) { + bot.sendMessage(prefs.getString(prefs.getString("gdrive_credentails_folder_created")), update); + } else { + bot.sendMessage(prefs.getString("gdrive_credentails_folder_error"), update); + } + bot.sendMessage(prefs.getString("gdrive_how2setup").replace("%1", prefs.getHotkey()), update); + break; + case "setupgdrive ok": + try { + InputStream is = new FileInputStream("credentials/credentials.json"); + String jsonTxt = IOUtils.toString(is, StandardCharsets.UTF_8); + validateURL = validateURL.replace("$CLIENT_ID$", new JSONObject(jsonTxt).getJSONObject("installed").getString("client_id")); + bot.sendMessage(prefs.getString("gdrive_need2allow").replace("%1", validateURL), update); + bot.sendMessage(prefs.getString("gdrive_localcurl").replace("%1", prefs.getHotkey()), update); + new Thread(() -> { + try { + GDrive.getGoogleRootFolders(); + bot.sendMessage(prefs.getString("gdrive_setup_complete").replace("%1", prefs.getHotkey()), update); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + }).start(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + } + } else { + bot.sendMessage(prefs.getString("only_master_can_run"), update); + } + + + } + + private void createConfigFile(String key, PrefObj prefs) { + ArrayList configs = new ArrayList<>(); + configs.add(new CustomConfigFileObj("client-secret", key)); + Config.createCustomConfig(configs, configFile, prefs.getString("gdrive_setup_info")); + LOGGER.info(prefs.getString("gdrive_conf_file_created")); + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/def/About.java b/src/main/java/com/vegazsdev/bobobot/commands/def/About.java new file mode 100755 index 0000000..45ba0f5 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/def/About.java @@ -0,0 +1,29 @@ +package com.vegazsdev.bobobot.commands.def; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import org.telegram.telegrambots.meta.api.objects.Update; + +public class About extends Command { + + public About() { + super("about", "About infomation"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + bot.sendMessage( + "*bo³+t Bot* for Telegram by @VegaZS\n" + + "Written in Java using TelegramBots and many other libraries :)\n\n" + + "[TelegramBots (by rubenlagus)](https://github.com/rubenlagus/TelegramBots)\n" + + "[Apache Commons](https://commons.apache.org/)\n" + + "[Apache Log4j 2 (API/Core)](https://logging.apache.org/log4j/)\n" + + "[Google API Client](https://developers.google.com/api-client-library)\n" + + "[Google OAuth Client](https://developers.google.com/api-client-library/java/google-oauth-java-client)\n" + + "[Google Drive API](https://developers.google.com/drive)\n" + + "[Google Guava](https://github.com/google/guava)\n" + + "[SQLite JDBC Driver (by xerial)](https://github.com/xerial/sqlite-jdbc)" + + "", update); + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeHotkey.java b/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeHotkey.java new file mode 100755 index 0000000..7087dbc --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeHotkey.java @@ -0,0 +1,42 @@ +package com.vegazsdev.bobobot.commands.def; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.DbThings; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.XMLs; +import org.telegram.telegrambots.meta.api.objects.Update; + +public class ChangeHotkey extends Command { + + public ChangeHotkey() { + super("chkey", "Change current hotkey on this chat"); + } + + private String supportedHotkeys = XMLs.getFromStringsXML("core-strings.xml", "possible_hotkeys"); + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + if (bot.isUserAdminOrPV(update)) { + if (update.getMessage().getText().trim().equals(prefs.getHotkey() + "chkey".trim())) { + bot.sendMessage(prefs.getString("chkey_help") + .replace("%1", prefs.getHotkey()) + .replace("%2", supportedHotkeys), update); + } else { + if (update.getMessage().getText().contains(" ")) { + String msg = update.getMessage().getText().trim().split(" ")[1]; + if (supportedHotkeys.contains(msg)) { + DbThings.changeHotkey(prefs.getId(), msg); + prefs = DbThings.selectIntoPrefsTable(prefs.getId()); + bot.sendMessage(prefs.getString("chkey_cur_hotkey") + .replace("%1", prefs.getHotkey()), update); + } else { + bot.sendMessage(prefs.getString("only_admin_can_run"), update); + } + } else { + bot.sendMessage(prefs.getString("something_went_wrong"), update); + } + } + } + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeLang.java b/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeLang.java new file mode 100755 index 0000000..503d076 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/def/ChangeLang.java @@ -0,0 +1,48 @@ +package com.vegazsdev.bobobot.commands.def; + +import com.vegazsdev.bobobot.Main; +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.DbThings; +import com.vegazsdev.bobobot.db.PrefObj; +import com.vegazsdev.bobobot.utils.XMLs; +import org.telegram.telegrambots.meta.api.objects.Update; + + +public class ChangeLang extends Command { + + public ChangeLang() { + super("chlang", "Change current language on this chat"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + + if (bot.isUserAdminOrPV(update)) { + if (update.getMessage().getText().equals(prefs.getHotkey() + "chlang".trim())) { + bot.sendMessage("Available languages:\n" + XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "disp_lang") + + "\nTo change language, use: !chlang langcode\neg: !chlang br", update); + } else { + String msg = update.getMessage().getText().split(" ")[1].trim(); + if (msg.contains(" ")) { + msg = msg.replace(" ", ""); + } + if (msg.length() < 3) { + String hello = XMLs.getFromStringsXML("strings-" + msg + ".xml", "hello"); + if (hello == null) { + bot.sendMessage("Language not avaiable, type !chlang to see avaiable languages", update); + } else { + DbThings.changeLanguage(prefs.getId(), "strings-" + msg + ".xml"); + prefs = DbThings.selectIntoPrefsTable(prefs.getId()); + bot.sendMessage(prefs.getString("lang_updated"), update); + } + } else { + bot.sendMessage("Language not avaiable, type !chlang to see avaiable languages", update); + } + } + } else { + bot.sendMessage("Only admins can run this command", update); + } + + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/commands/def/ListAllCommands.java b/src/main/java/com/vegazsdev/bobobot/commands/def/ListAllCommands.java new file mode 100755 index 0000000..87f283c --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/commands/def/ListAllCommands.java @@ -0,0 +1,24 @@ +package com.vegazsdev.bobobot.commands.def; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.core.Command; +import com.vegazsdev.bobobot.db.PrefObj; +import org.telegram.telegrambots.meta.api.objects.Update; + +public class ListAllCommands extends Command { + + public ListAllCommands() { + super("comm", "Show all commands"); + } + + @Override + public void botReply(Update update, TelegramBot bot, PrefObj prefs) { + String hotkey = prefs.getHotkey(); + StringBuilder allCommandsAsString = new StringBuilder(); + for (int i = 0; i < bot.getActiveCommandsAsCmdObject().size(); i++) { + allCommandsAsString.append("*").append(hotkey).append(bot.getActiveCommandsAsCmdObject().get(i).getAlias()).append("*\n") + .append("_").append(bot.getActiveCommandsAsCmdObject().get(i).getCommandInfo()).append("_\n\n"); + } + bot.sendMessage(allCommandsAsString.toString(), update); + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/core/Bot.java b/src/main/java/com/vegazsdev/bobobot/core/Bot.java new file mode 100755 index 0000000..00a0d34 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/core/Bot.java @@ -0,0 +1,28 @@ +package com.vegazsdev.bobobot.core; + +public class Bot { + + public String token; + public String username; + + public Bot(String token, String username) { + this.token = token; + this.username = username; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/core/Command.java b/src/main/java/com/vegazsdev/bobobot/core/Command.java new file mode 100755 index 0000000..868bcd9 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/core/Command.java @@ -0,0 +1,35 @@ +package com.vegazsdev.bobobot.core; + +import com.vegazsdev.bobobot.TelegramBot; +import com.vegazsdev.bobobot.db.PrefObj; +import org.telegram.telegrambots.meta.api.objects.Update; + +public abstract class Command { + + private String alias; + private String commandInfo; + + public Command(String alias, String commandInfo) { + this.alias = alias; + this.commandInfo = commandInfo; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getCommandInfo() { + return commandInfo; + } + + public void setCommandInfo(String commandInfo) { + this.commandInfo = commandInfo; + } + + public abstract void botReply(Update update, TelegramBot bot, PrefObj prefs); + +} diff --git a/src/main/java/com/vegazsdev/bobobot/core/CommandWithClass.java b/src/main/java/com/vegazsdev/bobobot/core/CommandWithClass.java new file mode 100755 index 0000000..1ccab46 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/core/CommandWithClass.java @@ -0,0 +1,38 @@ +package com.vegazsdev.bobobot.core; + +public class CommandWithClass { + + private Class clazz; + private String alias; + private String commandInfo; + + public CommandWithClass(Class clazz, String alias, String commandInfo) { + this.clazz = clazz; + this.alias = alias; + this.commandInfo = commandInfo; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getCommandInfo() { + return commandInfo; + } + + public void setCommandInfo(String commandInfo) { + this.commandInfo = commandInfo; + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/core/CustomConfigFileObj.java b/src/main/java/com/vegazsdev/bobobot/core/CustomConfigFileObj.java new file mode 100755 index 0000000..41eb515 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/core/CustomConfigFileObj.java @@ -0,0 +1,28 @@ +package com.vegazsdev.bobobot.core; + +public class CustomConfigFileObj { + + private String confName; + private String confDefValue; + + public CustomConfigFileObj(String confName, String confDefValue) { + this.confName = confName; + this.confDefValue = confDefValue; + } + + public String getConfName() { + return confName; + } + + public void setConfName(String confName) { + this.confName = confName; + } + + public String getConfDefValue() { + return confDefValue; + } + + public void setConfDefValue(String confDefValue) { + this.confDefValue = confDefValue; + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/core/ForwardMethod.java b/src/main/java/com/vegazsdev/bobobot/core/ForwardMethod.java new file mode 100755 index 0000000..464ac8a --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/core/ForwardMethod.java @@ -0,0 +1,20 @@ +package com.vegazsdev.bobobot.core; + +public class ForwardMethod { + + private Class aClass; + private String alias; + + public ForwardMethod(Class aClass, String alias) { + this.aClass = aClass; + } + + public Class getaClass() { + return aClass; + } + + public String getAlias() { + return alias; + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/db/DbThings.java b/src/main/java/com/vegazsdev/bobobot/db/DbThings.java new file mode 100755 index 0000000..fb87349 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/db/DbThings.java @@ -0,0 +1,105 @@ +package com.vegazsdev.bobobot.db; + +import com.vegazsdev.bobobot.Main; +import com.vegazsdev.bobobot.utils.FileTools; +import com.vegazsdev.bobobot.utils.XMLs; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; + +import java.sql.*; +import java.util.Objects; + +public class DbThings { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(DbThings.class); + + // Generic Methods + + public static void createNewDatabase(String database) { + if (FileTools.checkIfFolderExists("databases")) { + FileTools.createFolder("databases"); + } + try (Connection conn = connect(database)) { + if (conn != null) { + DatabaseMetaData meta = conn.getMetaData(); + LOGGER.info(Objects.requireNonNull( + XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "sql_driver_info")) + .replace("%1", meta.getDriverName())); + LOGGER.info(Objects.requireNonNull( + XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "sql_db_ok")) + .replace("%1", database)); + } + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + + private static Connection connect(String database) { + String url = "jdbc:sqlite:databases/" + database; + Connection conn = null; + try { + conn = DriverManager.getConnection(url); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + return conn; + } + + public static void createTable(String database, String query) { + try (Connection conn = connect(database); + Statement stmt = conn.createStatement()) { + stmt.execute(query); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + + // specific prefs.db methods + + public static void insertIntoPrefsTable(double id) { + String sql = "INSERT INTO chat_prefs(group_id) VALUES(?)"; + try (Connection conn = connect("prefs.db"); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.setDouble(1, id); + pstmt.executeUpdate(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + + public static PrefObj selectIntoPrefsTable(double id) { + String sql = "SELECT group_id, lang, hotkey FROM chat_prefs WHERE group_id = " + id; + PrefObj prefObj = null; + try (Connection conn = connect("prefs.db"); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql)) { + while (rs.next()) { + prefObj = new PrefObj(rs.getDouble("group_id"), rs.getString("lang"), rs.getString("hotkey")); + } + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + return prefObj; + } + + public static void changeLanguage(double groupid, String newlang) { + String sql = "UPDATE chat_prefs SET lang = '" + newlang + "' WHERE group_id = " + groupid; + try (Connection conn = connect("prefs.db"); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.executeUpdate(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + + public static void changeHotkey(double groupid, String newhotkey) { + String sql = "UPDATE chat_prefs SET hotkey = '" + newhotkey + "' WHERE group_id = " + groupid; + try (Connection conn = connect("prefs.db"); + PreparedStatement pstmt = conn.prepareStatement(sql)) { + pstmt.executeUpdate(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/db/PrefObj.java b/src/main/java/com/vegazsdev/bobobot/db/PrefObj.java new file mode 100755 index 0000000..14d7277 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/db/PrefObj.java @@ -0,0 +1,47 @@ +package com.vegazsdev.bobobot.db; + +import com.vegazsdev.bobobot.utils.XMLs; + +public class PrefObj { + private double id; + private String lang; + private String hotkey; + + public PrefObj(double id, String lang, String hotkey) { + this.id = id; + this.lang = lang; + this.hotkey = hotkey; + } + + public double getId() { + return id; + } + + public void setId(double id) { + this.id = id; + } + + public String getLang() { + return lang; + } + + public void setLang(String lang) { + this.lang = lang; + } + + public String getString(String value) { + if (XMLs.getFromStringsXML(this.getLang(), value) == null) { + return XMLs.getFromStringsXML("strings-en.xml", value); + } else { + return XMLs.getFromStringsXML(this.getLang(), value); + } + } + + public String getHotkey() { + return hotkey; + } + + public void setHotkey(String hotkey) { + this.hotkey = hotkey; + } +} diff --git a/src/main/java/com/vegazsdev/bobobot/utils/Config.java b/src/main/java/com/vegazsdev/bobobot/utils/Config.java new file mode 100755 index 0000000..5bd3084 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/utils/Config.java @@ -0,0 +1,72 @@ +package com.vegazsdev.bobobot.utils; + +import com.vegazsdev.bobobot.Main; +import com.vegazsdev.bobobot.core.CustomConfigFileObj; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Objects; +import java.util.Properties; + +public class Config { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(Config.class); + + public boolean createDefConfig() { + try { + FileTools.createFolder("configs"); + Properties saveProps = new Properties(); + saveProps.setProperty("bot-token", "put your telegram bot token here"); + saveProps.setProperty("bot-username", "put your bot user name, without @"); + saveProps.setProperty("bot-master", "put your telegram user id here"); + saveProps.store(new FileOutputStream("configs/" + + Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "config_file")) + ), "Bo³+t config file"); + return true; + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return false; + } + } + + public static String getDefConfig(String prop) { + try { + Properties getProps = new Properties(); + getProps.load(new FileInputStream("configs/config.prop")); + return getProps.getProperty(prop); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + + public static boolean createCustomConfig(ArrayList configs, String configFile, String comment) { + FileTools.createFolder("configs"); + try { + Properties saveProps = new Properties(); + for (CustomConfigFileObj config : configs) { + saveProps.setProperty(config.getConfName(), config.getConfDefValue()); + } + saveProps.store(new FileOutputStream("configs/" + configFile), comment); + return true; + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return false; + } + } + + public String getCustomConfig(String filename, String prop) { + try { + Properties getProps = new Properties(); + getProps.load(new FileInputStream(filename)); + return getProps.getProperty(prop); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + +} diff --git a/src/main/java/com/vegazsdev/bobobot/utils/FileTools.java b/src/main/java/com/vegazsdev/bobobot/utils/FileTools.java new file mode 100755 index 0000000..5ccafb5 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/utils/FileTools.java @@ -0,0 +1,104 @@ +package com.vegazsdev.bobobot.utils; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.GZIPOutputStream; + +public class FileTools { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(FileTools.class); + + public boolean checkFileExistsCurPath(String file) { + File f = new File(file); + return f.exists() && !f.isDirectory(); + } + + public static boolean checkIfFolderExists(String folder) { + return !new File(folder).exists(); + } + + public static boolean createFolder(String folder) { + if (checkIfFolderExists(folder)) { + File dir = new File(folder); + return dir.mkdir(); + } else { + return false; + } + } + + public void gzipFile(String source_filepath, String destinaton_zip_filepath) { + + byte[] buffer = new byte[1024]; + + try { + + FileOutputStream fileOutputStream = new FileOutputStream(destinaton_zip_filepath); + + GZIPOutputStream gzipOuputStream = new GZIPOutputStream(fileOutputStream); + + FileInputStream fileInput = new FileInputStream(source_filepath); + + int bytes_read; + + while ((bytes_read = fileInput.read(buffer)) > 0) { + gzipOuputStream.write(buffer, 0, bytes_read); + } + + fileInput.close(); + + gzipOuputStream.finish(); + gzipOuputStream.close(); + + + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + + public String readFile(String fileName) throws Exception { + BufferedReader br = new BufferedReader(new FileReader(fileName)); + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + while (line != null) { + sb.append(line); + sb.append("\n"); + line = br.readLine(); + } + return sb.toString(); + } + + + public List getResourceFiles(String path) throws IOException { + List filenames = new ArrayList<>(); + + try ( + InputStream in = getResourceAsStream(path); + BufferedReader br = new BufferedReader(new InputStreamReader(in))) { + String resource; + + while ((resource = br.readLine()) != null) { + filenames.add(resource); + } + } + + return filenames; + } + + private InputStream getResourceAsStream(String resource) { + final InputStream in + = getContextClassLoader().getResourceAsStream(resource); + + return in == null ? getClass().getResourceAsStream(resource) : in; + } + + private ClassLoader getContextClassLoader() { + return Thread.currentThread().getContextClassLoader(); + } + + +} diff --git a/src/main/java/com/vegazsdev/bobobot/utils/GDrive.java b/src/main/java/com/vegazsdev/bobobot/utils/GDrive.java new file mode 100755 index 0000000..94a6ff5 --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/utils/GDrive.java @@ -0,0 +1,210 @@ +package com.vegazsdev.bobobot.utils; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; +import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; +import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; +import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.AbstractInputStreamContent; +import com.google.api.client.http.FileContent; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.util.store.FileDataStoreFactory; +import com.google.api.services.drive.Drive; +import com.google.api.services.drive.DriveScopes; +import com.google.api.services.drive.model.File; +import com.google.api.services.drive.model.FileList; +import com.google.api.services.drive.model.Permission; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; + +import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class GDrive { + + // most of code here is from: https://o7planning.org/en/11889/manipulating-files-and-folders-on-google-drive-using-java + // and from: https://developers.google.com/drive/api/v3/quickstart/java + + private static final Logger LOGGER = (Logger) LogManager.getLogger(GDrive.class); + + private static String APPLICATION_NAME = "Google Drive API Java Quickstart"; + + private static java.io.File CREDENTIALS_FOLDER = new java.io.File("credentials"); + + private static JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); + + // Directory to store user credentials for this application. + private static String CLIENT_SECRET_FILE_NAME = "credentials.json"; + + private static List SCOPES = Collections.singletonList(DriveScopes.DRIVE); + + // Global instance of the {@link FileDataStoreFactory}. + private static FileDataStoreFactory DATA_STORE_FACTORY; + + // Global instance of the HTTP transport. + private static HttpTransport HTTP_TRANSPORT; + + private static Drive _driveService; + + public static File createGoogleFolder(String folderIdParent, String folderName) throws IOException { + + File fileMetadata = new File(); + + fileMetadata.setName(folderName); + fileMetadata.setMimeType("application/vnd.google-apps.folder"); + + if (folderIdParent != null) { + List parents = Collections.singletonList(folderIdParent); + fileMetadata.setParents(parents); + } + Drive driveService = getDriveService(); + // Create a Folder. + // Returns File object with id & name fields will be assigned values + return driveService.files().create(fileMetadata).setFields("id, name").execute(); + } + + private static Drive getDriveService() throws IOException { + reset(); + _driveService = null; + Credential credential = getCredentials(); + _driveService = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) // + .setApplicationName(APPLICATION_NAME).build(); + return _driveService; + } + + private static void reset() { + APPLICATION_NAME = "Google Drive API Java Quickstart"; + JSON_FACTORY = JacksonFactory.getDefaultInstance(); + CLIENT_SECRET_FILE_NAME = "credentials.json"; + SCOPES = Collections.singletonList(DriveScopes.DRIVE); + try { + DATA_STORE_FACTORY = new FileDataStoreFactory(CREDENTIALS_FOLDER); + HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + _driveService = null; + } + + private static Credential getCredentials() throws IOException { + + java.io.File clientSecretFilePath = new java.io.File(CREDENTIALS_FOLDER, CLIENT_SECRET_FILE_NAME); + + if (!clientSecretFilePath.exists()) { + throw new FileNotFoundException("Please copy " + CLIENT_SECRET_FILE_NAME // + + " to folder: " + CREDENTIALS_FOLDER.getAbsolutePath()); + } + + InputStream in = new FileInputStream(clientSecretFilePath); + + GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); + + // Build flow and trigger user authorization request. + GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, + clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build(); + LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); + return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); + } + + public static List getGoogleRootFolders() throws IOException { + return getGoogleSubFolders(null); + } + + public static List getGoogleSubFolders(String googleFolderIdParent) throws IOException { + + Drive driveService = getDriveService(); + + String pageToken = null; + List list = new ArrayList(); + + String query = null; + if (googleFolderIdParent == null) { + query = " mimeType = 'application/vnd.google-apps.folder' " // + + " and 'root' in parents"; + } else { + query = " mimeType = 'application/vnd.google-apps.folder' " // + + " and '" + googleFolderIdParent + "' in parents"; + } + + do { + FileList result = driveService.files().list().setQ(query).setSpaces("drive") // + // Fields will be assigned values: id, name, createdTime + .setFields("nextPageToken, files(id, name, createdTime)")// + .setPageToken(pageToken).execute(); + for (File file : result.getFiles()) { + list.add(file); + } + pageToken = result.getNextPageToken(); + } while (pageToken != null); + // + return list; + } + + public static File createGoogleFile(String googleFolderIdParent, String contentType, // + String customFileName, java.io.File uploadFile) throws IOException { + AbstractInputStreamContent uploadStreamContent = new FileContent(contentType, uploadFile); + return _createGoogleFile(googleFolderIdParent, contentType, customFileName, uploadStreamContent); + } + + private static File _createGoogleFile(String googleFolderIdParent, String contentType, // + String customFileName, AbstractInputStreamContent uploadStreamContent) throws IOException { + + File fileMetadata = new File(); + fileMetadata.setName(customFileName); + + List parents = Arrays.asList(googleFolderIdParent); + fileMetadata.setParents(parents); + + Drive driveService = getDriveService(); + + File file = driveService.files().create(fileMetadata, uploadStreamContent) + .setFields("id, webContentLink, webViewLink, parents").execute(); + + return file; + } + + public static List showFiles(String parent) throws IOException { + + Drive driveService = getDriveService(); + + String pageToken = null; + List list = new ArrayList(); + + do { + FileList result = driveService.files().list() + .setQ("'" + parent + "' in parents and mimeType != 'application/vnd.google-apps.folder' and trashed = false") + .setSpaces("drive") + .setFields("nextPageToken, files(id, name, parents)") + .setPageToken(pageToken) + .execute(); + for (File file : result.getFiles()) { + list.add(file); + } + pageToken = result.getNextPageToken(); + } while (pageToken != null); + // + return list; + } + + public static Permission createPublicPermission(String googleFileId) throws IOException { + // All values: user - group - domain - anyone + String permissionType = "anyone"; + // All values: organizer - owner - writer - commenter - reader + String permissionRole = "reader"; + + Permission newPermission = new Permission(); + newPermission.setType(permissionType); + newPermission.setRole(permissionRole); + + Drive driveService = getDriveService(); + return driveService.permissions().create(googleFileId, newPermission).execute(); + } + + +} diff --git a/src/main/java/com/vegazsdev/bobobot/utils/JSONs.java b/src/main/java/com/vegazsdev/bobobot/utils/JSONs.java new file mode 100644 index 0000000..04fb7ee --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/utils/JSONs.java @@ -0,0 +1,50 @@ +package com.vegazsdev.bobobot.utils; + +import com.google.gson.Gson; +import com.vegazsdev.bobobot.Main; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; + +public class JSONs { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(JSONs.class); + + public static void writeArrayToJSON(ArrayList values, String file) { + Gson gson = new Gson(); + try { + FileOutputStream fileOutputStream = new FileOutputStream(file); + fileOutputStream.write(gson.toJson(values).getBytes()); + fileOutputStream.close(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + public static ArrayList getArrayFromJSON(String file) { + try { + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis); + BufferedReader bufferedReader = new BufferedReader(isr); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + sb.append(line); + } + String json = sb.toString(); + Gson gson = new Gson(); + return gson.fromJson(json, ArrayList.class); + } catch (Exception e) { + LOGGER.error(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "config_file_not_found") + "\n" + e.getMessage(), e); + return null; + } + + } + + +} diff --git a/src/main/java/com/vegazsdev/bobobot/utils/XMLs.java b/src/main/java/com/vegazsdev/bobobot/utils/XMLs.java new file mode 100755 index 0000000..746afbf --- /dev/null +++ b/src/main/java/com/vegazsdev/bobobot/utils/XMLs.java @@ -0,0 +1,46 @@ +package com.vegazsdev.bobobot.utils; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.util.Objects; + +public class XMLs { + + private static final Logger LOGGER = (Logger) LogManager.getLogger(XMLs.class); + + private static Element getElementFromStrings(String xmlFile) { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResourceAsStream("strings/" + xmlFile))); + return document.getDocumentElement(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return null; + } + } + + public static String getFromStringsXML(String file, String tagName) { + try { + Element element = getElementFromStrings(file); + assert element != null; + NodeList list = element.getElementsByTagName(tagName); + if (list != null && list.getLength() > 0) { + NodeList subList = list.item(0).getChildNodes(); + if (subList != null && subList.getLength() > 0) { + return subList.item(0).getNodeValue(); + } + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + return null; + } + +} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100755 index 0000000..658671b --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/strings/core-strings.xml b/src/main/resources/strings/core-strings.xml new file mode 100755 index 0000000..5dd0131 --- /dev/null +++ b/src/main/resources/strings/core-strings.xml @@ -0,0 +1,30 @@ + + + + + + + + config.prop + ! / ; - * \ , .' + en, br + + + + Bo³+t is Ready, waiting for Telegram messages! + Initializing Bo³+t... + [Command Classes] Initialized: %1 + CONFIG FILE CREATED! PLEASE EDIT THIS FILE WITH YOUR BOT INFORMATION AND RUN BOT AGAIN! EXITING... + Config file not found, creating a new one... + Exception thrown, returning null + Command Failure: %1 - %2 + %1 used %2 command + The driver name is %1 + A new database: %1 has been created. + + diff --git a/src/main/resources/strings/strings-br.xml b/src/main/resources/strings/strings-br.xml new file mode 100755 index 0000000..a54c5ed --- /dev/null +++ b/src/main/resources/strings/strings-br.xml @@ -0,0 +1,55 @@ + + + + + + Algo deu errado, Tente fazer o processo novamente + Apenas o Mestre do Bot pode usar esse comando + Apenas Administradores podem usar esse comando + + + + Olá! Sua mensagem foi: %1 + + + + Linguagens Disponíveis: + Linguagem Atualizada! + + + + credentials/credentials.json + *Credenciais criadas com sucesso!* Agora, execute *%1setupgdrive ok* + _Código de verificação recebido com sucesso!_ + _Pasta de credenciais criada!_ + Erro na criação da pasta de credenciais! (talvez a pasta ja exista?) + *Configuração Finalizada com Sucesso!* + Agora, precisamos conseguir acesso ao seu Google Drive, então, entre em: [here](%1) + Se depois de permitir o acesso e receber um erro ao acessar o localhost, copie a URL e digite: *%1setupgdrive curltoken* + Configura o Bo³+t para o Google Drive + Arquivo de Configuração do Google Drive foi criado com sucesso + Arquivo de Configuração antigo detectado, sendo assim, deletamos o arquivo antigo, execute esse comando para reconfigurar as credenciais! + Precisamos configurar sua conta do Google Drive para enviar arquivos, então, vamos configurar O Processo é bem simples, acesse: [Google Drive Dev. API](https://developers.google.com/drive/api/v3/quickstart/java) Toque em *Enable the Drive API* Copie o *Client Secret* e execute: *%1setupgdrive mykey ColarSuaClientSecretAqui* Depois disso, precisamos das credenciais, então, na mesma página de antes Toque em *DOWNLOAD CLIENT CONFIGURATION* salve e abra esse arquivo usando algum editor de texto *Copie todo o conteúdo do arquivo e execute: %1setupgdrive json ColarConteúdoAqui* Finalizado, apenas escreva *!setupgdrive ok* nesse chat + *Arquivo de configuração criado!* Continue configurando usando *%1setupgdrive json ColeConteúdoDoJSONAqui* + Para ativar o Token manualmente, envie-me a URL com a falha ao acessar o localhost! Faça isso usando: *%1setupgdrive url* Ex: %1setupgdrive http://localhost:8888/Callback?4.... + + + + UserID: *%1* agora tem permissões para portar GSIs + Para adicionar permissões, responda o usuário desejado com: *%1%2 allowuser* + *Ports na Fila:* _%1 %2_ + Port adicionado na fila + Sem Ports na Fila + *Tipo de GSI ou URL invalida!* Tipos de GSIs suportadas no Android 9: %1 Tipos de GSIs suportadas no Android 10: %2 + + + + Baixando Arquivo... + Arquivo enviado para seu Google Drive + + + + Hotkey atual neste chat: *%1* *Hotkeys Suportadas: %2* Para trocar a hotkey deste chat, execute esse comando novamente, passando a Hotkey desejada *ex: %1chkey /* + Hotkey atual deste chat: *%1* + + diff --git a/src/main/resources/strings/strings-en.xml b/src/main/resources/strings/strings-en.xml new file mode 100755 index 0000000..5d20ca6 --- /dev/null +++ b/src/main/resources/strings/strings-en.xml @@ -0,0 +1,66 @@ + + + + + + + + Something went wrong, try to do the process again + Only Bot Master can use this command + Only Administrators can use this command + + + + Hello! Your message was: %1 + + + + Available Languages: + Language Updated! + + + + credentials/credentials.json + *Credentials created with success!* Now, run *%1setupgdrive ok* + _Received verification code!_ + Credentials folder created! + Error on create credentials folder! (maybe this folder already exists?) + *Setup Complete!* + Now, we need to get your Google Drive permissions, so, enter [here](%1) + If you get a error when try to access localhost, type: *%1setupgdrive curltoken* + Setup Bo³+t for Google Drive + Google Drive config file created + Old config file detected, so we deleted, run this command again to setup new credentials! + We need to configure your Google Drive Account in order to send files to Google Drive, so, please configure The setup is very easy, just enter here: [Google Drive Dev. API](https://developers.google.com/drive/api/v3/quickstart/java) Tap in *Enable the Drive API* Copy *Client Secret* and run this command: *%1setupgdrive mykey PasteYourClientSecretHere* After that, we need to get credentials, so, in the same page that you get Client Secret Tap on *DOWNLOAD CLIENT CONFIGURATION* save and open this file *Copy everything and run this command: %1setupgdrive json PasteFullJSONHere* Once you got that finished, just type *!setupgdrive ok* on this chat + *Config file created!* Proceed setup using *%1setupgdrive json YourJSONCredentialsHere* + To activate token manually, send url that gives you error! Do that by using: *%1setupgdrive url* Example: %1setupgdrive http://localhost:8888/Callback?4.... + + + + UserID: *%1* now has port permissions + To add permissions, reply to user that you wanna add permissions, by using *%1%2 allowuser* + *Ports on Queue:* %1 _%2_ + Added to Queue + No ports on queue + *GSI Type or URL is not valid!* Supported types on Android 9: %1 Supported types on Android 10: %2 + + + + Downloading file... + File sent to your Google Drive + + + + Current bot hotkey on this chat: *%1* *Supported Hotkeys: %2* To change hotkey on this group, run this command again, passing the desired hotkey *eg: %1chkey /* + Current hotkey now is: *%1* + +