ListInlineKeyboardButtonChannel = new ArrayList<>();
53 | InlineKeyboardButton ListInlineKeyboardButtonChannelBTN = new InlineKeyboardButton();
54 | ListInlineKeyboardButtonChannelBTN.setText(prefs.getString("start_treble_experience"));
55 | ListInlineKeyboardButtonChannelBTN.setUrl("https://t.me/TrebleExperience");
56 | ListInlineKeyboardButtonChannel.add(ListInlineKeyboardButtonChannelBTN);
57 | rowsInline.add(ListInlineKeyboardButtonChannel);
58 |
59 | /*
60 | * Finish InlineKeyboardButton setup
61 | */
62 | markupInline.setKeyboard(rowsInline);
63 | message.setReplyMarkup(markupInline);
64 |
65 | /*
66 | * Send the message
67 | */
68 | bot.sendMessageAsyncBase(message, update);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/owner/Eval.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.owner;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.core.command.annotations.DisableCommand;
6 | import com.vegazsdev.bobobot.db.PrefObj;
7 | import com.vegazsdev.bobobot.utils.Config;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.telegram.telegrambots.meta.api.objects.Update;
11 |
12 | import javax.script.ScriptEngine;
13 | import javax.script.ScriptEngineManager;
14 | import java.util.Objects;
15 |
16 | import static com.vegazsdev.bobobot.Main.shellStatus;
17 |
18 | /**
19 | * Execute some commands using one command, this is Eval.
20 | * That command has been disabled.
21 | */
22 | @DisableCommand
23 | @SuppressWarnings("unused")
24 | public class Eval extends Command {
25 |
26 | /**
27 | * Logger: To send warning, info & errors to terminal.
28 | */
29 | private static final Logger logger = LoggerFactory.getLogger(Eval.class);
30 |
31 | public Eval() {
32 | super("eval");
33 | }
34 |
35 | @SuppressWarnings("SpellCheckingInspection")
36 | @Override
37 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
38 | ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
39 | String[] msgComparableRaw = update.getMessage().getText().split(" ");
40 |
41 | if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) {
42 | try {
43 | engine.eval("var imports = new JavaImporter(" +
44 | "java," +
45 | "java.io," +
46 | "java.lang," +
47 | "java.util," +
48 | "Packages.com.vegazsdev.bobobot.commands" +
49 | "Packages.org.telegram.telegrambots," +
50 | "Packages.org.telegram.telegrambots.meta.api.methods," +
51 | "Packages.org.telegram.telegrambots.meta.api.objects" +
52 | ");"
53 | );
54 |
55 | engine.put("args", msgComparableRaw);
56 | engine.put("bot", bot);
57 | engine.put("shell", shellStatus);
58 | engine.put("engine", engine);
59 | engine.put("update", update);
60 | engine.put("prefs", prefs);
61 |
62 | String command = update.getMessage().getText().substring(msgComparableRaw[0].length());
63 |
64 | Object out = engine.eval(
65 | "(function() {" +
66 | "with (imports) {\n" +
67 | command +
68 | "\n}" +
69 | "})();"
70 | );
71 |
72 | bot.sendMessageAsync(out == null ? "Executed without error." : out.toString(), update);
73 | } catch (Exception exception) {
74 | bot.sendMessageAsync("`" + exception.getMessage() + "`", update);
75 | logger.error(exception.getMessage());
76 | }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/utils/FileTools.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.utils;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.*;
7 | import java.util.zip.GZIPOutputStream;
8 |
9 | public class FileTools {
10 |
11 | /**
12 | * Logger: To send warning, info & errors to terminal.
13 | */
14 | private static final Logger logger = LoggerFactory.getLogger(FileTools.class);
15 |
16 | public static boolean checkIfFolderExists(String folder) {
17 | File file = new File(folder);
18 | return file.exists() && file.isDirectory();
19 | }
20 |
21 | public static void createFolder(String folder) {
22 | if (!checkIfFolderExists(folder)) {
23 | File dir = new File(folder);
24 | dir.mkdir();
25 | }
26 | }
27 |
28 | public static boolean deleteFolder(String folder) {
29 | File file = new File(folder);
30 | return file.delete();
31 | }
32 |
33 | public static boolean checkFileExistsCurPath(String file) {
34 | File f = new File(file);
35 | return f.exists() && !f.isDirectory();
36 | }
37 |
38 | public void gzipFile(String source_filepath, String dest) {
39 | FileOutputStream fileOutputStream = null;
40 | GZIPOutputStream gzipOutputStream = null;
41 | FileInputStream fileInput = null;
42 |
43 | byte[] buffer = new byte[1024];
44 |
45 | try {
46 | fileOutputStream = new FileOutputStream(dest);
47 | gzipOutputStream = new GZIPOutputStream(fileOutputStream);
48 | fileInput = new FileInputStream(source_filepath);
49 |
50 | int bytes_read;
51 |
52 | while ((bytes_read = fileInput.read(buffer)) > 0) {
53 | gzipOutputStream.write(buffer, 0, bytes_read);
54 | }
55 |
56 | fileInput.close();
57 | } catch (Exception e) {
58 | logger.error(e.getMessage(), e);
59 | } finally {
60 | try {
61 | if (gzipOutputStream != null) {
62 | gzipOutputStream.finish();
63 | gzipOutputStream.close();
64 | }
65 |
66 | if (fileInput != null) fileInput.close();
67 |
68 | if (fileOutputStream != null) {
69 | fileOutputStream.flush();
70 | fileOutputStream.close();
71 | }
72 | } catch (Exception exception) {
73 | logger.error(exception.getMessage());
74 | }
75 | }
76 | }
77 |
78 | public String readFile(String fileName) {
79 | BufferedReader bufferedReader = null;
80 | FileReader fileReader = null;
81 |
82 | StringBuilder stringBuilder = new StringBuilder();
83 | String line;
84 |
85 | try {
86 | fileReader = new FileReader(fileName);
87 | bufferedReader = new BufferedReader(fileReader);
88 |
89 | line = bufferedReader.readLine();
90 |
91 | while (line != null) {
92 | stringBuilder.append(line);
93 | stringBuilder.append("\n");
94 | line = bufferedReader.readLine();
95 | }
96 | return stringBuilder.toString();
97 | } catch (Exception exception) {
98 | logger.error(exception.getMessage());
99 | } finally {
100 | try {
101 | if (fileReader != null) fileReader.close();
102 | if (bufferedReader != null) bufferedReader.close();
103 | } catch (Exception exception) {
104 | logger.error(exception.getMessage());
105 | }
106 | }
107 | return null;
108 | }
109 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/gsi/SourceForgeSetup.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.gsi;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.db.PrefObj;
6 | import com.vegazsdev.bobobot.utils.Config;
7 | import com.vegazsdev.bobobot.utils.FileTools;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.telegram.telegrambots.meta.api.objects.Update;
11 |
12 | import java.io.FileInputStream;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 | import java.util.Objects;
16 | import java.util.Properties;
17 |
18 | /**
19 | * This class is important for the ErfanGSI command.
20 | *
21 | * That class setup sourceforge prop file for GSI upload.
22 | */
23 | public class SourceForgeSetup extends Command {
24 |
25 | /**
26 | * Logger: To send warning, info & errors to terminal.
27 | */
28 | private static final Logger logger = LoggerFactory.getLogger(SourceForgeSetup.class);
29 |
30 | public SourceForgeSetup() {
31 | super("sfs");
32 | }
33 |
34 | /**
35 | * Get prop from sourceforge config file.
36 | */
37 | @SuppressWarnings("SpellCheckingInspection")
38 | public static String getSfConf(String prop) {
39 | FileInputStream fileInputStream = null;
40 | try {
41 | Properties getProps = new Properties();
42 | fileInputStream = new FileInputStream("configs/sf-creds.prop");
43 | getProps.load(fileInputStream);
44 | return getProps.getProperty(prop);
45 | } catch (Exception exception) {
46 | logger.error(exception.getMessage());
47 | } finally {
48 | if (fileInputStream != null) {
49 | try {
50 | fileInputStream.close();
51 | } catch (IOException ioException) {
52 | logger.error(ioException.getMessage());
53 | }
54 | }
55 | }
56 | return null;
57 | }
58 |
59 | @SuppressWarnings("SpellCheckingInspection")
60 | @Override
61 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
62 | if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) {
63 | if (FileTools.checkFileExistsCurPath("configs/sf-creds.prop")) {
64 | bot.sendReply(prefs.getString("unable_to_create"), update);
65 | } else {
66 | mkSfConf();
67 | bot.sendReply(prefs.getString("created_sf_folder"), update);
68 | }
69 | }
70 | }
71 |
72 | /**
73 | * Method to setup sourceforge config file.
74 | */
75 | @SuppressWarnings("SpellCheckingInspection")
76 | public void mkSfConf() {
77 | FileOutputStream fileOutputStream = null;
78 |
79 | try {
80 | Properties saveProps = new Properties();
81 | if (!FileTools.checkFileExistsCurPath("configs/sf-creds.prop")) {
82 | saveProps.setProperty("bot-sf-user", "put your sf username");
83 | saveProps.setProperty("bot-sf-host", "frs.sourceforge.net");
84 | saveProps.setProperty("bot-sf-pass", "put your sf pass");
85 | saveProps.setProperty("bot-sf-proj", "put your sf project name");
86 | saveProps.setProperty("bot-send-announcement", "false");
87 | saveProps.setProperty("bot-announcement-id", "none");
88 |
89 | fileOutputStream = new FileOutputStream("configs/sf-creds.prop");
90 | saveProps.store(fileOutputStream, null);
91 | }
92 | } catch (Exception exception) {
93 | logger.error(exception.getMessage());
94 | } finally {
95 | if (fileOutputStream != null) {
96 | try {
97 | fileOutputStream.flush();
98 | fileOutputStream.close();
99 | } catch (IOException ioException) {
100 | logger.error(ioException.getMessage());
101 | }
102 | }
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/db/DbThings.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.db;
2 |
3 | import com.vegazsdev.bobobot.Main;
4 | import com.vegazsdev.bobobot.utils.FileTools;
5 | import com.vegazsdev.bobobot.utils.XMLs;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.sql.*;
10 | import java.util.Objects;
11 |
12 | public class DbThings {
13 |
14 | /**
15 | * Logger: To send warning, info & errors to terminal.
16 | */
17 | private static final Logger logger = LoggerFactory.getLogger(DbThings.class);
18 |
19 | public static void createNewDatabase(String database) {
20 | if (!FileTools.checkIfFolderExists("databases")) {
21 | FileTools.createFolder("databases");
22 | }
23 | try (Connection conn = connect(database)) {
24 | if (conn != null) {
25 | DatabaseMetaData meta = conn.getMetaData();
26 | logger.info(Objects.requireNonNull(
27 | XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "sql_driver_info"))
28 | .replace("%1", meta.getDriverName()));
29 | logger.info(Objects.requireNonNull(
30 | XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "sql_db_ok"))
31 | .replace("%1", database));
32 | }
33 | } catch (SQLException e) {
34 | logger.error(e.getMessage(), e);
35 | }
36 | }
37 |
38 | private static Connection connect(String database) {
39 | String url = "jdbc:sqlite:databases/" + database;
40 | Connection conn = null;
41 | try {
42 | conn = DriverManager.getConnection(url);
43 | } catch (SQLException e) {
44 | logger.error(e.getMessage(), e);
45 | }
46 | return conn;
47 | }
48 |
49 | public static void createTable(String database, String query) {
50 | try (Connection conn = connect(database);
51 | Statement stmt = conn.createStatement()) {
52 | stmt.execute(query);
53 | } catch (SQLException e) {
54 | logger.error(e.getMessage(), e);
55 | }
56 | }
57 |
58 | // specific prefs.db methods
59 |
60 | public static void insertIntoPrefsTable(double id) {
61 | String sql = "INSERT INTO chat_prefs(group_id) VALUES(?)";
62 | try (Connection conn = connect("prefs.db");
63 | PreparedStatement prepareStatement = conn.prepareStatement(sql)) {
64 | prepareStatement.setDouble(1, id);
65 | prepareStatement.executeUpdate();
66 | } catch (SQLException e) {
67 | logger.error(e.getMessage());
68 | }
69 | }
70 |
71 | public static PrefObj selectIntoPrefsTable(double id) {
72 | String sql = "SELECT group_id, lang, hotkey FROM chat_prefs WHERE group_id = " + id;
73 | PrefObj prefObj = null;
74 | try (Connection conn = connect("prefs.db");
75 | Statement stmt = conn.createStatement();
76 | ResultSet rs = stmt.executeQuery(sql)) {
77 | while (rs.next()) {
78 | prefObj = new PrefObj(rs.getDouble("group_id"), rs.getString("lang"), rs.getString("hotkey"));
79 | }
80 | } catch (SQLException e) {
81 | logger.error(e.getMessage());
82 | }
83 | return prefObj;
84 | }
85 |
86 | public static void changeLanguage(double groupId, String newLang) {
87 | String sql = "UPDATE chat_prefs SET lang = '" + newLang + "' WHERE group_id = " + groupId;
88 | try (Connection conn = connect("prefs.db");
89 | PreparedStatement prepareStatement = conn.prepareStatement(sql)) {
90 | prepareStatement.executeUpdate();
91 | } catch (SQLException e) {
92 | logger.error(e.getMessage());
93 | }
94 | }
95 |
96 | public static void changeHotkey(double groupId, String newHotkey) {
97 | String sql = "UPDATE chat_prefs SET hotkey = '" + newHotkey + "' WHERE group_id = " + groupId;
98 | try (Connection conn = connect("prefs.db");
99 | PreparedStatement prepareStatement = conn.prepareStatement(sql)) {
100 | prepareStatement.executeUpdate();
101 | } catch (SQLException e) {
102 | logger.error(e.getMessage());
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/utils/JSONs.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.utils;
2 |
3 | import com.google.common.annotations.Beta;
4 | import com.google.gson.Gson;
5 | import com.vegazsdev.bobobot.Main;
6 | import org.json.JSONArray;
7 | import org.json.JSONObject;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.io.*;
12 | import java.util.ArrayList;
13 |
14 | public class JSONs {
15 |
16 | /**
17 | * Logger: To send warning, info & errors to terminal.
18 | */
19 | private static final Logger logger = LoggerFactory.getLogger(JSONs.class);
20 |
21 | public static void writeArrayToJSON(ArrayList values, String file) {
22 | Gson gson = new Gson();
23 | FileOutputStream fileOutputStream = null;
24 |
25 | try {
26 | fileOutputStream = new FileOutputStream(file);
27 | fileOutputStream.write(gson.toJson(values).getBytes());
28 | fileOutputStream.close();
29 | } catch (Exception e) {
30 | logger.error(e.getMessage(), e);
31 | } finally {
32 | if (fileOutputStream != null) {
33 | try {
34 | fileOutputStream.flush();
35 | fileOutputStream.close();
36 | } catch (IOException ioException) {
37 | logger.error(ioException.getMessage());
38 | }
39 | }
40 | }
41 | }
42 |
43 | @SuppressWarnings("rawtypes")
44 | public static ArrayList getArrayFromJSON(String file) {
45 | Gson gson = new Gson();
46 |
47 | FileInputStream fileInputStream = null;
48 | InputStreamReader inputStreamReader = null;
49 | BufferedReader bufferedReader = null;
50 |
51 | try {
52 | fileInputStream = new FileInputStream(file);
53 | inputStreamReader = new InputStreamReader(fileInputStream);
54 | bufferedReader = new BufferedReader(inputStreamReader);
55 | StringBuilder stringBuilder = new StringBuilder();
56 |
57 | String line;
58 |
59 | while ((line = bufferedReader.readLine()) != null) {
60 | stringBuilder.append(line);
61 | }
62 |
63 | String json = stringBuilder.toString();
64 | return gson.fromJson(json, ArrayList.class);
65 | } catch (Exception e) {
66 | logger.error(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "config_file_not_found") + "\n" + e.getMessage(), e);
67 | return null;
68 | } finally {
69 | if (fileInputStream != null) {
70 | try {
71 | fileInputStream.close();
72 | } catch (IOException ioException) {
73 | logger.error(ioException.getMessage(), ioException);
74 | }
75 | }
76 |
77 | if (inputStreamReader != null) {
78 | try {
79 | inputStreamReader.close();
80 | } catch (IOException ioException) {
81 | logger.error(ioException.getMessage(), ioException);
82 | }
83 | }
84 |
85 | if (bufferedReader != null) {
86 | try {
87 | bufferedReader.close();
88 | } catch (IOException ioException) {
89 | logger.error(ioException.getMessage(), ioException);
90 | }
91 | }
92 | }
93 | }
94 |
95 | // START: LAZY METHODS
96 | @Beta
97 | public static String getValueOfArrayFromJSONObject(String json, String array, String value) {
98 | try {
99 | JSONObject jsonObject = new JSONObject(json);
100 | JSONArray jsonArray = jsonObject.getJSONArray(array);
101 | return jsonArray.getJSONObject(0).getString(value);
102 | } catch (Exception exception) {
103 | logger.error(exception.getMessage(), exception);
104 | }
105 | return null;
106 | }
107 |
108 | @Beta
109 | public static long getLongOfArrayFromJSONObject(String json, String array, String value) {
110 | try {
111 | JSONObject jsonObject = new JSONObject(json);
112 | JSONArray jsonArray = jsonObject.getJSONArray(array);
113 | return jsonArray.getJSONObject(0).getLong(value);
114 | } catch (Exception exception) {
115 | logger.error(exception.getMessage(), exception);
116 | }
117 | return 0;
118 | }
119 | // END: LAZY METHODS
120 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/android/StatiXOS.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.android;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.db.PrefObj;
6 | import com.vegazsdev.bobobot.utils.JSONs;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
10 | import org.telegram.telegrambots.meta.api.objects.Update;
11 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
12 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
13 |
14 | import java.net.URI;
15 | import java.net.http.HttpClient;
16 | import java.net.http.HttpRequest;
17 | import java.net.http.HttpResponse;
18 | import java.sql.Timestamp;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * That class is for StatiXOS.
24 | */
25 | @SuppressWarnings({"unused", "SpellCheckingInspection"})
26 | public class StatiXOS extends Command {
27 |
28 | private static final Logger logger = LoggerFactory.getLogger(StatiXOS.class);
29 |
30 | public StatiXOS() {
31 | super("sxos");
32 | }
33 |
34 | @Override
35 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
36 | /*
37 | * Main vars
38 | */
39 | String[] msgComparableRaw = update.getMessage().getText().split(" ");
40 |
41 | /*
42 | * Prepare sendMessage
43 | */
44 | SendMessage sendMessage = new SendMessage();
45 | sendMessage.setDisableWebPagePreview(true);
46 | sendMessage.enableHtml(true);
47 |
48 | /*
49 | * Prepare InlineKeyboardButton
50 | */
51 | InlineKeyboardMarkup markupInline = new InlineKeyboardMarkup();
52 | List> rowsInline = new ArrayList<>();
53 |
54 | if (update.getMessage().getText().contains(" ")) {
55 | /*
56 | * Try to run
57 | */
58 | try {
59 | /*
60 | * Prepare HttpClient base
61 | */
62 | String urlBase = "https://downloads.statixos.com/json/";
63 | HttpClient client = HttpClient.newHttpClient();
64 | HttpRequest request = HttpRequest.newBuilder()
65 | .uri(URI.create(urlBase + msgComparableRaw[1].replace(".json", "") + ".json"))
66 | .build();
67 |
68 | /*
69 | * Run the request
70 | */
71 | client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
72 | .thenApply(response -> {
73 | if (response.statusCode() == 200) {
74 | /*
75 | * Prepare the variables
76 | */
77 | Timestamp timestamp = new Timestamp(JSONs.getLongOfArrayFromJSONObject(String.valueOf(response.body()), "response", "datetime"));
78 | String urlToDownload = JSONs.getValueOfArrayFromJSONObject(String.valueOf(response.body()), "response", "url");
79 | String romType = JSONs.getValueOfArrayFromJSONObject(String.valueOf(response.body()), "response", "romtype");
80 | String romName = JSONs.getValueOfArrayFromJSONObject(String.valueOf(response.body()), "response", "filename");
81 | String romVersion = JSONs.getValueOfArrayFromJSONObject(String.valueOf(response.body()), "response", "version");
82 | String ID = JSONs.getValueOfArrayFromJSONObject(String.valueOf(response.body()), "response", "id");
83 |
84 | /*
85 | * Set download variable into Inline Keyboard Button
86 | */
87 | List inlineKeyboardButtonArrayList = new ArrayList<>();
88 | InlineKeyboardButton downloadROM = new InlineKeyboardButton();
89 |
90 | downloadROM.setText("\uD83D\uDCE6 Download");
91 | downloadROM.setUrl(urlToDownload);
92 | inlineKeyboardButtonArrayList.add(downloadROM);
93 | rowsInline.add(inlineKeyboardButtonArrayList);
94 |
95 | /*
96 | * Finish
97 | */
98 | markupInline.setKeyboard(rowsInline);
99 | sendMessage.setReplyMarkup(markupInline);
100 |
101 | /*
102 | * Set the text
103 | */
104 | sendMessage.setChatId(String.valueOf(update.getMessage().getChatId()));
105 | sendMessage.setText(
106 | "✉️ File name\n"
107 | + romName + "\n\n"
108 | + "❓ Status Type\n"
109 | + romType + "\n\n"
110 | + "\uD83D\uDCCD ID\n"
111 | + ID + "\n\n"
112 | + "\uD83D\uDD30 Version\n"
113 | + romVersion + ""
114 | );
115 | bot.sendMessageAsyncBase(sendMessage, update);
116 | } else {
117 | bot.sendReply("Failed", update);
118 | }
119 | return response;
120 | })
121 | .thenApply(HttpResponse::body);
122 | } catch (Exception exception) {
123 | logger.error(exception.getMessage());
124 | }
125 | } else {
126 | bot.sendReply(prefs.getString("bad_usage"), update);
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/src/main/resources/strings/strings-br.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Algo deu errado, Tente fazer o processo novamente
6 | Apenas o Mestre do Bot pode usar esse comando
7 | Apenas Administradores podem usar esse comando
8 | Mal uso.
9 |
10 |
11 | Olá! Como você está? 👋
Fui desenvolvido especialmente para servir de automatização para ErfanGSIs, não tenho muitas funções além disso.
12 | 🔧 Código-fonte
13 | 📫 Canal da TrebleExperience
14 |
15 |
16 | ❔<b> Sobre</b>
<b>Bo³+t</b> é programado em java e originalmente desenvolvido por @VegaZS
⌨<b> Desenvolvedor/Mantenedor do Bo³+t</b>
<a href="https://github.com/VegaBobo">VegaZS</a> - Desenvolvedor original
<a href="https://github.com/Velosh">Velosh</a> - Mantenedor não oficial do <b>Bo³+t</b> para Treble Experience
❕<b> Info da Build</b>
<code>%1</code>
17 | ❕ Código-fonte
18 | 🌐 Canal do Treble
19 |
20 |
21 | Linguagens Disponíveis:
22 | Linguagem Atualizada!
23 | Idioma não disponível, digite %1chlang para ver os idiomas disponíveis
24 |
25 |
26 | ID do usuário: <b>%1</b> agora tem permissões para portar GSIs
27 | Para adicionar permissões, responda o usuário desejado com: <code>%1%2 allowuser</code>
28 | <b>Ports na Fila:</b> %1
<i>%2</i>
29 | Port adicionado na fila.
30 | Sem ports na fila.
31 | <b>Tipo de GSI ou URL invalida!</b>
ipos de GSIs suportadas no Android 10: %1
Tipos de GSIs suportadas no Android 11: %2
Tipos de GSIs suportadas no Android S: %3
32 | A pasta da ferramenta ErfanGSIs não existe.
33 | Algo está errado, cheque se você está usando a tool do ErfanGSIs atualizada.
34 | Bip bop... Algo de errado não está certo, o processo de fazer GSI falhou, cheque se tem algo errado.
35 | Pronto! A GSI <b>%1</b> foi feita com sucesso por <a href="tg://user?id=%2">%3</a>, você pode ver mais sobre essa GSI com este <a href="https://t.me/%4/%5">link</a>.
36 |
37 |
38 | ID do usuário: <b>%1</b> agora tem permissões para portar SGSIs
39 | Para adicionar permissões, responda o usuário desejado com: <code>%1%2 allowuser</code>
40 | <b>Ports na Fila:</b> %1
<i>%2</i>
41 | Port adicionado na fila.
42 | Sem ports na fila.
43 | <b>Tipo de SGSI ou URL invalida!</b>
Tipos de SGSIs suportadas no Android 9: %1
Tipos de GSIs suportadas no Android 10: %2
Tipos de GSIs suportadas no Android 11: %3
Tipos de GSIs suportadas no Android 12: %4
44 | A pasta da ferramenta XiaoxindadaGSIs não existe.
45 | Algo está errado, cheque se você está usando a tool do XiaoxindadaGSIs atualizada.
46 | Bip bop... Algo de errado não está certo, o processo de fazer SGSI falhou, cheque se tem algo errado.
47 |
48 |
49 | Current bot hotkey on this chat: <b>%1</b>
<b>Supported Hotkeys: %2</b>
50 | Hotkey atual deste chat: <b>%1</b>
51 | Desculpe, não é possível trocar, provavelmente essa hotkey não é compatível
52 |
53 |
54 | 📩 <b>Novo pedido de GSI recebido!</b>
55 | ❕ <b>Informação adicional</b>
56 | ❔ <b>Info do usuário</b>
57 | Olá <a href="tg://user?id=%2">%1</a> (<code>%3</code>), sua solicitação foi enviada! Espere agora.
58 | <b>• Nome:</b> <code>%1</code>
59 | <b>• Nome de usuário:</b> <code>%1</code>
60 | <b>• ID do usuário:</b> <code>%1</code>
61 | Não tem
62 | Informação não compartilhada pelo usuário.
63 | Olá <a href="tg://user?id=%2">%1</a> (<code>%3</code>), o link que você enviou parece ser inválido! Use com parâmetros http e tente novamente.
64 | Este bot não pode ser usado em outros locais!
65 | Não é possível enviar o pedido, a variável de chat privado não existe ou não tem valor.
66 | Não é possível enviar o pedido, a variável de chat público não existe ou não tem valor.
67 | As variáveis do chat (público e privado) devem ser utilizadas e implementadas na forma de Bot API, verifique se está correto.
68 |
69 |
70 | É impossível criar, pois já existe um arquivo de propriedades do SourceForge
71 | Verifique sua pasta de configuração
72 |
73 |
74 | Desculpe, o comando <code>shell</code> está bloqueado (provavelmente existe outro comando <code>shell</code> em execução).
75 | Código de retorno: <code>%1</code>, comando shell desbloqueado.
76 |
77 |
78 | Pronto.
79 |
80 |
--------------------------------------------------------------------------------
/src/main/resources/strings/strings-en.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
21 | Something went wrong, try to do the process again
22 | Only Bot Master can use this command
23 | Only Administrators can use this command
24 | Bad usage.
25 |
26 |
27 | Hey there! How are you? 👋
I was developed especially to serve as an automation for ErfanGSIs, I don't have many functions beyond that.
28 | 🔧 Source Code
29 | 📫 TrebleExperience Channel
30 |
31 |
32 | ❔<b> About</b>
<b>Bo³+t</b> is written in java and originally developed by @VegaZS
⌨<b> Developer/Maintainer of Bo³+t</b>
<a href="https://github.com/VegaBobo">VegaZS</a> - Original dev
<a href="https://github.com/Velosh">Velosh</a> - Unofficial maintainer of <b>Bo³+t</b> for Treble Experience
❕<b> Build Info</b>
<code>%1</code>
33 | ❕ Source code
34 | 🌐 Treble Channel
35 |
36 |
37 | Available Languages:
38 | Language Updated!
39 | Language not available, type %1chlang to see available languages
40 |
41 |
42 | UserID: <b>%1</b> now has port permissions
43 | To add permissions, reply to user that you wanna add permissions, by using <code>%1%2 allowuser</code>
44 | <b>Ports on Queue:</b> %1
<i>%2</i>
45 | Added to queue.
46 | No ports on queue.
47 | <b>GSI Type or URL is not valid!</b>
Supported types on Android 10: %1
Supported types on Android 11: %2
Supported types on Android 12: %3
48 | The ErfanGSIs tool folder does not exist.
49 | Something is wrong, check if you are using the updated ErfanGSIs tool.
50 | Beep bop... Something wrong isn't correct, the GSI process failed, check if something is wrong.
51 | Done! <b>%1</b> GSI was successfully built by <a href="tg://user?id=%2">%3</a>, you can see more about this GSI with this <a href="https://t.me/%4/%5">link</a>.
52 |
53 |
54 | UserID: <b>%1</b> now has port permissions
55 | To add permissions, reply to user that you wanna add permissions, by using <code>%1%2 allowuser</code>
56 | <b>Ports on Queue:</b> %1
<i>%2</i>
57 | Added to queue.
58 | No ports on queue.
59 | <b>SGSI Type or URL is not valid!</b>
Supported types on Android 9: %1
Supported types on Android 10: %2
Supported types on Android 11: %3
Supported types on Android 12: %4
60 | The XiaoxindadaSGSIs tool folder does not exist.
61 | Something is wrong, check if you are using the updated XiaoxindadaSGSIs tool.
62 | Beep bop... Something wrong isn't correct, the GSI process failed, check if something is wrong.
63 |
64 |
65 | Current bot hotkey on this chat: <code>%1</code>
<b>Supported Hotkeys: %2</b>
66 | Current hotkey now is: <b>%1</b>
67 | Sorry, it is not possible to change, this hotkey is probably not compatible
68 |
69 |
70 | 📩 <b>New GSI order received!</b>
71 | ❕ <b>Additional information</b>
72 | ❔ <b>User info</b>
73 | Hello <a href="tg://user?id=%2">%1</a> (<code>%3</code>) your request has been sent! Just wait now.
74 | <b>• Name:</b> <code>%1</code>
75 | <b>• Username:</b> <code>%1</code>
76 | <b>• User ID:</b> <code>%1</code>
77 | Don't have
78 | Information not shared by the user.
79 | Hello <a href="tg://user?id=%2">%1</a> (<code>%3</code>), the link you sent appears to be invalid! Use with http parameters and try again.
80 | This bot cannot be used in other locations!
81 | Can't send request, the private chat variable does not exist or has no value.
82 | Can't send request, the public chat variable does not exist or has no value.
83 | The chat (public and private) variables must be used and implemented in the form of Bot API, check if it is correct.
84 |
85 |
86 | It is impossible to create, as a SourceForge properties file already exists
87 | Check your config folder
88 |
89 |
90 | Sorry, the <code>shell</code> command is locked (Probably exists other shell command running).
91 | Return code: <code>%1</code>, shell command unlocked.
92 |
93 |
94 | Done.
95 |
96 |
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/owner/Chat2Shell.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.owner;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.db.PrefObj;
6 | import com.vegazsdev.bobobot.utils.Config;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.telegram.telegrambots.meta.api.objects.Update;
10 |
11 | import java.io.BufferedReader;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.io.InputStreamReader;
15 | import java.util.Objects;
16 |
17 | import static com.vegazsdev.bobobot.Main.shellStatus;
18 |
19 | /**
20 | * This class is for shell command, don't need to say anything.
21 | */
22 | @SuppressWarnings("unused")
23 | public class Chat2Shell extends Command {
24 |
25 | /**
26 | * Logger: To send warning, info & errors to terminal.
27 | */
28 | private static final Logger logger = LoggerFactory.getLogger(Chat2Shell.class);
29 |
30 | public Chat2Shell() {
31 | super("shell");
32 | }
33 |
34 | /**
35 | * Run bash command with this method.
36 | */
37 | public static String runBash(String command) {
38 | StringBuilder baseCommand = new StringBuilder();
39 | InputStream inputStream = null;
40 | InputStreamReader inputStreamReader = null;
41 | BufferedReader bufferedReader = null;
42 | try {
43 | /*
44 | * Process base
45 | */
46 | ProcessBuilder pb;
47 | pb = new ProcessBuilder("/bin/bash", "-c", command);
48 | pb.redirectErrorStream(true);
49 | Process process = pb.start();
50 |
51 | /*
52 | * Stream base
53 | */
54 | inputStream = process.getInputStream();
55 | inputStreamReader = new InputStreamReader(inputStream);
56 | bufferedReader = new BufferedReader(inputStreamReader);
57 |
58 | String line;
59 |
60 | while ((line = bufferedReader.readLine()) != null) {
61 | baseCommand.append(line);
62 | }
63 | return String.valueOf(baseCommand);
64 | } catch (Exception exception) {
65 | logger.error(exception.getMessage(), exception);
66 | } finally {
67 | if (inputStream != null) {
68 | try {
69 | inputStream.close();
70 | } catch (IOException ioException) {
71 | logger.error(ioException.getMessage(), ioException);
72 | }
73 | }
74 |
75 | if (inputStreamReader != null) {
76 | try {
77 | inputStreamReader.close();
78 | } catch (IOException ioException) {
79 | logger.error(ioException.getMessage(), ioException);
80 | }
81 | }
82 |
83 | if (bufferedReader != null) {
84 | try {
85 | bufferedReader.close();
86 | } catch (IOException ioException) {
87 | logger.error(ioException.getMessage(), ioException);
88 | }
89 | }
90 | }
91 | return null;
92 | }
93 |
94 | @SuppressWarnings("SpellCheckingInspection")
95 | @Override
96 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
97 | if (update.getMessage().getFrom().getId() == Float.parseFloat(Objects.requireNonNull(Config.getDefConfig("bot-master")))) {
98 | if (shellStatus.canRun() && !shellStatus.isRunning()) {
99 | /*
100 | * Lock status, until the Shell process ends
101 | */
102 | shellStatus.lockStatus();
103 |
104 | String msg = update.getMessage().getText().substring(7);
105 |
106 | ProcessBuilder processBuilder;
107 | processBuilder = new ProcessBuilder("/bin/bash", "-c", msg);
108 |
109 | StringBuilder fullLogs = new StringBuilder();
110 | fullLogs.append("").append(runBash("whoami")).append("").append(" (").append(runBash("uname -n")).append(")").append(" ~ ").append(update.getMessage().getText().substring(7)).append("\n");
111 |
112 | int id = bot.sendReply(fullLogs.toString(), update);
113 |
114 | InputStream inputStream = null;
115 | InputStreamReader inputStreamReader = null;
116 | BufferedReader bufferedReader = null;
117 | try {
118 | processBuilder.redirectErrorStream(true);
119 | Process process = processBuilder.start();
120 |
121 | inputStream = process.getInputStream();
122 | inputStreamReader = new InputStreamReader(inputStream);
123 | bufferedReader = new BufferedReader(inputStreamReader);
124 |
125 | String line;
126 |
127 | while ((line = bufferedReader.readLine()) != null) {
128 | fullLogs.append("").append(line).append("").append("\n");
129 | if (!(line.length() > 4096)) bot.editMessage(fullLogs.toString(), update, id);
130 | }
131 |
132 | process.waitFor();
133 | bot.sendReply2ID(prefs.getString("return_code_shell")
134 | .replace("%1", String.valueOf(process.exitValue())), id, update
135 | );
136 | shellStatus.unlockStatus();
137 | } catch (Exception e) {
138 | if (!shellStatus.canRun())
139 | shellStatus.unlockStatus();
140 |
141 | bot.sendMessageAsync(prefs.getString("something_went_wrong"), update);
142 | logger.error(e.getMessage());
143 | } finally {
144 | if (inputStream != null) {
145 | try {
146 | inputStream.close();
147 | } catch (IOException ioException) {
148 | logger.error(ioException.getMessage(), ioException);
149 | }
150 | }
151 |
152 | if (inputStreamReader != null) {
153 | try {
154 | inputStreamReader.close();
155 | } catch (IOException ioException) {
156 | logger.error(ioException.getMessage(), ioException);
157 | }
158 | }
159 |
160 | if (bufferedReader != null) {
161 | try {
162 | bufferedReader.close();
163 | } catch (IOException ioException) {
164 | logger.error(ioException.getMessage(), ioException);
165 | }
166 | }
167 | }
168 | } else {
169 | bot.sendReply(prefs.getString("cant_run_shell"), update);
170 | }
171 | }
172 | }
173 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/gsi/Request.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.gsi;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.db.PrefObj;
6 | import com.vegazsdev.bobobot.utils.Config;
7 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
8 | import org.telegram.telegrambots.meta.api.objects.Update;
9 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
10 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Objects;
15 | import java.util.concurrent.TimeUnit;
16 | import java.util.regex.Pattern;
17 |
18 | /**
19 | * That class send GSI order to private group, the order is obtained from the public group.
20 | */
21 | @SuppressWarnings({"SpellCheckingInspection", "unused"})
22 | public class Request extends Command {
23 |
24 | private String dontHaveUsername;
25 |
26 | public Request() {
27 | super("request");
28 | }
29 |
30 | @Override
31 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
32 | /*
33 | * Check if the privateChat/publicChat values is ok or nah
34 | */
35 | if (Config.getDefConfig("privateChat") == null || Objects.equals(Config.getDefConfig("privateChat"), "")) {
36 | bot.sendReply(prefs.getString("issue_with_privatechat"), update);
37 | } else if (!(Config.getDefConfig("requestChat") == null) || !Objects.equals(Config.getDefConfig("requestChat"), "")) {
38 | if (Objects.requireNonNull(Config.getDefConfig("requestChat")).startsWith("-") && Objects.requireNonNull(Config.getDefConfig("privateChat")).startsWith("-")) {
39 | // General base: message/id and some tricks
40 | String chatId = update.getMessage().getChatId().toString();
41 | String[] msgComparableRaw = update.getMessage().getText().split(" ");
42 | String msgSwitchPrefix = msgComparableRaw[0];
43 | String msgBaseRaw = update.getMessage().getText();
44 |
45 | // Request message id
46 | int id = 0;
47 |
48 | // Regex for valid link
49 | String validLink = "^(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
50 |
51 | // General base: SendMessage() and switch() things
52 | SendMessage message = new SendMessage();
53 | message.setDisableWebPagePreview(true);
54 | message.enableHtml(true);
55 | message.setChatId(chatId);
56 |
57 | if (!(update.getMessage().getFrom().getId() == Float.parseFloat(String.valueOf(777000)))) {
58 | if (Objects.requireNonNull(Config.getDefConfig("requestChat")).contains(String.valueOf(update.getMessage().getChatId()))) {
59 | if (Pattern.matches(validLink, msgComparableRaw[1])) {
60 | // Delete the message who user sent
61 | bot.deleteMessage(chatId, update.getMessage().getMessageId(), update);
62 |
63 | // Set to thank message
64 | message.setText(prefs.getString("request_done")
65 | .replace("%1", update.getMessage().getFrom().getFirstName())
66 | .replace("%2", String.valueOf(update.getMessage().getFrom().getId()))
67 | .replace("%3", String.valueOf(update.getMessage().getFrom().getId()))
68 | );
69 |
70 | message.setChatId(chatId); // Get to stock chat id
71 | id = bot.sendMessageAsyncBase(message, update);
72 |
73 | // Set dontHaveUsername
74 | dontHaveUsername = prefs.getString("dont_have");
75 |
76 | // workaround to info
77 | StringBuilder str = new StringBuilder();
78 | String addInfo = "";
79 | for (int i = 2; i < msgComparableRaw.length; i++) {
80 | str.append(msgComparableRaw[i]).append(" ");
81 | addInfo = String.valueOf(str);
82 | }
83 | if (addInfo.equals("")) addInfo = prefs.getString("info_not_shared");
84 |
85 | /*
86 | * Prepare InlineKeyboardButton
87 | */
88 | InlineKeyboardMarkup markupInline = new InlineKeyboardMarkup();
89 | List> inlineKeyboardButton = new ArrayList<>();
90 |
91 | List inlineKeyboardButtonArrayList = new ArrayList<>();
92 | InlineKeyboardButton inlineKeyboardButtonAonly = new InlineKeyboardButton();
93 | inlineKeyboardButtonAonly.setText("\uD83D\uDCE6 Firmware/ROM Link");
94 | inlineKeyboardButtonAonly.setUrl(msgComparableRaw[1]);
95 | inlineKeyboardButtonArrayList.add(inlineKeyboardButtonAonly);
96 | inlineKeyboardButton.add(inlineKeyboardButtonArrayList);
97 |
98 | /*
99 | * Finish InlineKeyboardButton setup
100 | */
101 | markupInline.setKeyboard(inlineKeyboardButton);
102 | message.setReplyMarkup(markupInline);
103 |
104 | // Initial to the message base
105 | message.setChatId(Objects.requireNonNull(Config.getDefConfig("privateChat")));
106 | message.setText(
107 | prefs.getString("gsi_order") + "\n\n"
108 | + prefs.getString("addinfo") + "\n"
109 | + "" + addInfo + ""
110 | + "\n\n"
111 | + prefs.getString("user_info") + "\n\n"
112 | + prefs.getString("first_and_last_name")
113 | .replace("%1", update.getMessage().getFrom().getFirstName() + validateLastName(update.getMessage().getFrom().getLastName())) + "\n"
114 | + prefs.getString("user_name")
115 | .replace("%1", validateUsername(update.getMessage().getFrom().getUserName())) + "\n"
116 | + prefs.getString("user_id")
117 | .replace("%1", String.valueOf(update.getMessage().getFrom().getId()))
118 | );
119 | } else {
120 | message.setText(prefs.getString("invalid_link")
121 | .replace("%1", update.getMessage().getFrom().getFirstName())
122 | .replace("%2", String.valueOf(update.getMessage().getFrom().getId()))
123 | .replace("%3", String.valueOf(update.getMessage().getFrom().getId()))
124 | );
125 |
126 | // Delete the message who user sent
127 | bot.deleteMessage(chatId, update.getMessage().getMessageId(), update);
128 | }
129 | } else {
130 | message.setText(prefs.getString("cant_be_used"));
131 | }
132 |
133 | /*
134 | * Send the message
135 | */
136 | bot.sendMessageAsyncBase(message, update);
137 |
138 | /*
139 | * Delete thanks message
140 | */
141 | try {
142 | TimeUnit.MINUTES.sleep(1);
143 | if (id != 0) bot.deleteMessage(chatId, id, update);
144 | } catch (InterruptedException e) {
145 | e.printStackTrace();
146 | }
147 | } else {
148 | bot.deleteMessage(chatId, update.getMessage().getMessageId(), update);
149 | }
150 | } else {
151 | bot.sendReply(prefs.getString("issue_with_index_chat"), update);
152 | }
153 | } else {
154 | bot.sendReply(prefs.getString("issue_with_publicchat"), update);
155 | }
156 | }
157 |
158 | // START: Workarounds for first/last name & username
159 | private String validateUsername(String username) {
160 | if (username == null || username.equals("")) {
161 | return dontHaveUsername;
162 | } else {
163 | return "@" + username;
164 | }
165 | }
166 |
167 | private String validateLastName(String lastName) {
168 | if (lastName == null || lastName.equals("")) {
169 | return "";
170 | } else {
171 | return " " + lastName;
172 | }
173 | }
174 | // END: Workarounds for first/last name & username
175 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/Main.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot;
2 |
3 | import com.google.common.reflect.ClassPath;
4 | import com.vegazsdev.bobobot.commands.owner.Chat2Shell;
5 | import com.vegazsdev.bobobot.core.bot.Bot;
6 | import com.vegazsdev.bobobot.core.bot.BuildInfo;
7 | import com.vegazsdev.bobobot.core.command.Command;
8 | import com.vegazsdev.bobobot.core.command.annotations.DisableCommand;
9 | import com.vegazsdev.bobobot.core.shell.ShellStatus;
10 | import com.vegazsdev.bobobot.db.DbThings;
11 | import com.vegazsdev.bobobot.db.PrefObj;
12 | import com.vegazsdev.bobobot.exception.BotTokenException;
13 | import com.vegazsdev.bobobot.utils.Config;
14 | import com.vegazsdev.bobobot.utils.FileTools;
15 | import com.vegazsdev.bobobot.utils.XMLs;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 | import org.telegram.telegrambots.meta.TelegramBotsApi;
19 | import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
20 |
21 | import java.io.IOException;
22 | import java.util.ArrayList;
23 | import java.util.Objects;
24 |
25 | public class Main {
26 |
27 | /**
28 | * Logger: To send warning, info & errors to terminal.
29 | */
30 | private static final Logger logger = LoggerFactory.getLogger(Main.class);
31 |
32 | /**
33 | * That variable is used to get core strings.
34 | */
35 | public static String DEF_CORE_STRINGS_XML = "core-strings.xml";
36 |
37 | /**
38 | * That variable is for shell command.
39 | */
40 | public static ShellStatus shellStatus;
41 |
42 | @SuppressWarnings({"SpellCheckingInspection", "UnstableApiUsage", "rawtypes"})
43 | public static void main(String[] args) {
44 | /*
45 | * Start-up of all
46 | */
47 | logger.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "bot_init"));
48 |
49 | /*
50 | * Check if exists props file and other things
51 | */
52 | if (!FileTools.checkFileExistsCurPath("configs/" + XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file"))) {
53 | logger.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_not_found"));
54 | new Config().createDefConfig();
55 | logger.error(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_info"));
56 | if (!FileTools.checkFileExistsCurPath("configs/allowed2port.json"))
57 | Chat2Shell.runBash("echo \"[]\" >> configs/allowed2port.json");
58 | System.exit(0);
59 | }
60 |
61 | /*
62 | * Create ArrayList (Class) to save classes, we'll use it to botsApi.registerBot()
63 | */
64 | ArrayList commandClasses = new ArrayList<>();
65 |
66 | /*
67 | * Create ClassLoader to get class name, method and other things
68 | */
69 | final ClassLoader loader = Thread.currentThread().getContextClassLoader();
70 | try {
71 | for (final ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) {
72 | if (info.getName().startsWith("com.vegazsdev.bobobot.commands")) {
73 | /*
74 | * Prepare clazz var (To get class (info var of for{}) info)
75 | */
76 | final Class> clazz = info.load();
77 |
78 | /*
79 | * Check if it is a valid command
80 | */
81 | if (clazz.getGenericSuperclass().toString().equals(String.valueOf(Command.class))) {
82 | /*
83 | * If valid: Check if it has DisableCommand annotation, if it has, say: failed to initialize
84 | * Else, add the class into commandClasses
85 | */
86 | if (clazz.isAnnotationPresent(DisableCommand.class)) {
87 | logger.warn(Objects.requireNonNull(
88 | XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "cc_failed_to_init"))
89 | .replace("%1", clazz.getSimpleName()));
90 | } else {
91 | /*
92 | * If valid, add the validated class to commandClasses
93 | */
94 | try {
95 | commandClasses.add(clazz);
96 | logger.info(Objects.requireNonNull(
97 | XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "cc_init_cmd"))
98 | .replace("%1", clazz.getSimpleName()));
99 | } catch (Exception e) {
100 | logger.error(e.getMessage());
101 | }
102 | }
103 | } else {
104 | /*
105 | * If the command does not have a superclass of the command (core) class, give a warning and ignore
106 | */
107 | logger.warn(Objects.requireNonNull(
108 | XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "cc_not_valid_command"))
109 | .replace("%1", clazz.getSimpleName()));
110 | }
111 | }
112 | }
113 | } catch (IOException e) {
114 | logger.error(e.getMessage());
115 | }
116 |
117 | /*
118 | * Check if the props is ok or no
119 | */
120 | if (((Config.getDefConfig("bot-token") != null && Objects.requireNonNull(Config.getDefConfig("bot-token")).contains(" "))
121 | || (Config.getDefConfig("bot-username") != null && Objects.requireNonNull(Config.getDefConfig("bot-username")).contains(" ")))
122 | || Objects.requireNonNull(Config.getDefConfig("bot-master")).contains(" ") || (Objects.requireNonNull(Config.getDefConfig("publicChannel")).contains(" "))) {
123 | logger.error(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "config_file_info"));
124 | System.exit(0);
125 | }
126 |
127 | /*
128 | * Create BuildInfo object, it is used in TelegramBots class to About class, just for info (you can remove it fine)
129 | */
130 | BuildInfo buildInfo = new BuildInfo(true);
131 |
132 | /*
133 | * Create ShellStatus object, is necesary to avoid multiples instances when using Shell command
134 | */
135 | shellStatus = new ShellStatus();
136 | shellStatus.unlockStatus();
137 |
138 | /*
139 | * Create Bot object
140 | */
141 | Bot bot = null;
142 | try {
143 | bot = new Bot(
144 | Objects.requireNonNull(Config.getDefConfig("bot-token")),
145 | Config.getDefConfig("bot-username"),
146 | buildInfo.getVersion());
147 | } catch (BotTokenException e) {
148 | logger.error(e.getMessage());
149 | System.exit(1);
150 | }
151 |
152 | /*
153 | * Create database if it doesn't exist
154 | */
155 | if (!FileTools.checkFileExistsCurPath("databases/prefs.db")) {
156 | DbThings.createNewDatabase("prefs.db");
157 | DbThings.createTable("prefs.db",
158 | "CREATE TABLE IF NOT EXISTS chat_prefs ("
159 | + "group_id real UNIQUE PRIMARY KEY,"
160 | + "hotkey text DEFAULT '/',"
161 | + "lang text DEFAULT 'strings-en.xml'"
162 | + ");"
163 | );
164 | }
165 |
166 | /*
167 | * Create some checks
168 | * Check if the private/public chats has own its prefs in database
169 | */
170 | if ((Config.getDefConfig("privateChat") == null || Objects.equals(Config.getDefConfig("privateChat"), "")) || (Config.getDefConfig("requestChat") == null) || !Objects.requireNonNull(Config.getDefConfig("requestChat")).startsWith("-") && !Objects.requireNonNull(Config.getDefConfig("privateChat")).startsWith("-")) {
171 | logger.info(XMLs.getFromStringsXML("strings-en.xml", "issue_with_index_chat"));
172 | } else {
173 | /*
174 | * PrefObj, chatPrefs
175 | */
176 | PrefObj chatPrefs = TelegramBot.getPrefs(Double.parseDouble(Objects.requireNonNull(Config.getDefConfig("privateChat"))));
177 |
178 | /*
179 | * Check if the database exists for private chat
180 | */
181 | if (chatPrefs == null) {
182 | logger.info("There is no database for: " + Config.getDefConfig("privateChat") + ", creating one...");
183 | new PrefObj(0, "strings-en.xml", "/");
184 | }
185 |
186 | /*
187 | * Support multiple request chats
188 | */
189 | if (Objects.requireNonNull(Config.getDefConfig("requestChat")).contains(",")) {
190 | String[] requestChats = Objects.requireNonNull(Config.getDefConfig("requestChat")).split(",");
191 | for (String requestChat : requestChats) {
192 | /*
193 | * PrefObj, chatPrefs
194 | */
195 | chatPrefs = TelegramBot.getPrefs(Double.parseDouble(requestChat));
196 | if (chatPrefs == null) {
197 | logger.info("There is no database for: " + requestChat + ", creating one...");
198 | new PrefObj(0, "strings-en.xml", "/");
199 | }
200 | }
201 | } else {
202 | chatPrefs = TelegramBot.getPrefs(Double.parseDouble(Objects.requireNonNull(Config.getDefConfig("requestChat"))));
203 |
204 | /*
205 | * Check if the database exists for request chat
206 | */
207 | if (chatPrefs == null) {
208 | logger.info("There is no database for: " + Config.getDefConfig("requestChat") + ", creating one...");
209 | new PrefObj(0, "strings-en.xml", "/");
210 | }
211 | }
212 | }
213 |
214 | /*
215 | * Time to run bot
216 | */
217 | try {
218 | TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
219 | botsApi.registerBot(new TelegramBot(bot, commandClasses));
220 | logger.info(XMLs.getFromStringsXML(DEF_CORE_STRINGS_XML, "bot_started"));
221 | } catch (Exception e) {
222 | logger.error(e.toString());
223 | }
224 | }
225 | }
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/TelegramBot.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot;
2 |
3 | import com.vegazsdev.bobobot.core.bot.Bot;
4 | import com.vegazsdev.bobobot.core.command.CommandWithClass;
5 | import com.vegazsdev.bobobot.db.DbThings;
6 | import com.vegazsdev.bobobot.db.PrefObj;
7 | import com.vegazsdev.bobobot.utils.FileTools;
8 | import com.vegazsdev.bobobot.utils.XMLs;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 | import org.telegram.telegrambots.bots.TelegramLongPollingBot;
12 | import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatMember;
13 | import org.telegram.telegrambots.meta.api.methods.groupadministration.LeaveChat;
14 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
15 | import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage;
16 | import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText;
17 | import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMember;
18 | import org.telegram.telegrambots.meta.api.objects.Update;
19 | import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
20 |
21 | import java.lang.reflect.Method;
22 | import java.util.ArrayList;
23 | import java.util.Objects;
24 | import java.util.concurrent.ExecutionException;
25 |
26 | @SuppressWarnings("rawtypes")
27 | public class TelegramBot extends TelegramLongPollingBot {
28 |
29 | private static final Logger logger = LoggerFactory.getLogger(TelegramBot.class);
30 |
31 | private final Bot bot;
32 | private PrefObj chatPrefs;
33 | private ArrayList commandClasses;
34 |
35 | TelegramBot(Bot bot, ArrayList commandClasses) {
36 | this.bot = bot;
37 | this.commandClasses = commandClasses;
38 | }
39 |
40 | public TelegramBot(Bot bot) {
41 | this.bot = bot;
42 | }
43 |
44 | public static PrefObj getPrefs(double chatId) {
45 | PrefObj prefObj = DbThings.selectIntoPrefsTable(chatId);
46 | if (prefObj == null) {
47 | DbThings.insertIntoPrefsTable(chatId);
48 | }
49 | return prefObj;
50 | }
51 |
52 | @Override
53 | public void onUpdateReceived(Update update) {
54 | /*
55 | * Avoid hotkey problem
56 | */
57 | if (!FileTools.checkFileExistsCurPath("databases/prefs.db")) {
58 | DbThings.createNewDatabase("prefs.db");
59 | DbThings.createTable("prefs.db",
60 | "CREATE TABLE IF NOT EXISTS chat_prefs ("
61 | + "group_id real UNIQUE PRIMARY KEY,"
62 | + "hotkey text DEFAULT '/',"
63 | + "lang text DEFAULT 'strings-en.xml'"
64 | + ");"
65 | );
66 | }
67 |
68 | if (update.getMessage() != null) {
69 | /*
70 | * PrefObj, chatPrefs
71 | */
72 | chatPrefs = getPrefs(Double.parseDouble(Objects.requireNonNull(update.getMessage().getChatId().toString())));
73 |
74 | /*
75 | * Check if exists that chat in our db
76 | */
77 | if (chatPrefs == null) {
78 | try {
79 | chatPrefs = new PrefObj(0, "strings-en.xml", "/");
80 | } catch (Exception exception) {
81 | logger.error(exception.getMessage());
82 | }
83 | }
84 |
85 | /*
86 | * Create thread to run commands (it can run without thread)
87 | */
88 | new Thread(new Runnable() {
89 | private TelegramBot tBot;
90 |
91 | /*
92 | * Create TelegramBot object using init()
93 | */
94 | Runnable init(TelegramBot tBot) {
95 | this.tBot = tBot;
96 | return this;
97 | }
98 |
99 | /*
100 | * Check conditional, command & other things
101 | */
102 | @Override
103 | public void run() {
104 | if (update.hasMessage() && update.getMessage().getText() != null
105 | && !update.getMessage().getText().equals("")
106 | && Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "possible_hotkeys"))
107 | .indexOf(update.getMessage().getText().charAt(0)) >= 0) {
108 |
109 | String msg = update.getMessage().getText();
110 | long usrId = update.getMessage().getFrom().getId();
111 |
112 | /*
113 | * It is ok to run and send command
114 | */
115 | if (chatPrefs.getHotkey() != null && msg.startsWith(Objects.requireNonNull(chatPrefs.getHotkey()))) {
116 | for (CommandWithClass commandWithClass : getActiveCommandsAsCmdObject()) {
117 | String adjustCommand = msg.replace(Objects.requireNonNull(chatPrefs.getHotkey()), "");
118 |
119 | if (adjustCommand.contains(" ")) {
120 | adjustCommand = adjustCommand.split(" ")[0];
121 | }
122 |
123 | if (commandWithClass.getAlias().equals(adjustCommand)) {
124 | try {
125 | logger.info(Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "command_ok"))
126 | .replace("%1", update.getMessage().getFrom().getFirstName() + " (" + usrId + ")")
127 | .replace("%2", adjustCommand));
128 | runMethod(commandWithClass.getClazz(), update, tBot, chatPrefs);
129 | } catch (Exception e) {
130 | logger.error(Objects.requireNonNull(XMLs.getFromStringsXML(Main.DEF_CORE_STRINGS_XML, "command_failure"))
131 | .replace("%1", commandWithClass.getAlias())
132 | .replace("%2", e.getMessage()), e);
133 | }
134 | }
135 | }
136 | }
137 | }
138 | }
139 | }.init(this)).start();
140 | }
141 | }
142 |
143 | public void sendMessageAsync(String msg, Update update) {
144 | /*
145 | * Prepare SendMessage base
146 | */
147 | SendMessage sendMessage = new SendMessage();
148 | sendMessage.setText(msg);
149 | sendMessage.setChatId(String.valueOf(update.getMessage().getChatId()));
150 | sendMessage.enableMarkdown(true);
151 | sendMessage.disableWebPagePreview();
152 |
153 | /*
154 | * Execute executeAsync() method
155 | */
156 | try {
157 | executeAsync(sendMessage).get().getMessageId();
158 | } catch (TelegramApiException | ExecutionException | InterruptedException exception) {
159 | logger.error(exception.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
160 | }
161 | }
162 |
163 | public int sendMessageAsyncBase(SendMessage sendMessage, Update update) {
164 | /*
165 | * Execute executeAsync() method & use existent SendMessage object
166 | */
167 | try {
168 | return executeAsync(sendMessage).get().getMessageId();
169 | } catch (TelegramApiException | ExecutionException | InterruptedException exception) {
170 | logger.error(exception.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
171 | }
172 | return 0;
173 | }
174 |
175 | public void deleteMessage(String chatID, Integer messageID, Update update) {
176 | /*
177 | * Prepare DeleteMessage base
178 | */
179 | DeleteMessage deleteMessage = new DeleteMessage();
180 | deleteMessage.setMessageId(messageID);
181 | deleteMessage.setChatId(chatID);
182 |
183 | /*
184 | * Execute executeAsync() method
185 | */
186 | try {
187 | executeAsync(deleteMessage);
188 | } catch (TelegramApiException telegramApiException) {
189 | logger.error(telegramApiException.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
190 | }
191 | }
192 |
193 | public int sendReply(String msg, Update update) {
194 | /*
195 | * Prepare SendMessage base
196 | */
197 | SendMessage sendMessage = new SendMessage();
198 | sendMessage.setText(msg);
199 | sendMessage.setChatId(String.valueOf(update.getMessage().getChatId()));
200 | sendMessage.enableHtml(true);
201 | sendMessage.setReplyToMessageId(update.getMessage().getMessageId());
202 | sendMessage.disableWebPagePreview();
203 |
204 | /*
205 | * Execute executeAsync() method
206 | */
207 | try {
208 | return executeAsync(sendMessage).get().getMessageId();
209 | } catch (TelegramApiException | ExecutionException | InterruptedException exception) {
210 | logger.error(exception.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
211 | }
212 | return 0;
213 | }
214 |
215 | public void sendReply2ID(String msg, int id, Update update) {
216 | /*
217 | * Prepare SendMessage base
218 | */
219 | SendMessage sendMessage = new SendMessage();
220 | sendMessage.setText(msg);
221 | sendMessage.setChatId(String.valueOf(update.getMessage().getChatId()));
222 | sendMessage.enableHtml(true);
223 | sendMessage.setReplyToMessageId(id);
224 | sendMessage.disableWebPagePreview();
225 |
226 | /*
227 | * Execute executeAsync() method
228 | */
229 | try {
230 | executeAsync(sendMessage).get().getMessageId();
231 | } catch (TelegramApiException | ExecutionException | InterruptedException exception) {
232 | logger.error(exception.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
233 | }
234 | }
235 |
236 | public void editMessage(String msg, Update update, int id) {
237 | /*
238 | * Prepare EditMessageText base
239 | */
240 | EditMessageText editMessageText = new EditMessageText();
241 | editMessageText.setText(msg);
242 | editMessageText.setChatId(String.valueOf(update.getMessage().getChatId()));
243 | editMessageText.setMessageId(id);
244 | editMessageText.enableHtml(true);
245 |
246 | /*
247 | * Execute executeAsync() method
248 | */
249 | try {
250 | executeAsync(editMessageText);
251 | } catch (TelegramApiException telegramApiException) {
252 | logger.error(telegramApiException.getMessage() + " (CID: " + update.getMessage().getChat().getId() + " | UID: " + update.getMessage().getFrom().getId() + ")");
253 | }
254 | }
255 |
256 | public boolean isPM(String userID, String chatID) {
257 | return !chatID.equals(userID);
258 | }
259 |
260 | public boolean isAdmin(String userID, String chatID) {
261 | if (userID.equals(chatID)) {
262 | /*
263 | * https://github.com/TrebleExperience/Bot3/commit/0f31e973edecce5ea25a92a6b3b841aaae1b333c
264 | */
265 | return false;
266 | } else {
267 | try {
268 | /*
269 | * Create GetChatMember() object to get info of the user
270 | */
271 | GetChatMember getChatMember = new GetChatMember();
272 | getChatMember.setChatId(chatID);
273 | getChatMember.setUserId(Long.valueOf(userID));
274 |
275 | /*
276 | * Execute GetChatMember() (to get info) using ChatMember().execute()
277 | */
278 | ChatMember chatMember = execute(getChatMember);
279 |
280 | /*
281 | * If executed fine, we'll be able to check status
282 | */
283 | return switch (chatMember.getStatus()) {
284 | case "administrator", "creator" -> true;
285 | default -> false;
286 | };
287 | } catch (Exception exception) {
288 | logger.error(exception.getMessage() + " (CID: " + chatID + " | UID: " + userID + ")");
289 | return false;
290 | }
291 | }
292 | }
293 |
294 | public boolean leaveChat(String chatID) {
295 | /*
296 | * Prepare LeaveChat base
297 | */
298 | LeaveChat leaveChat = new LeaveChat();
299 | leaveChat.setChatId(chatID);
300 |
301 | /*
302 | * Execute executeAsync() method
303 | */
304 | try {
305 | return executeAsync(leaveChat).thenApply(response -> /* Just a workaround */ response.toString().equals("true")).get();
306 | } catch (TelegramApiException | ExecutionException | InterruptedException telegramApiException) {
307 | logger.error(telegramApiException.getMessage() + " (CID to leave: " + chatID + ")");
308 | return false;
309 | }
310 | }
311 |
312 | private void runMethod(Class aClass, Update update, TelegramBot tBot, PrefObj prefs) {
313 | try {
314 | Object instance = ((Class>) aClass).getDeclaredConstructor().newInstance();
315 | Method method = ((Class>) aClass).getDeclaredMethod("botReply", Update.class, TelegramBot.class, PrefObj.class);
316 | method.invoke(instance, update, tBot, prefs);
317 | } catch (Exception e) {
318 | logger.error(e.getMessage());
319 | }
320 | }
321 |
322 | public ArrayList getActiveCommandsAsCmdObject() {
323 | ArrayList allCommandsArObj = new ArrayList<>();
324 | for (Class clazz : commandClasses) {
325 | try {
326 | Object instance = ((Class>) clazz).getDeclaredConstructor().newInstance();
327 | Method methodAli = ((Class>) clazz).getSuperclass().getDeclaredMethod("getAlias");
328 | String alias = (String) methodAli.invoke(instance);
329 | CommandWithClass c = new CommandWithClass(clazz, alias);
330 | allCommandsArObj.add(c);
331 | } catch (Exception e) {
332 | logger.error(e.getMessage());
333 | }
334 | }
335 | return allCommandsArObj;
336 | }
337 |
338 | @Override
339 | public String getBotUsername() {
340 | return bot.getUsername();
341 | }
342 |
343 | @Override
344 | public String getBotToken() {
345 | return bot.getToken();
346 | }
347 |
348 | public String getVersionID() {
349 | return bot.getVersionID();
350 | }
351 | }
352 |
--------------------------------------------------------------------------------
/src/main/java/com/vegazsdev/bobobot/commands/gsi/ErfanGSIs.java:
--------------------------------------------------------------------------------
1 | package com.vegazsdev.bobobot.commands.gsi;
2 |
3 | import com.vegazsdev.bobobot.TelegramBot;
4 | import com.vegazsdev.bobobot.core.command.Command;
5 | import com.vegazsdev.bobobot.core.gsi.GSICmdObj;
6 | import com.vegazsdev.bobobot.core.gsi.SourceForgeUpload;
7 | import com.vegazsdev.bobobot.db.PrefObj;
8 | import com.vegazsdev.bobobot.utils.Config;
9 | import com.vegazsdev.bobobot.utils.FileTools;
10 | import com.vegazsdev.bobobot.utils.JSONs;
11 | import okio.BufferedSource;
12 | import okio.Okio;
13 | import okio.Source;
14 | import org.apache.commons.io.FileUtils;
15 | import org.apache.commons.io.FilenameUtils;
16 | import org.apache.commons.lang3.ArrayUtils;
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 | import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
20 | import org.telegram.telegrambots.meta.api.objects.Update;
21 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
22 | import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
23 |
24 | import java.io.*;
25 | import java.nio.file.Files;
26 | import java.nio.file.Path;
27 | import java.nio.file.Paths;
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.List;
31 | import java.util.Objects;
32 | import java.util.concurrent.atomic.AtomicReference;
33 | import java.util.stream.Stream;
34 |
35 | /**
36 | * Main command of the bot specialized in making GSI (Erfan tool).
37 | *
38 | * This class consists of doing GSI using the Erfan Abdi tool, named ErfanGSIs.
39 | *
40 | * Some methods:
41 | *
42 | * - {@link #isCommandValid(Update)}
43 | * - {@link #try2AvoidCodeInjection(String)}
44 | * - {@link #isGSIValid(String)}
45 | * - {@link #createGSI(GSICmdObj, TelegramBot)}
46 | * - {@link #userHasPortPermissions(String)}
47 | * - {@link #getModelOfOutput(String)}
48 | * - {@link #addPortPerm(String)}
49 | *
50 | *
51 | */
52 | @SuppressWarnings({"SpellCheckingInspection", "unused"})
53 | public class ErfanGSIs extends Command {
54 |
55 | /**
56 | * Logger: To send warning, info & errors to terminal.
57 | */
58 | private static final Logger logger = LoggerFactory.getLogger(ErfanGSIs.class);
59 |
60 | /**
61 | * Main variables to GSI process.
62 | */
63 | private static final ArrayList queue = new ArrayList<>();
64 | private static boolean isPorting = false;
65 | private final String toolPath = "ErfanGSIs/";
66 |
67 | /**
68 | * Get supported versions from ErfanGSIs tool.
69 | */
70 | private final File[] supportedGSIs10 = new File(toolPath + "roms/10").listFiles(File::isDirectory);
71 | private final File[] supportedGSIs11 = new File(toolPath + "roms/11").listFiles(File::isDirectory);
72 | private final File[] supportedGSIs12 = new File(toolPath + "roms/12").listFiles(File::isDirectory);
73 |
74 | /**
75 | * Some workarounds.
76 | */
77 | private String messageError = "";
78 | private String infoGSI = "";
79 | private String noticeGSI = "";
80 | private String developerNoticeGSI = "";
81 |
82 | /**
83 | * Create dummy PrefObj
84 | */
85 | private PrefObj prefObj;
86 |
87 | public ErfanGSIs() {
88 | super("url2gsi");
89 | }
90 |
91 | private static String[] listFilesForFolder(final File folder) {
92 | StringBuilder paths = new StringBuilder();
93 | for (final File fileEntry : Objects.requireNonNull(folder.listFiles())) {
94 | if (fileEntry.isDirectory()) {
95 | listFilesForFolder(fileEntry);
96 | } else {
97 | if (fileEntry.getName().contains(".img")) {
98 | paths.append(fileEntry.getAbsolutePath()).append("\n");
99 | }
100 | }
101 | }
102 | return paths.toString().split("\n");
103 | }
104 |
105 | @Override
106 | public void botReply(Update update, TelegramBot bot, PrefObj prefs) {
107 | String[] msgComparableRaw = update.getMessage().getText().split(" ");
108 | if (update.getMessage().getText().contains(" ")) {
109 | switch (msgComparableRaw[1]) {
110 | case "allowuser" -> {
111 | if (update.getMessage().getReplyToMessage() != null) {
112 | String userid = update.getMessage().getReplyToMessage().getFrom().getId().toString();
113 | if (addPortPerm(userid)) {
114 | bot.sendReply(prefs.getString("egsi_allowed").replace("%1", userid), update);
115 | }
116 | } else {
117 | bot.sendReply(prefs.getString("egsi_allow_by_reply").replace("%1", prefs.getHotkey())
118 | .replace("%2", this.getAlias()), update);
119 | }
120 | }
121 | case "queue" -> {
122 | if (!queue.isEmpty()) {
123 | StringBuilder v = new StringBuilder();
124 | for (int i = 0; i < queue.size(); i++) {
125 | v.append("#").append(i + 1).append(": ").append(queue.get(i).getGsi()).append("\n");
126 | }
127 | bot.sendReply(prefs.getString("egsi_current_queue")
128 | .replace("%2", v.toString())
129 | .replace("%1", String.valueOf(queue.size())), update);
130 | } else {
131 | bot.sendReply(prefs.getString("egsi_no_ports_queue"), update);
132 | }
133 | }
134 | case "cancel" -> {
135 | if (isPorting) {
136 | ProcessBuilder pb;
137 | pb = new ProcessBuilder("/bin/bash", "-c", "kill -TERM -- -$(ps ax | grep url2GSI.sh | grep -v grep | awk '{print $1;}')");
138 | try {
139 | pb.start();
140 | } catch (IOException ignored) {}
141 |
142 | if (FileTools.checkIfFolderExists(toolPath + "output")) {
143 | if (FileTools.deleteFolder(toolPath + "output")) {
144 | logger.info("Output folder deleted");
145 | }
146 | }
147 | } else {
148 | bot.sendReply(prefs.getString("egsi_no_ports_queue"), update);
149 | }
150 | }
151 | case "list", "roms", "gsis" -> sendSupportedROMs(update, bot, prefs);
152 | default -> {
153 | messageError = prefs.getString("egsi_fail_to_build_gsi");
154 | prefObj = prefs;
155 | if (userHasPortPermissions(update.getMessage().getFrom().getId().toString())) {
156 | if (!FileTools.checkIfFolderExists("ErfanGSIs")) {
157 | bot.sendReply(prefs.getString("egsi_dont_exists_tool_folder"), update);
158 | } else {
159 | GSICmdObj gsiCommand = isCommandValid(update);
160 | if (gsiCommand != null) {
161 | boolean isGSITypeValid = isGSIValid(gsiCommand.getGsi());
162 | if (isGSITypeValid) {
163 | if (!isPorting) {
164 | isPorting = true;
165 | createGSI(gsiCommand, bot);
166 | while (queue.size() != 0) {
167 | GSICmdObj portNow = queue.get(0);
168 | queue.remove(0);
169 | createGSI(portNow, bot);
170 | }
171 | isPorting = false;
172 | } else {
173 | queue.add(gsiCommand);
174 | bot.sendReply(prefs.getString("egsi_added_to_queue"), update);
175 | }
176 | } else {
177 | sendSupportedROMs(update, bot, prefs);
178 | }
179 | }
180 | }
181 | }
182 | }
183 | }
184 | } else {
185 | bot.sendReply(prefs.getString("bad_usage"), update);
186 | }
187 | }
188 |
189 | /**
190 | * Avoid shell usage on jurl2gsi command.
191 | */
192 | private String try2AvoidCodeInjection(String parameters) {
193 | try {
194 | parameters = parameters.replace("&", "")
195 | .replace("\\", "").replace(";", "").replace("<", "")
196 | .replace(">", "").replace("|", "");
197 | } catch (Exception e) {
198 | return parameters;
199 | }
200 | return parameters;
201 | }
202 |
203 | /**
204 | * Check if the args passed to jurl2gsi command is valid.
205 | */
206 | private GSICmdObj isCommandValid(Update update) {
207 | GSICmdObj gsiCmdObj = new GSICmdObj();
208 | String msg = update.getMessage().getText().replace(Config.getDefConfig("bot-hotkey") + this.getAlias() + " ", "");
209 | String[] msgComparableRaw = update.getMessage().getText().split(" "), paramComparableRaw;
210 | boolean canContinueLoop = false;
211 | String url, gsi, param;
212 |
213 | if (msgComparableRaw.length >= 3) {
214 | try {
215 | url = msg.split(" ")[1];
216 | gsiCmdObj.setUrl(url);
217 | gsi = msg.split(" ")[2];
218 | gsiCmdObj.setGsi(gsi);
219 | param = msg.replace(msgComparableRaw[0], "").replace(msgComparableRaw[1], "").replace(msgComparableRaw[2], "").trim();
220 | param = try2AvoidCodeInjection(param);
221 | paramComparableRaw = param.split(" ");
222 |
223 | if (param.contains("-nv")) {
224 | noticeGSI = "GSI Notice\nThis GSI requires the vendor to have the same version of the system, check this.\n\n";
225 | } else {
226 | noticeGSI = "GSI Notice\nNo information for this GSI was reported. Read the Developer Notice and check if there is any additional information directly from the builder.\n\n";
227 | }
228 |
229 | StringBuilder stringBuilder = new StringBuilder();
230 | for (String string : paramComparableRaw) {
231 | if (string.startsWith("-")) canContinueLoop = true;
232 | if (!string.startsWith("-")) break;
233 | if (canContinueLoop) stringBuilder.append(string).append(" ");
234 | }
235 |
236 | developerNoticeGSI = param.replace(String.valueOf(stringBuilder), "");
237 | if (developerNoticeGSI.contains(param)) developerNoticeGSI = "";
238 | if (!developerNoticeGSI.equals("")) {
239 | developerNoticeGSI =
240 | "Developer Notice\n"
241 | + param.replace(String.valueOf(stringBuilder), "")
242 | + "\n\n";
243 | } else {
244 | developerNoticeGSI =
245 | "Developer Notice\n"
246 | + "No additional information was reported by the builder, if you think this is a mistake, report it directly to the builder."
247 | + "\n\n";
248 | }
249 |
250 | param = String.valueOf(stringBuilder);
251 |
252 | gsiCmdObj.setParam(param);
253 | gsiCmdObj.setUpdate(update);
254 | return gsiCmdObj;
255 | } catch (Exception e) {
256 | logger.error(e.getMessage());
257 | return null;
258 | }
259 | } else {
260 | return null;
261 | }
262 | }
263 |
264 | /**
265 | * Check if the GSI is valid.
266 | * It checks if the tool is updated (if it has R/S support), check if the ROM exists too.
267 | */
268 | // FIX-ME
269 | private boolean isGSIValid(String gsi) {
270 | return true;
271 | }
272 |
273 | /**
274 | * Avoid users abuse, only users with port permission can use jurl2gsi command.
275 | */
276 | private boolean userHasPortPermissions(String idAsString) {
277 | if (Objects.equals(Config.getDefConfig("bot-master"), idAsString)) {
278 | return true;
279 | }
280 | String portConfigFile = "configs/allowed2port.json";
281 | return Arrays.asList(Objects.requireNonNull(JSONs.getArrayFromJSON(portConfigFile)).toArray()).contains(idAsString);
282 | }
283 |
284 | /**
285 | * Get model/codename of the device.
286 | */
287 | public String getModelOfOutput(String folder) {
288 | /*
289 | * Initialize core variables
290 | */
291 | File outputFolder = new File(folder);
292 | File file = null;
293 | String modelName = null;
294 | String buildType = null;
295 | String brand = null;
296 |
297 | /*
298 | * List the files
299 | */
300 | for (final File fileEntry : Objects.requireNonNull(outputFolder.listFiles())) {
301 | if (fileEntry.getName().endsWith(".txt") && !fileEntry.getName().contains("System-Tree")) {
302 | file = new File(String.valueOf(fileEntry));
303 | }
304 | }
305 |
306 | /*
307 | * Try to get codename
308 | */
309 | try (Source fileSource = Okio.source(Objects.requireNonNull(file));
310 | BufferedSource bufferedSource = Okio.buffer(fileSource)) {
311 |
312 | /*
313 | * Get codename
314 | */
315 | while (true) {
316 | String line = bufferedSource.readUtf8Line();
317 | if (line == null) break;
318 | if (line.startsWith("Brand")) brand = line.substring(7);
319 | if (line.startsWith("Model")) modelName = line.substring(7);
320 | if (line.startsWith("Build Type")) buildType = line.substring(12);
321 | }
322 |
323 | /*
324 | * Check if the model have special codename
325 | */
326 | if (Objects.requireNonNull(modelName).length() < 1)
327 | modelName = "Generic";
328 | else if (modelName.toLowerCase().contains("x00qd"))
329 | modelName = "Asus Zenfone 5";
330 | else if (modelName.toLowerCase().contains("qssi"))
331 | modelName = "Qualcomm Single System Image";
332 | else if (modelName.toLowerCase().contains("miatoll"))
333 | modelName = "Redmi Note 9S/Redmi Note 9 Pro/Redmi Note 9 Pro Max/POCO M2 Pro";
334 | else if (modelName.toLowerCase().contains("surya"))
335 | modelName = "Poco X3";
336 | else if (modelName.toLowerCase().contains("lavender"))
337 | modelName = "Redmi Note 7";
338 | else if (modelName.toLowerCase().contains("ginkgo"))
339 | modelName = "Redmi Note 8";
340 | else if (modelName.toLowerCase().contains("raphael"))
341 | modelName = "Mi 9T Pro";
342 | else if (modelName.toLowerCase().contains("mainline"))
343 | modelName = "AOSP/Pixel (Mainline) Device";
344 | else if (modelName.toLowerCase().contains("sm6250"))
345 | modelName = "Atoll device";
346 | else if (modelName.toLowerCase().contains("msi"))
347 | modelName = "Motorola System Image";
348 | else if (modelName.toLowerCase().contains("mssi"))
349 | modelName = "MIUI Single System Image";
350 | else if (modelName.equals("a30"))
351 | modelName = "Samsung Galaxy A30";
352 | else if (modelName.equals("a20"))
353 | modelName = "Samsung Galaxy A20";
354 | else if (modelName.equals("a10"))
355 | modelName = "Samsung Galaxy A10";
356 | else if (modelName.equals("LE2123"))
357 | modelName = "OnePlus 9 Pro";
358 | else if (modelName.toLowerCase().contains("apollo"))
359 | modelName = "Mi 10T/Mi 10T Pro/Redmi K30S";
360 | else if (modelName.toLowerCase().contains("gauguin"))
361 | modelName = "Mi 10T Lite/Mi 10i 5G/Redmi Note 9 5G";
362 | else if (modelName.equals(" "))
363 | modelName = "Generic";
364 |
365 | if (Objects.requireNonNull(brand).equals("google") || Objects.requireNonNull(brand).equals("Android")) {
366 | if (modelName.equals("AOSP/Pixel (Mainline) Device")) {
367 | switch (Objects.requireNonNull(buildType)) {
368 | // only Pixel which have QP, RP & SP (Q, R & S)
369 | case "raven-user", "aosp_raven-user", "aosp_raven-userdebug", "aosp_raven-eng"
370 | -> modelName = "Google Pixel 6 Pro";
371 | case "oriel-user", "aosp_oriel-user", "aosp_oriel-userdebug", "aosp_oriel-eng"
372 | -> modelName = "Google Pixel 6";
373 | case "barbet-user", "aosp_barbet-user", "aosp_barbet-userdebug", "aosp_barbet-eng"
374 | -> modelName = "Google Pixel 5a";
375 | case "redfin-user", "aosp_redfin-user", "aosp_redfin-userdebug", "aosp_redfin-eng"
376 | -> modelName = "Google Pixel 5";
377 | case "bramble-user", "aosp_bramble-user", "aosp_bramble-userdebug", "aosp_bramble-eng"
378 | -> modelName = "Google Pixel 4a 5G";
379 | case "sunfish-user", "aosp_sunfish-user", "aosp_sunfish-userdebug", "aosp_sunfish-eng"
380 | -> modelName = "Google Pixel 4a";
381 | case "coral-user", "aosp_coral-user", "aosp_coral-userdebug", "aosp_coral-eng"
382 | -> modelName = "Google Pixel 4 XL";
383 | case "flame-user", "aosp_flame-user", "aosp_flame-userdebug", "aosp_flame-eng"
384 | -> modelName = "Google Pixel 4";
385 | case "bonito-user", "aosp_bonito-user", "aosp_bonito-userdebug", "aosp_bonito-eng"
386 | -> modelName = "Google Pixel 3a XL";
387 | case "sargo-user", "aosp_sargo-user", "aosp_sargo-userdebug", "aosp_sargo-eng"
388 | -> modelName = "Google Pixel 3a";
389 | case "crosshatch-user", "aosp_crosshatch-user", "aosp_crosshatch-userdebug", "aosp_crosshatch-eng"
390 | -> modelName = "Google Pixel 3 XL";
391 | case "blueline-user", "aosp_blueline-user", "aosp_blueline-userdebug", "aosp_blueline-eng"
392 | -> modelName = "Google Pixel 3";
393 | case "taimen-user", "aosp_taimen-user", "aosp_taimen-userdebug", "aosp_taimen-eng"
394 | -> modelName = "Google Pixel 2 XL";
395 | case "walleye-user", "aosp_walleye-user", "aosp_walleye-userdebug", "aosp_walleye-eng"
396 | -> modelName = "Google Pixel 2";
397 | case "marlin-user", "aosp_marlin-user", "aosp_marlin-userdebug", "aosp_marlin-eng"
398 | -> modelName = "Google Pixel XL";
399 | case "sailfish-user", "aosp_sailfish-user", "aosp_sailfish-userdebug", "aosp_sailfish-eng"
400 | -> modelName = "Google Pixel";
401 | default
402 | -> modelName = "Google Pixel (?)";
403 | }
404 | }
405 | } else if (Objects.requireNonNull(brand).equals("Redmi")) {
406 | if (modelName.equals("Atoll device")) {
407 | modelName = "Redmi Note 9S/Redmi Note 9 Pro/Redmi Note 9 Pro Max/POCO M2 Pro";
408 | }
409 | }
410 |
411 | /*
412 | * First check
413 | */
414 | String stringToCheck = modelName.toLowerCase();
415 | boolean testPass = false;
416 |
417 | char[] characterSearch = {
418 | 'q', 'w', 'e', 'r', 't', 'y', 'u',
419 | 'i', 'o', 'p', 'a', 's', 'd', 'f',
420 | 'g', 'h', 'j', 'k', 'l', 'z', 'x',
421 | 'c', 'v', 'b', 'n', 'm'
422 | };
423 |
424 | for (int i = 0; i < stringToCheck.length(); i++) {
425 | char character = stringToCheck.charAt(i);
426 | for (char search : characterSearch) {
427 | if (search == character) {
428 | testPass = true;
429 | break;
430 | }
431 | }
432 | }
433 |
434 | if (!testPass) return "Generic";
435 | return modelName;
436 | } catch (IOException e) {
437 | return "Generic";
438 | }
439 | }
440 |
441 | /**
442 | * Create a GSI with one method.
443 | */
444 | private void createGSI(GSICmdObj gsiCmdObj, TelegramBot bot) {
445 | /*
446 | * Variables to bash
447 | */
448 | ProcessBuilder pb;
449 | InputStream inputStream = null;
450 | InputStreamReader inputStreamReader = null;
451 | BufferedReader bufferedReader = null;
452 |
453 | /*
454 | * Pre-final GSI process variables
455 | */
456 | boolean success = false;
457 | Update update = gsiCmdObj.getUpdate();
458 | StringBuilder fullLogs = new StringBuilder();
459 | String builder = update.getMessage().getFrom().getFirstName();
460 | Long builderID = update.getMessage().getFrom().getId();
461 |
462 | /*
463 | * Start the GSI process
464 | */
465 | pb = new ProcessBuilder("/bin/bash", "-c",
466 | "cd " + toolPath + " ; ./url2GSI.sh '" + gsiCmdObj.getUrl() + "' " + gsiCmdObj.getGsi() + " " + gsiCmdObj.getParam()
467 | );
468 | fullLogs.append("-> Starting process...");
469 |
470 | /*
471 | * Send the message, it's GSI time!
472 | */
473 | int id = bot.sendReply(fullLogs.toString(), update);
474 |
475 | /*
476 | * GSI build process
477 | */
478 | try {
479 | /*
480 | * Start process
481 | */
482 | pb.redirectErrorStream(true);
483 | Process process = pb.start();
484 |
485 | /*
486 | * Prepare in/output log
487 | */
488 | inputStream = process.getInputStream();
489 | inputStreamReader = new InputStreamReader(inputStream);
490 | bufferedReader = new BufferedReader(inputStreamReader);
491 |
492 | /*
493 | * Some variables (to get buffer output using readLine())
494 | */
495 | String line;
496 |
497 | while ((line = bufferedReader.readLine()) != null) {
498 | line = "" + line + "";
499 | fullLogs.append("\n").append(line);
500 | bot.editMessage(fullLogs.toString(), update, id);
501 | }
502 |
503 | process.waitFor();
504 | if (process.exitValue() == 0) {
505 | success = true;
506 | }
507 |
508 | /*
509 | * If the GSI got true boolean, it will create gzip, upload, prepare message and send it to channel/group
510 | */
511 | if (success) {
512 | bot.editMessage(fullLogs.toString(), update, id);
513 |
514 | /*
515 | * Get files inside ErfanGSIs/output
516 | */
517 | String[] gzipFiles = listFilesForFolder(new File("ErfanGSIs" + "/output"));
518 |
519 | /*
520 | * Gzip the files
521 | */
522 | for (String gzipFile : gzipFiles) {
523 | fullLogs.append("\n").append("-> Gzipping: ").append(gzipFile).append(".gz").append("");
524 | bot.editMessage(fullLogs.toString(), update, id);
525 | new FileTools().gzipFile(gzipFile, gzipFile + ".gz");
526 | }
527 |
528 | /*
529 | * Create ArrayList to save A/B, Aonly & vendorOverlays files
530 | */
531 | ArrayList arr = new ArrayList<>();
532 |
533 | /*
534 | * A/B, Aonly & vendorOverlay Atomic variables
535 | */
536 | AtomicReference aonly = new AtomicReference<>("");
537 | AtomicReference ab = new AtomicReference<>("");
538 | AtomicReference vendorOverlays = new AtomicReference<>("");
539 | AtomicReference odmOverlays = new AtomicReference<>("");
540 |
541 | /*
542 | * Try to get files inside ErfanGSIs/output and set into correct variable (ex: A/B image to A/B variable)
543 | */
544 | try (Stream paths = Files.walk(Paths.get("ErfanGSIs/output/"))) {
545 | paths
546 | .filter(Files::isRegularFile)
547 | .forEach(fileName -> {
548 | if (fileName.toString().endsWith(".gz") || fileName.toString().endsWith("System-Tree.txt")) {
549 | arr.add(fileName.toString());
550 | if (fileName.toString().contains("Aonly")) {
551 | aonly.set(FilenameUtils.getBaseName(fileName.toString()) + "." + FilenameUtils.getExtension(fileName.toString()));
552 | } else if (fileName.toString().contains("AB")) {
553 | ab.set(FilenameUtils.getBaseName(fileName.toString()) + "." + FilenameUtils.getExtension(fileName.toString()));
554 | } else if (fileName.toString().contains("VendorOverlays")) {
555 | vendorOverlays.set(FilenameUtils.getBaseName(fileName.toString()) + "." + FilenameUtils.getExtension(fileName.toString()));
556 | } else if (fileName.toString().contains("ODMOverlays")) {
557 | odmOverlays.set(FilenameUtils.getBaseName(fileName.toString()) + "." + FilenameUtils.getExtension(fileName.toString()));
558 | }
559 | }
560 | if (fileName.toString().contains(".txt") && !fileName.toString().contains("System-Tree")) {
561 | infoGSI = fileName.toString();
562 | }
563 | });
564 | } catch (IOException e) {
565 | logger.error(e.getMessage());
566 | }
567 |
568 | /*
569 | * Now say the bot will upload files to SourceForge
570 | */
571 | fullLogs.append("\n").append("-> Uploading compressed files from GSI to SourceForge...");
572 | bot.editMessage(fullLogs.toString(), update, id);
573 |
574 | /*
575 | * SourceForge upload time
576 | */
577 | String re = new SourceForgeUpload().uploadGsi(arr, gsiCmdObj.getGsi());
578 | re = re + "/";
579 |
580 | /*
581 | * Check the GSI name has special name, like this:
582 | * !jurl2gsi Generic:StatiXOS-Nuclear
583 | * The name of this ROM is 'StatiXOS Nuclear' (without quotes), the '-' (char) will be the replacement char, to be used as a space
584 | */
585 | if (gsiCmdObj.getGsi().contains(":")) {
586 | gsiCmdObj.setGsi(gsiCmdObj.getGsi().split(":")[1]);
587 | gsiCmdObj.setGsi(gsiCmdObj.getGsi().replace("-", " "));
588 | gsiCmdObj.setGsi(gsiCmdObj.getGsi().replace("_", " "));
589 | }
590 |
591 | /*
592 | * Prepare GSI message
593 | */
594 | SendMessage sendMessage = new SendMessage();
595 | sendMessage.setDisableWebPagePreview(true);
596 | sendMessage.enableHtml(true);
597 |
598 | /*
599 | * Prepare InlineKeyboardButton
600 | */
601 | InlineKeyboardMarkup markupInline = new InlineKeyboardMarkup();
602 | List> rowsInline = new ArrayList<>();
603 |
604 | if (!aonly.toString().trim().equals("")) {
605 | List rowInline2 = new ArrayList<>();
606 | InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton();
607 | inlineKeyboardButton.setText("Aonly Download");
608 | inlineKeyboardButton.setUrl("https://sourceforge.net/projects/" + SourceForgeSetup.getSfConf("bot-sf-proj") + "/files/" + re + aonly);
609 | rowInline2.add(inlineKeyboardButton);
610 | rowsInline.add(rowInline2);
611 | }
612 |
613 | if (!ab.toString().trim().equals("")) {
614 | List rowInline = new ArrayList<>();
615 | InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton();
616 | inlineKeyboardButton.setText("A/B Download");
617 | inlineKeyboardButton.setUrl("https://sourceforge.net/projects/" + SourceForgeSetup.getSfConf("bot-sf-proj") + "/files/" + re + ab);
618 | rowInline.add(inlineKeyboardButton);
619 | rowsInline.add(rowInline);
620 | }
621 |
622 | if (!vendorOverlays.toString().trim().equals("")) {
623 | List rowInline = new ArrayList<>();
624 | InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton();
625 | inlineKeyboardButton.setText("Vendor Overlays Download");
626 | inlineKeyboardButton.setUrl("https://sourceforge.net/projects/" + SourceForgeSetup.getSfConf("bot-sf-proj") + "/files/" + re + vendorOverlays);
627 | rowInline.add(inlineKeyboardButton);
628 | rowsInline.add(rowInline);
629 | }
630 |
631 | if (!odmOverlays.toString().trim().equals("")) {
632 | List rowInline = new ArrayList<>();
633 | InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton();
634 | inlineKeyboardButton.setText("ODM Overlays Download");
635 | inlineKeyboardButton.setUrl("https://sourceforge.net/projects/" + SourceForgeSetup.getSfConf("bot-sf-proj") + "/files/" + re + odmOverlays);
636 | rowInline.add(inlineKeyboardButton);
637 | rowsInline.add(rowInline);
638 | }
639 |
640 | /*
641 | * Finish InlineKeyboardButton setup
642 | */
643 | markupInline.setKeyboard(rowsInline);
644 | sendMessage.setReplyMarkup(markupInline);
645 |
646 | /*
647 | * Info of GSI image
648 | */
649 | String descGSI = "" + new FileTools().readFile(infoGSI).trim();
650 |
651 | /*
652 | * Prepare message id
653 | */
654 | int idGSI;
655 |
656 | /*
657 | * Send GSI message
658 | */
659 | sendMessage.setText("Requested " + gsiCmdObj.getGsi() + " | GSI + SGSI"
660 | + "\nFrom " + getModelOfOutput(toolPath + "output")
661 | + "\nBuilt by " + builder + ""
662 | + "\n\nInformation\n" + descGSI
663 | + "\n\n"
664 | + noticeGSI
665 | + developerNoticeGSI
666 | + "Credits" + "\n"
667 | + "Erfan Abdi" + " | "
668 | + "Xiaoxindada" + " | "
669 | + "Husson" + " | "
670 | + "Bo³+t" + "\n\n"
671 | + "Treble Experience" + "\n"
672 | + "Channel | Chat | GitHub"
673 | );
674 | sendMessage.setChatId(Objects.requireNonNull(SourceForgeSetup.getSfConf("bot-announcement-id")));
675 | idGSI = bot.sendMessageAsyncBase(sendMessage, update);
676 |
677 | fullLogs.append("\n").append("-> Finished!");
678 | bot.editMessage(fullLogs.toString(), update, id);
679 |
680 | /*
681 | * Reply kthx
682 | */
683 | if (idGSI != 0) bot.sendReply(prefObj.getString("egsi_done")
684 | .replace("%1", gsiCmdObj.getGsi())
685 | .replace("%2", String.valueOf(builderID))
686 | .replace("%3", builder)
687 | .replace("%4", Objects.requireNonNull(Config.getDefConfig("publicChannel")))
688 | .replace("%5", String.valueOf(idGSI)), update);
689 |
690 | /*
691 | * Delete output/input folder with two codes (The first seems not worked so to make sure, use other code for it)
692 | */
693 | FileUtils.deleteDirectory(new File(toolPath + "output"));
694 | if (FileTools.checkIfFolderExists(toolPath + "output")) {
695 | if (FileTools.deleteFolder(toolPath + "output")) {
696 | logger.info("Output folder deleted");
697 | }
698 | }
699 |
700 | FileUtils.deleteDirectory(new File(toolPath + "input"));
701 | if (FileTools.checkIfFolderExists(toolPath + "input")) {
702 | if (FileTools.deleteFolder(toolPath + "input")) {
703 | logger.info("Input folder deleted");
704 | }
705 | }
706 |
707 | /*
708 | * Cleanup variables
709 | */
710 | ab.set(null);
711 | aonly.set(null);
712 | vendorOverlays.set(null);
713 | odmOverlays.set(null);
714 | infoGSI = null;
715 | developerNoticeGSI = null;
716 | arr.clear();
717 | gsiCmdObj.clean();
718 | } else {
719 | bot.sendReply(messageError, update);
720 | }
721 | } catch (Exception ex) {
722 | bot.sendReply(messageError, update);
723 | } finally {
724 | if (inputStream != null) {
725 | try {
726 | inputStream.close();
727 | } catch (IOException ioException) {
728 | logger.error(ioException.getMessage());
729 | }
730 | }
731 |
732 | if (inputStreamReader != null) {
733 | try {
734 | inputStreamReader.close();
735 | } catch (IOException ioException) {
736 | logger.error(ioException.getMessage());
737 | }
738 | }
739 |
740 | if (bufferedReader != null) {
741 | try {
742 | bufferedReader.close();
743 | } catch (IOException ioException) {
744 | logger.error(ioException.getMessage());
745 | }
746 | }
747 | }
748 | }
749 |
750 | /**
751 | * Add port permission using user id.
752 | */
753 | @SuppressWarnings({"rawtypes", "unchecked"})
754 | private boolean addPortPerm(String id) {
755 | try {
756 | if (FileTools.checkFileExistsCurPath("configs/allowed2port.json")) {
757 | ArrayList arrayList = JSONs.getArrayFromJSON("configs/allowed2port.json");
758 | if (arrayList != null) {
759 | arrayList.add(id);
760 | }
761 | JSONs.writeArrayToJSON(arrayList, "configs/allowed2port.json");
762 | } else {
763 | ArrayList arrayList = new ArrayList<>();
764 | arrayList.add(id);
765 | JSONs.writeArrayToJSON(arrayList, "configs/allowed2port.json");
766 | }
767 | return true;
768 | } catch (Exception e) {
769 | logger.error(e.getMessage(), e);
770 | return false;
771 | }
772 | }
773 |
774 | /**
775 | * Common message for list/jurl2gsi args
776 | */
777 | public void sendSupportedROMs(Update update, TelegramBot bot, PrefObj prefs) {
778 | File[] supportedGSIsPandQ = ArrayUtils.addAll(supportedGSIs10);
779 | File[] supportedGSIsRandS = ArrayUtils.addAll(supportedGSIs11, supportedGSIs12);
780 |
781 | if (supportedGSIsPandQ != null && supportedGSIsRandS != null) {
782 | bot.sendReply(prefs.getString("egsi_supported_types")
783 | .replace("%1",
784 | Arrays.toString(supportedGSIs10).replace(toolPath + "roms/10/", "")
785 | .replace("[", "")
786 | .replace("]", ""))
787 | .replace("%2",
788 | Arrays.toString(supportedGSIs11).replace(toolPath + "roms/11/", "")
789 | .replace("[", "")
790 | .replace("]", ""))
791 | .replace("%3",
792 | Arrays.toString(supportedGSIs12).replace(toolPath + "roms/12/", "")
793 | .replace("[", "")
794 | .replace("]", "")), update);
795 | } else {
796 | bot.sendReply(prefs.getString("egsi_something_is_wrong"), update);
797 | }
798 | }
799 | }
800 |
--------------------------------------------------------------------------------