diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Account.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Account.kt new file mode 100644 index 0000000..c976c59 --- /dev/null +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Account.kt @@ -0,0 +1,5 @@ +package de.fabianonline.telegram_backup + +class Account(val file_base: String, val phone_number: String) { + +} \ No newline at end of file diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt index 7e15981..5fcc149 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt @@ -31,7 +31,11 @@ import org.slf4j.Logger class CommandLineController { private val storage: ApiStorage - var app: TelegramApp + val app: TelegramApp + val target_dir: String + val file_base: String + val phone_number: String + val account_file_base: String private fun getLine(): String { if (System.console() != null) { @@ -53,25 +57,45 @@ class CommandLineController { init { logger.info("CommandLineController started. App version {}", Config.APP_APPVER) - this.printHeader() + printHeader() if (CommandLineOptions.cmd_version) { System.exit(0) } else if (CommandLineOptions.cmd_help) { - this.show_help() + show_help() System.exit(0) } else if (CommandLineOptions.cmd_license) { - CommandLineController.show_license() + show_license() System.exit(0) } - this.setupFileBase() + + // Setup file_base + logger.debug("Target dir from Config: {}", Config.TARGET_DIR.anonymize()) + target_dir = CommandLineOptions.val_target ?: Config.TARGET_DIR + logger.debug("Target dir after options: {}", target_dir) + println("Base directory for files: ${target_dir.anonymize()}") + if (CommandLineOptions.cmd_list_accounts) { - this.list_accounts() + Utils.print_accounts(target_dir) System.exit(0) } + + logger.trace("Checking accounts") + try { + phone_number = selectAccount(target_dir, CommandLineOptions.val_account) + } catch(e: AccountNotFoundException) { + show_error("The specified account could not be found.") + } catch(e: NoAccountsException) { + println("No accounts found. Starting login process...") + CommandLineOptions.cmd_login = true + } + + file_base = target_dir + File.separatorChar + account_to_use + + account = Account(file_base, account_to_use) + logger.debug("Initializing TelegramApp") app = TelegramApp(Config.APP_ID, Config.APP_HASH, Config.APP_MODEL, Config.APP_SYSVER, Config.APP_APPVER, Config.APP_LANG) - logger.trace("Checking accounts") - val account = this.selectAccount() + logger.debug("CommandLineOptions.cmd_login: {}", CommandLineOptions.cmd_login) logger.info("Initializing ApiStorage") storage = ApiStorage(account) @@ -196,44 +220,22 @@ class CommandLineController { println() } - private fun setupFileBase() { - logger.debug("Target dir at startup: {}", Config.FILE_BASE.anonymize()) - if (CommandLineOptions.val_target != null) { - Config.FILE_BASE = CommandLineOptions.val_target!! - } - logger.debug("Target dir after options: {}", Config.FILE_BASE.anonymize()) - System.out.println("Base directory for files: " + Config.FILE_BASE.anonymize()) - } - - private fun selectAccount(): String? { - var account = "none" - val accounts = Utils.getAccounts() - if (CommandLineOptions.cmd_login) { - logger.debug("Login requested, doing nothing.") - // do nothing - } else if (CommandLineOptions.val_account != null) { - logger.debug("Account requested: {}", CommandLineOptions.val_account!!.anonymize()) + private fun selectAccount(file_base: String, requested_account: String?): String { + val found_account: String? + val accounts = Utils.getAccounts(file_base) + if (requested_account != null) { + logger.debug("Account requested: {}", requested_account.anonymize()) logger.trace("Checking accounts for match.") - var found = false - for (acc in accounts) { - logger.trace("Checking {}", acc.anonymize()) - if (acc == CommandLineOptions.val_account) { - found = true - logger.trace("Matches.") - break - } + found_account = accounts.find{it == requested_account} + + if (found_account == null) { + throw AccountNotFoundException() } - if (!found) { - show_error("Couldn't find account '" + CommandLineOptions.val_account!!.anonymize() + "'. Maybe you want to use '--login' first?") - } - account = CommandLineOptions.val_account!! } else if (accounts.size == 0) { - println("No accounts found. Starting login process...") - CommandLineOptions.cmd_login = true - return null + throw NoAccountsException() } else if (accounts.size == 1) { - account = accounts.firstElement() - System.out.println("Using only available account: " + account.anonymize()) + found_account = accounts.firstElement() + println("Using only available account: " + account.anonymize()) } else { show_error(("You didn't specify which account to use.\n" + "Use '--account ' to use account .\n" + @@ -241,8 +243,8 @@ class CommandLineController { System.exit(1) } logger.debug("accounts.size: {}", accounts.size) - logger.debug("account: {}", account.anonymize()) - return account + logger.debug("account: {}", found_account.anonymize()) + return found_account!! } private fun cmd_stats() { @@ -315,20 +317,6 @@ class CommandLineController { println(" --list-channels Lists all channels together with their ID") } - private fun list_accounts() { - println("List of available accounts:") - val accounts = Utils.getAccounts() - if (accounts.size > 0) { - for (str in accounts) { - System.out.println(" " + str.anonymize()) - } - println("Use '--account ' to use one of those accounts.") - } else { - println("NO ACCOUNTS FOUND") - println("Use '--login' to login to a telegram account.") - } - } - companion object { private val logger = LoggerFactory.getLogger(CommandLineController::class.java) @@ -342,4 +330,7 @@ class CommandLineController { println("TODO: Print the GPL.") } } + + class AccountNotFoundException() : Exception("Account not found") {} + class NoAccountsException() : Exception("No accounts found") {} } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt index 8be0bc0..26bba17 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt @@ -29,7 +29,7 @@ object Config { val APP_APPVER: String val APP_LANG = "en" - var FILE_BASE = System.getProperty("user.home") + File.separatorChar + ".telegram_backup" + var TARGET_DIR = System.getProperty("user.home") + File.separatorChar + ".telegram_backup" val FILE_NAME_AUTH_KEY = "auth.dat" val FILE_NAME_DC = "dc.dat" val FILE_NAME_DB = "database.sqlite" diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt index cef1f85..4d5adeb 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt @@ -51,6 +51,33 @@ class Database private constructor(var client: TelegramClient) { private var conn: Connection? = null private var stmt: Statement? = null var user_manager: UserManager + + init { + private val logger = LoggerFactory.getLogger(Database::class.java) + + this.user_manager = UserManager.getInstance() + System.out.println("Opening database...") + try { + Class.forName("org.sqlite.JDBC") + } catch (e: ClassNotFoundException) { + CommandLineController.show_error("Could not load jdbc-sqlite class.") + } + + val path = "jdbc:sqlite:${user_manager.fileBase}${Config.FILE_NAME_DB}" + + try { + conn = DriverManager.getConnection(path) + stmt = conn!!.createStatement() + } catch (e: SQLException) { + CommandLineController.show_error("Could not connect to SQLITE database.") + } + + // Run updates + val updates = DatabaseUpdates(conn!!, this) + updates.doUpdates() + + System.out.println("Database is ready.") + } fun getTopMessageID(): Int { try { @@ -69,34 +96,32 @@ class Database private constructor(var client: TelegramClient) { fun getChatCount(): Int = queryInt("SELECT COUNT(*) FROM chats") fun getUserCount(): Int = queryInt("SELECT COUNT(*) FROM users") - val missingIDs: LinkedList - get() { - try { - val missing = LinkedList() - val max = getTopMessageID() - val rs = stmt!!.executeQuery("SELECT message_id FROM messages WHERE source_type IN ('group', 'dialog') ORDER BY id") - rs.next() - var id = rs.getInt(1) - for (i in 1..max) { - if (i == id) { - rs.next() - if (rs.isClosed()) { - id = Integer.MAX_VALUE - } else { - id = rs.getInt(1) - } - } else if (i < id) { - missing.add(i) + fun getMissingIDs: LinkedList() + try { + val missing = LinkedList() + val max = getTopMessageID() + val rs = stmt!!.executeQuery("SELECT message_id FROM messages WHERE source_type IN ('group', 'dialog') ORDER BY id") + rs.next() + var id = rs.getInt(1) + for (i in 1..max) { + if (i == id) { + rs.next() + if (rs.isClosed()) { + id = Integer.MAX_VALUE + } else { + id = rs.getInt(1) } + } else if (i < id) { + missing.add(i) } - rs.close() - return missing - } catch (e: SQLException) { - e.printStackTrace() - throw RuntimeException("Could not get list of ids.") } - + rs.close() + return missing + } catch (e: SQLException) { + e.printStackTrace() + throw RuntimeException("Could not get list of ids.") } + } fun getMessagesWithMedia(): LinkedList { try { @@ -207,30 +232,7 @@ class Database private constructor(var client: TelegramClient) { } - init { - this.user_manager = UserManager.getInstance() - System.out.println("Opening database...") - try { - Class.forName("org.sqlite.JDBC") - } catch (e: ClassNotFoundException) { - CommandLineController.show_error("Could not load jdbc-sqlite class.") - } - - val path = "jdbc:sqlite:${user_manager.fileBase}${Config.FILE_NAME_DB}" - - try { - conn = DriverManager.getConnection(path) - stmt = conn!!.createStatement() - } catch (e: SQLException) { - CommandLineController.show_error("Could not connect to SQLITE database.") - } - - // Run updates - val updates = DatabaseUpdates(conn!!, this) - updates.doUpdates() - - System.out.println("Database is ready.") - } + fun backupDatabase(currentVersion: Int) { val filename = String.format(Config.FILE_NAME_DB_BACKUP, currentVersion) @@ -550,7 +552,9 @@ class Database private constructor(var client: TelegramClient) { fun fetchSetting(key: String): String? { val rs = stmt!!.executeQuery("SELECT value FROM settings WHERE key='${key}'") rs.next() - return rs.getString(1) + val result = rs.getString(1) + rs.close() + return result } fun saveSetting(key: String, value: String?) { @@ -562,6 +566,7 @@ class Database private constructor(var client: TelegramClient) { ps.setString(2, value) } ps.execute() + ps.close() } fun getIdsFromQuery(query: String): LinkedList { @@ -787,18 +792,6 @@ class Database private constructor(var client: TelegramClient) { } companion object { - private val logger = LoggerFactory.getLogger(Database::class.java) - internal var instance: Database? = null - - fun init(c: TelegramClient) { - instance = Database(c) - } - - fun getInstance(): Database { - if (instance == null) throw RuntimeException("Database is not initialized but getInstance() was called.") - return instance!! - } - fun bytesToTLMessage(b: ByteArray?): TLMessage? { try { if (b == null) return null diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt index 3b99292..00de1d9 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt @@ -34,9 +34,23 @@ object Utils { private val logger = LoggerFactory.getLogger(Utils::class.java) as Logger - fun getAccounts(): Vector { + fun print_accounts(file_base: String) { + println("List of available accounts:") + val accounts = getAccounts(file_base) + if (accounts.size > 0) { + for (str in accounts) { + println(" " + str.anonymize()) + } + println("Use '--account ' to use one of those accounts.") + } else { + println("NO ACCOUNTS FOUND") + println("Use '--login' to login to a telegram account.") + } + } + + fun getAccounts(file_base: String): Vector { val accounts = Vector() - val folder = File(Config.FILE_BASE) + val folder = File(file_base) val files = folder.listFiles() if (files != null) for (f in files) {