diff --git a/.gitignore b/.gitignore index 1f29647..b58488e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ .gradle/ auth.dat dc.dat +data/ diff --git a/build.gradle b/build.gradle index c227b16..45adfc8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' apply plugin: 'application' -mainClassName= 'de.fabianonline.telegram_backup.Main' +mainClassName= 'de.fabianonline.telegram_backup.CommandLineRunner' repositories { mavenCentral() @@ -12,6 +12,7 @@ repositories { dependencies { compile 'com.github.badoualy:kotlogram:0.0.6' + compile 'org.xerial:sqlite-jdbc:3.8.11.2' } run { diff --git a/src/main/java/de/fabianonline/telegram_backup/ApiStorage.java b/src/main/java/de/fabianonline/telegram_backup/ApiStorage.java index 44ddf38..84955f4 100644 --- a/src/main/java/de/fabianonline/telegram_backup/ApiStorage.java +++ b/src/main/java/de/fabianonline/telegram_backup/ApiStorage.java @@ -11,55 +11,108 @@ import java.io.FileNotFoundException; import java.io.IOException; class ApiStorage implements TelegramApiStorage { - public void saveAuthKey(AuthKey authKey) { - try { - FileUtils.writeByteArrayToFile(Config.FILE_AUTH_KEY, authKey.getKey()); - } catch (IOException e) { - e.printStackTrace(); + private String prefix = null; + private boolean do_save = false; + private AuthKey auth_key = null; + private DataCenter dc = null; + private File file_auth_key = null; + private File file_dc = null; + + public ApiStorage(String prefix) { + this.setPrefix(prefix); + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + this.do_save = (this.prefix!=null); + if (this.do_save) { + String base = Config.FILE_BASE + + File.separatorChar + + this.prefix + + File.separatorChar; + this.file_auth_key = new File(base + Config.FILE_NAME_AUTH_KEY); + this.file_dc = new File(base + Config.FILE_NAME_DC); + this._saveAuthKey(); + this._saveDc(); + } else { + this.file_auth_key = null; + this.file_dc = null; + } + } + + public void saveAuthKey(AuthKey authKey) { + this.auth_key = authKey; + this._saveAuthKey(); + } + + private void _saveAuthKey() { + if (this.do_save && this.auth_key!=null) { + try { + FileUtils.writeByteArrayToFile(this.file_auth_key, this.auth_key.getKey()); + } catch (IOException e) { + e.printStackTrace(); + } } } public AuthKey loadAuthKey() { - try { - return new AuthKey(FileUtils.readFileToByteArray(Config.FILE_AUTH_KEY)); - } catch (IOException e) { - if (!(e instanceof FileNotFoundException)) e.printStackTrace(); + if (this.auth_key != null) return this.auth_key; + if (this.file_auth_key != null) { + try { + return new AuthKey(FileUtils.readFileToByteArray(this.file_auth_key)); + } catch (IOException e) { + if (!(e instanceof FileNotFoundException)) e.printStackTrace(); + } } return null; } public void saveDc(DataCenter dc) { - try { - FileUtils.write(Config.FILE_DC, dc.toString()); - } catch (IOException e) { - e.printStackTrace(); + this.dc = dc; + this._saveDc(); + } + + private void _saveDc() { + if (this.do_save && this.dc != null) { + try { + FileUtils.write(this.file_dc, this.dc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } } } public DataCenter loadDc() { - try { - String[] infos = FileUtils.readFileToString(Config.FILE_DC).split(":"); - return new DataCenter(infos[0], Integer.parseInt(infos[1])); - } catch (IOException e) { - if (!(e instanceof FileNotFoundException)) e.printStackTrace(); + if (this.dc != null) return this.dc; + if (this.file_dc != null) { + try { + String[] infos = FileUtils.readFileToString(this.file_dc).split(":"); + return new DataCenter(infos[0], Integer.parseInt(infos[1])); + } catch (IOException e) { + if (!(e instanceof FileNotFoundException)) e.printStackTrace(); + } } return null; } public void deleteAuthKey() { - try { - FileUtils.forceDelete(Config.FILE_AUTH_KEY); - } catch (IOException e) { - e.printStackTrace(); + if (this.do_save) { + try { + FileUtils.forceDelete(this.file_auth_key); + } catch (IOException e) { + e.printStackTrace(); + } } } public void deleteDc() { - try { - FileUtils.forceDelete(Config.FILE_DC); - } catch (IOException e) { - e.printStackTrace(); + if (this.do_save) { + try { + FileUtils.forceDelete(this.file_dc); + } catch (IOException e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/de/fabianonline/telegram_backup/CommandLineController.java b/src/main/java/de/fabianonline/telegram_backup/CommandLineController.java new file mode 100644 index 0000000..d2b1acc --- /dev/null +++ b/src/main/java/de/fabianonline/telegram_backup/CommandLineController.java @@ -0,0 +1,150 @@ +package de.fabianonline.telegram_backup; + +import com.github.badoualy.telegram.api.Kotlogram; +import com.github.badoualy.telegram.api.TelegramApp; +import com.github.badoualy.telegram.api.TelegramClient; +import com.github.badoualy.telegram.tl.exception.RpcErrorException; + +import de.fabianonline.telegram_backup.Config; +import de.fabianonline.telegram_backup.ApiStorage; +import de.fabianonline.telegram_backup.UserManager; +import de.fabianonline.telegram_backup.DownloadManager; + +import java.io.File; +import java.io.IOException; +import java.util.Scanner; + +public class CommandLineController { + private ApiStorage storage; + private CommandLineOptions options; + public TelegramApp app; + public UserManager user = null; + + public CommandLineController(String[] args) { + options = new CommandLineOptions(args); + if (options.cmd_help) this.show_help(); + if (options.cmd_list_accounts) this.list_accounts(); + if (options.account==null && !options.cmd_login) { + show_error("You neither used --login nor did you give an account using --account. You need to use one of those two.\nPlease have a look at --help."); + } + + app = new TelegramApp(Config.APP_ID, Config.APP_HASH, Config.APP_MODEL, Config.APP_SYSVER, Config.APP_APPVER, Config.APP_LANG); + if (options.cmd_debug) Kotlogram.setDebugLogEnabled(true); + + if (options.account != null && !options.cmd_login) { + storage = new ApiStorage(options.account); + } else { + storage = new ApiStorage(null); + } + TelegramClient client = Kotlogram.getDefaultClient(app, storage); + + try { + user = new UserManager(client); + + if (options.cmd_login) { + System.out.println("Please enter your phone number in international format."); + System.out.println("Example: +4917077651234"); + System.out.print("> "); + String phone = new Scanner(System.in).nextLine(); + user.sendCodeToPhoneNumber(phone); + + System.out.println("Telegram sent you a code. Please enter it here."); + System.out.print("> "); + String code = new Scanner(System.in).nextLine(); + user.verifyCode(code); + + if (user.isPasswordNeeded()) { + System.out.println("We also need your account password."); + System.out.print("> "); + String pw = new Scanner(System.in).nextLine(); + user.verifyPassword(pw); + } + storage.setPrefix(user.getUser().getPhone()); + + System.out.println("Next time, please run this tool with '--account " + user.getUser().getPhone() + " to use this account."); + } + + System.out.println("You are now signed in as " + user.getUserString()); + + DownloadManager d = new DownloadManager(user); + d.downloadMessages(); + } catch (RpcErrorException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + client.close(); + } + System.out.println("----- EXIT -----"); + } + + private void show_help() { + System.out.println("Valid options are:"); + System.out.println(" --help Shows this help."); + System.out.println(" --account Use account ."); + System.out.println(" --login Login to an existing telegram account."); + System.out.println(" --debug Show (lots of) debug information."); + System.out.println(" --list-accounts List all existing accounts"); + + System.exit(0); + } + + private void list_accounts() { + System.out.println("List of available accounts:"); + int count = 0; + File folder = new File(Config.FILE_BASE); + File[] files = folder.listFiles(); + for (File f : files) { + if (f.isDirectory()) { + count++; + System.out.println(" " + f.getName()); + } + } + if (count>0) { + System.out.println("Use '--acount ' to use one of those accounts."); + } else { + System.out.println("NO ACCOUNTS FOUND"); + System.out.println("Use '--login' to login to a telegram account."); + } + System.exit(0); + } + + public static void show_error(String error) { + System.out.println("ERROR: " + error); + System.exit(1); + } + + private class CommandLineOptions { + public String account = null; + public boolean cmd_help = false; + public boolean cmd_login = false; + public boolean cmd_debug = false; + public boolean cmd_list_accounts = false; + + public CommandLineOptions(String[] args) { + String last_cmd = null; + + for (String arg : args) { + if (last_cmd != null) { + switch(last_cmd) { + case "--account": this.account=arg; break; + } + last_cmd = null; + continue; + } + + switch(arg) { + case "--account": last_cmd=arg; continue; + case "--help": this.cmd_help=true; break; + case "--login": this.cmd_login=true; break; + case "--debug": this.cmd_debug=true; break; + case "--list-accounts": this.cmd_list_accounts=true; break; + default: throw new RuntimeException("Unknown command " + arg); + } + } + if (last_cmd != null) { + CommandLineController.show_error("Command " + last_cmd + " had no parameter set."); + } + } + } +} diff --git a/src/main/java/de/fabianonline/telegram_backup/CommandLineRunner.java b/src/main/java/de/fabianonline/telegram_backup/CommandLineRunner.java new file mode 100644 index 0000000..d57ce0f --- /dev/null +++ b/src/main/java/de/fabianonline/telegram_backup/CommandLineRunner.java @@ -0,0 +1,9 @@ +package de.fabianonline.telegram_backup; + +import de.fabianonline.telegram_backup.CommandLineController; + +public class CommandLineRunner { + public static void main(String[] args) { + new CommandLineController(args); + } +} diff --git a/src/main/java/de/fabianonline/telegram_backup/Config.java b/src/main/java/de/fabianonline/telegram_backup/Config.java index 75f2666..35636f4 100644 --- a/src/main/java/de/fabianonline/telegram_backup/Config.java +++ b/src/main/java/de/fabianonline/telegram_backup/Config.java @@ -9,9 +9,10 @@ class Config { public static final String APP_SYSVER = "1.0"; public static final String APP_APPVER = "0.1"; public static final String APP_LANG = "en"; - - public static final File FILE_AUTH_KEY = new File("auth.dat"); - public static final File FILE_DC = new File("dc.dat"); - public static final File FILE_SALT = new File("salt.dat"); + + public static final String FILE_BASE = "data"; + public static final String FILE_NAME_AUTH_KEY = "auth.dat"; + public static final String FILE_NAME_DC = "dc.dat"; + public static final String FILE_NAME_DB = "database.sqlite"; } diff --git a/src/main/java/de/fabianonline/telegram_backup/Database.java b/src/main/java/de/fabianonline/telegram_backup/Database.java new file mode 100644 index 0000000..1e5e3ad --- /dev/null +++ b/src/main/java/de/fabianonline/telegram_backup/Database.java @@ -0,0 +1,97 @@ +package de.fabianonline.telegram_backup; + +import com.github.badoualy.telegram.tl.api.TLMessage; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; +import java.sql.SQLException; +import java.sql.ResultSet; +import java.io.File; + +import de.fabianonline.telegram_backup.UserManager; + + +class Database { + private Connection conn; + private Statement stmt; + + public Database(UserManager user) { + try { + Class.forName("org.sqlite.JDBC"); + } catch(ClassNotFoundException e) { + CommandLineController.show_error("Could not load jdbc-sqlite class."); + } + + String path = "jdbc:sqlite:" + + Config.FILE_BASE + + File.separatorChar + + user.getUser().getPhone() + + File.separatorChar + + Config.FILE_NAME_DB; + + try { + conn = DriverManager.getConnection(path); + stmt = conn.createStatement(); + } catch (SQLException e) { + CommandLineController.show_error("Could not connect to SQLITE database."); + } + + this.init(); + } + + private void init() { + try { + int version; + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='database_versions'"); + rs.next(); + if (rs.getInt(1)==0) { + version = 0; + } else { + rs.close(); + rs = stmt.executeQuery("SELECT MAX(version) FROM database_versions"); + rs.next(); + version = rs.getInt(1); + rs.close(); + } + System.out.println("Database version: " + version); + + if (version==0) { + stmt.executeUpdate("CREATE TABLE messages (" + + "id INTEGER PRIMARY KEY ASC, " + + "dialog_id INTEGER, " + + "to_id INTEGER, " + + "from_id INTEGER, " + + "type TEXT, " + + "text TEXT, " + + "time TEXT, " + + "has_media BOOLEAN, " + + "data BLOB)"); + stmt.executeUpdate("CREATE TABLE dialogs (" + + "id INTEGER PRIMARY KEY ASC, " + + "name TEXT, " + + "type TEXT)"); + stmt.executeUpdate("CREATE TABLE people (" + + "id INTEGER PRIMARY KEY ASC, " + + "name TEXT, " + + "username TEXT, " + + "type TEXT)"); + stmt.executeUpdate("CREATE TABLE database_versions (" + + "version INTEGER)"); + stmt.executeUpdate("INSERT INTO database_versions (version) VALUES (1)"); + version = 1; + } + } catch (SQLException e) { + System.out.println(e.getSQLState()); + e.printStackTrace(); + } + } + + public void save(TLMessage msg) { + /*BufferArrayOutputStream stream = new BufferArrayOutputStream(); + msg.serializeBody(stream); + bytes[] = stream.toByteArray(); + PreparedStatement ps = conn.prepareStatement(query); + ps.setBytes(x, bytes[]);*/ + } +} diff --git a/src/main/java/de/fabianonline/telegram_backup/DownloadManager.java b/src/main/java/de/fabianonline/telegram_backup/DownloadManager.java new file mode 100644 index 0000000..c1f78a3 --- /dev/null +++ b/src/main/java/de/fabianonline/telegram_backup/DownloadManager.java @@ -0,0 +1,18 @@ +package de.fabianonline.telegram_backup; + +import de.fabianonline.telegram_backup.UserManager; +import de.fabianonline.telegram_backup.Database; + +class DownloadManager { + UserManager user; + Database db; + + public DownloadManager(UserManager u) { + this.user = u; + this.db = new Database(u); + } + + public void downloadMessages() { + System.out.println("downloading messages... not."); + } +} diff --git a/src/main/java/de/fabianonline/telegram_backup/Main.java b/src/main/java/de/fabianonline/telegram_backup/Main.java deleted file mode 100644 index faf7f82..0000000 --- a/src/main/java/de/fabianonline/telegram_backup/Main.java +++ /dev/null @@ -1,60 +0,0 @@ -package de.fabianonline.telegram_backup; - -import com.github.badoualy.telegram.api.Kotlogram; -import com.github.badoualy.telegram.api.TelegramApp; -import com.github.badoualy.telegram.api.TelegramClient; -import com.github.badoualy.telegram.tl.exception.RpcErrorException; - -import de.fabianonline.telegram_backup.Config; -import de.fabianonline.telegram_backup.ApiStorage; -import de.fabianonline.telegram_backup.UserManager; - -import java.io.File; -import java.io.IOException; -import java.util.Scanner; - -public class Main { - public static TelegramApp app = new TelegramApp(Config.APP_ID, Config.APP_HASH, Config.APP_MODEL, Config.APP_SYSVER, Config.APP_APPVER, Config.APP_LANG); - public static UserManager user = null; - - public static void main(String[] args) { - System.out.println("Hello World"); - - Kotlogram.setDebugLogEnabled(true); - - TelegramClient client = Kotlogram.getDefaultClient(app, new ApiStorage()); - - try { - user = new UserManager(client); - - if (!user.isLoggedIn()) { - System.out.println("Please enter your phone number in international format."); - System.out.println("Example: +4917077651234"); - System.out.print("> "); - String phone = new Scanner(System.in).nextLine(); - user.sendCodeToPhoneNumber(phone); - - System.out.println("Telegram sent you a code. Please enter it here."); - System.out.print("> "); - String code = new Scanner(System.in).nextLine(); - user.verifyCode(code); - - if (user.isPasswordNeeded()) { - System.out.println("We also need your account password."); - System.out.print("> "); - String pw = new Scanner(System.in).nextLine(); - user.verifyPassword(pw); - } - } - - System.out.println("You are now signed in as " + user.getUserString()); - } catch (RpcErrorException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - client.close(); - } - System.out.println("----- EXIT -----"); - } -} diff --git a/src/main/java/de/fabianonline/telegram_backup/UserManager.java b/src/main/java/de/fabianonline/telegram_backup/UserManager.java index 21de8e5..02d1b6e 100644 --- a/src/main/java/de/fabianonline/telegram_backup/UserManager.java +++ b/src/main/java/de/fabianonline/telegram_backup/UserManager.java @@ -89,4 +89,6 @@ class UserManager { } return sb.toString(); } + + public TLUser getUser() { return this.user; } }