From f75a90936d0cd1ce508ab02c5f2046c57012958b Mon Sep 17 00:00:00 2001 From: Fabian Schlenz Date: Mon, 11 Dec 2017 12:14:25 +0100 Subject: [PATCH] Kotlin-Code is now compilable. Now let's go on to fix all those warning... --- .../telegram_backup/ApiStorage.kt | 22 ++-- .../telegram_backup/CommandLineController.kt | 112 ++++++++-------- .../CommandLineDownloadProgress.kt | 46 +++---- .../telegram_backup/CommandLineOptions.kt | 2 +- .../de/fabianonline/telegram_backup/Config.kt | 6 +- .../fabianonline/telegram_backup/Database.kt | 123 ++++++++---------- .../telegram_backup/DatabaseUpdates.kt | 38 +++--- .../telegram_backup/DownloadManager.kt | 77 +++++------ .../DownloadProgressInterface.kt | 2 +- .../telegram_backup/GUIController.kt | 22 +--- ...equestAccountGetPasswordWithCurrentSalt.kt | 7 +- .../telegram_backup/TelegramUpdateHandler.kt | 28 ++-- .../telegram_backup/UserManager.kt | 12 +- .../de/fabianonline/telegram_backup/Utils.kt | 18 ++- .../telegram_backup/exporter/HTMLExporter.kt | 26 ++-- .../AbstractMediaFileManager.kt | 23 ++-- .../mediafilemanager/DocumentFileManager.kt | 27 ++-- .../mediafilemanager/FileManagerFactory.kt | 2 +- .../mediafilemanager/GeoFileManager.kt | 23 ++-- .../mediafilemanager/PhotoFileManager.kt | 31 ++--- .../mediafilemanager/StickerFileManager.kt | 24 ++-- .../UnsupportedFileManager.kt | 41 ++---- 22 files changed, 319 insertions(+), 393 deletions(-) diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/ApiStorage.kt b/src/main/kotlin/de/fabianonline/telegram_backup/ApiStorage.kt index 151c67c..7cea7ab 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/ApiStorage.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/ApiStorage.kt @@ -27,7 +27,7 @@ import java.io.File import java.io.FileNotFoundException import java.io.IOException -internal class ApiStorage(prefix: String) : TelegramApiStorage { +internal class ApiStorage(prefix: String?) : TelegramApiStorage { private var prefix: String? = null private var do_save = false private var auth_key: AuthKey? = null @@ -39,7 +39,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { this.setPrefix(prefix) } - fun setPrefix(prefix: String) { + fun setPrefix(prefix: String?) { this.prefix = prefix this.do_save = this.prefix != null if (this.do_save) { @@ -57,7 +57,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { } } - fun saveAuthKey(authKey: AuthKey) { + override fun saveAuthKey(authKey: AuthKey) { this.auth_key = authKey this._saveAuthKey() } @@ -65,7 +65,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { private fun _saveAuthKey() { if (this.do_save && this.auth_key != null) { try { - FileUtils.writeByteArrayToFile(this.file_auth_key, this.auth_key!!.getKey()) + FileUtils.writeByteArrayToFile(this.file_auth_key, this.auth_key!!.key) } catch (e: IOException) { e.printStackTrace() } @@ -73,7 +73,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { } } - fun loadAuthKey(): AuthKey? { + override fun loadAuthKey(): AuthKey? { if (this.auth_key != null) return this.auth_key if (this.file_auth_key != null) { try { @@ -87,7 +87,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { return null } - fun saveDc(dc: DataCenter) { + override fun saveDc(dc: DataCenter) { this.dc = dc this._saveDc() } @@ -103,7 +103,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { } } - fun loadDc(): DataCenter? { + override fun loadDc(): DataCenter? { if (this.dc != null) return this.dc if (this.file_dc != null) { try { @@ -117,7 +117,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { return null } - fun deleteAuthKey() { + override fun deleteAuthKey() { if (this.do_save) { try { FileUtils.forceDelete(this.file_auth_key) @@ -128,7 +128,7 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { } } - fun deleteDc() { + override fun deleteDc() { if (this.do_save) { try { FileUtils.forceDelete(this.file_dc) @@ -139,9 +139,9 @@ internal class ApiStorage(prefix: String) : TelegramApiStorage { } } - fun saveSession(session: MTSession) {} + override fun saveSession(session: MTSession?) {} - fun loadSession(): MTSession? { + override fun loadSession(): MTSession? { return null } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt index 96e8cc9..a717273 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineController.kt @@ -30,29 +30,24 @@ import org.slf4j.Logger class CommandLineController { private val storage:ApiStorage var app:TelegramApp - private val line:String - get() { - if (System.console() != null) - { + + private fun getLine():String { + if (System.console() != null) { return System.console().readLine("> ") - } - else - { + } else { print("> ") return Scanner(System.`in`).nextLine() } } - private val password:String - get() { - if (System.console() != null) - { + + private fun getPassword():String { + if (System.console() != null) { return String(System.console().readPassword("> ")) - } - else - { - return line + } else { + return getLine() } } + init{ logger.info("CommandLineController started. App version {}", Config.APP_APPVER) this.printHeader() @@ -67,7 +62,7 @@ class CommandLineController { } else if (CommandLineOptions.cmd_license) { - this.show_license() + CommandLineController.show_license() System.exit(0) } this.setupFileBase() @@ -92,16 +87,16 @@ class CommandLineController { logger.info("Initializing UserManager") UserManager.init(client) val user = UserManager.getInstance() - if (!CommandLineOptions.cmd_login && !user.isLoggedIn()) + if (!CommandLineOptions.cmd_login && !user.loggedIn) { println("Your authorization data is invalid or missing. You will have to login with Telegram again.") CommandLineOptions.cmd_login = true } - if (account != null && user.isLoggedIn()) + if (account != null && user.loggedIn) { - if (account != "+" + user.getUser().getPhone()) + if (account != "+" + user.user!!.getPhone()) { - logger.error("Account: {}, user.getUser().getPhone(): +{}", Utils.anonymize(account), Utils.anonymize(user.getUser().getPhone())) + logger.error("Account: {}, user.user!!.getPhone(): +{}", Utils.anonymize(account), Utils.anonymize(user.user!!.getPhone())) throw RuntimeException("Account / User mismatch") } } @@ -137,7 +132,7 @@ class CommandLineController { logger.debug("CommandLineOptions.val_export: {}", CommandLineOptions.val_export) if (CommandLineOptions.val_export != null) { - if (CommandLineOptions.val_export.toLowerCase().equals("html")) + if (CommandLineOptions.val_export!!.toLowerCase().equals("html")) { (HTMLExporter()).export() System.exit(0) @@ -147,9 +142,9 @@ class CommandLineController { show_error("Unknown export format.") } } - if (user.isLoggedIn()) + if (user.loggedIn) { - System.out.println("You are logged in as " + Utils.anonymize(user.getUserString())) + System.out.println("You are logged in as " + Utils.anonymize(user.userString)) } else { @@ -202,13 +197,13 @@ class CommandLineController { logger.debug("Target dir at startup: {}", Utils.anonymize(Config.FILE_BASE)) if (CommandLineOptions.val_target != null) { - Config.FILE_BASE = CommandLineOptions.val_target + Config.FILE_BASE = CommandLineOptions.val_target!! } logger.debug("Target dir after options: {}", Utils.anonymize(Config.FILE_BASE)) System.out.println("Base directory for files: " + Utils.anonymize(Config.FILE_BASE)) } - private fun selectAccount():String { - val account:String = null + private fun selectAccount():String? { + var account = "none" val accounts = Utils.getAccounts() if (CommandLineOptions.cmd_login) { @@ -217,9 +212,9 @@ class CommandLineController { } else if (CommandLineOptions.val_account != null) { - logger.debug("Account requested: {}", Utils.anonymize(CommandLineOptions.val_account)) + logger.debug("Account requested: {}", Utils.anonymize(CommandLineOptions.val_account!!)) logger.trace("Checking accounts for match.") - val found = false + var found = false for (acc in accounts) { logger.trace("Checking {}", Utils.anonymize(acc)) @@ -232,16 +227,17 @@ class CommandLineController { } if (!found) { - show_error("Couldn't find account '" + Utils.anonymize(CommandLineOptions.val_account) + "'. Maybe you want to use '--login' first?") + show_error("Couldn't find account '" + Utils.anonymize(CommandLineOptions.val_account!!) + "'. Maybe you want to use '--login' first?") } - account = CommandLineOptions.val_account + account = CommandLineOptions.val_account!! } - else if (accounts.size() == 0) + else if (accounts.size == 0) { println("No accounts found. Starting login process...") CommandLineOptions.cmd_login = true + return null } - else if (accounts.size() == 1) + else if (accounts.size == 1) { account = accounts.firstElement() System.out.println("Using only available account: " + Utils.anonymize(account)) @@ -251,8 +247,9 @@ class CommandLineController { show_error(("You didn't specify which account to use.\n" + "Use '--account ' to use account .\n" + "Use '--list-accounts' to see all available accounts.")) + System.exit(1) } - logger.debug("accounts.size(): {}", accounts.size()) + logger.debug("accounts.size: {}", accounts.size) logger.debug("account: {}", Utils.anonymize(account)) return account } @@ -260,45 +257,48 @@ class CommandLineController { println() println("Stats:") val format = "%40s: %d%n" - System.out.format(format, "Number of accounts", Utils.getAccounts().size()) + System.out.format(format, "Number of accounts", Utils.getAccounts().size) System.out.format(format, "Number of messages", Database.getInstance().getMessageCount()) System.out.format(format, "Number of chats", Database.getInstance().getChatCount()) System.out.format(format, "Number of users", Database.getInstance().getUserCount()) System.out.format(format, "Top message ID", Database.getInstance().getTopMessageID()) println() println("Media Types:") - for (pair in Database.getInstance().getMessageMediaTypesWithCount().entrySet()) + for ((key, value) in Database.getInstance().getMessageMediaTypesWithCount()) { - System.out.format(format, pair.key, pair.value) + System.out.format(format, key, value) } println() println("Api layers of messages:") - for (pair in Database.getInstance().getMessageApiLayerWithCount().entrySet()) + for ((key, value) in Database.getInstance().getMessageApiLayerWithCount()) { - System.out.format(format, pair.key, pair.value) + System.out.format(format, key, value) } } @Throws(RpcErrorException::class, IOException::class) - private fun cmd_login(phone:String) { + private fun cmd_login(phoneToUse:String?) { val user = UserManager.getInstance() - if (phone == null) + val phone: String + if (phoneToUse == null) { println("Please enter your phone number in international format.") println("Example: +4917077651234") - phone = line - } + phone = getLine() + } else { + phone = phoneToUse + } user.sendCodeToPhoneNumber(phone) println("Telegram sent you a code. Please enter it here.") - val code = line + val code = getLine() user.verifyCode(code) - if (user.isPasswordNeeded()) + if (user.isPasswordNeeded) { println("We also need your account password. Please enter it now. It should not be printed, so it's okay if you see nothing while typing it.") - val pw = password + val pw = getPassword() user.verifyPassword(pw) } - storage.setPrefix("+" + user.getUser().getPhone()) - System.out.println("Everything seems fine. Please run this tool again with '--account +" + Utils.anonymize(user.getUser().getPhone()) + " to use this account.") + storage.setPrefix("+" + user.user!!.getPhone()) + System.out.println("Everything seems fine. Please run this tool again with '--account +" + Utils.anonymize(user.user!!.getPhone()) + " to use this account.") } private fun show_help() { println("Valid options are:") @@ -340,14 +340,14 @@ class CommandLineController { } companion object { private val logger = LoggerFactory.getLogger(CommandLineController::class.java) - fun show_error(error:String) { - logger.error(error) - println("ERROR: " + error) - System.exit(1) - } - fun show_license() { - println("TODO: Print the GPL.") - - } + + public fun show_error(error:String) { + logger.error(error) + println("ERROR: " + error) + System.exit(1) + } + fun show_license() { + println("TODO: Print the GPL.") } } +} diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineDownloadProgress.kt b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineDownloadProgress.kt index afe67b4..218962e 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineDownloadProgress.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineDownloadProgress.kt @@ -23,7 +23,7 @@ internal class CommandLineDownloadProgress : DownloadProgressInterface { private var mediaCount = 0 private var i = 0 - fun onMessageDownloadStart(count: Int, source: String?) { + override fun onMessageDownloadStart(count: Int, source: String?) { i = 0 if (source == null) { System.out.println("Downloading $count messages.") @@ -32,56 +32,56 @@ internal class CommandLineDownloadProgress : DownloadProgressInterface { } } - fun onMessageDownloaded(number: Int) { + override fun onMessageDownloaded(number: Int) { i += number - System.out.print("..." + i) + print("..." + i) } - fun onMessageDownloadFinished() { - System.out.println(" done.") + override fun onMessageDownloadFinished() { + println(" done.") } - fun onMediaDownloadStart(count: Int) { + override fun onMediaDownloadStart(count: Int) { i = 0 mediaCount = count - System.out.println("Checking and downloading media.") - System.out.println("Legend:") - System.out.println("'V' - Video 'P' - Photo 'D' - Document") - System.out.println("'S' - Sticker 'A' - Audio 'G' - Geolocation") - System.out.println("'.' - Previously downloaded file 'e' - Empty file") - System.out.println("' ' - Ignored media type (weblinks or contacts, for example)") - System.out.println("'x' - File skipped because of timeout errors") - System.out.println("" + count + " Files to check / download") + println("Checking and downloading media.") + println("Legend:") + println("'V' - Video 'P' - Photo 'D' - Document") + println("'S' - Sticker 'A' - Audio 'G' - Geolocation") + println("'.' - Previously downloaded file 'e' - Empty file") + println("' ' - Ignored media type (weblinks or contacts, for example)") + println("'x' - File skipped because of timeout errors") + println("" + count + " Files to check / download") } - fun onMediaDownloaded(fm: AbstractMediaFileManager) { - show(fm.getLetter().toUpperCase()) + override fun onMediaDownloaded(fm: AbstractMediaFileManager) { + show(fm.letter.toUpperCase()) } - fun onMediaDownloadedEmpty() { + override fun onMediaDownloadedEmpty() { show("e") } - fun onMediaAlreadyPresent(fm: AbstractMediaFileManager) { + override fun onMediaAlreadyPresent(fm: AbstractMediaFileManager) { show(".") } - fun onMediaSkipped() { + override fun onMediaSkipped() { show("x") } - fun onMediaDownloadFinished() { + override fun onMediaDownloadFinished() { showNewLine() - System.out.println("Done.") + println("Done.") } private fun show(letter: String) { - System.out.print(letter) + print(letter) i++ if (i % 100 == 0) showNewLine() } private fun showNewLine() { - System.out.println(" - $i/$mediaCount") + println(" - $i/$mediaCount") } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineOptions.kt b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineOptions.kt index 3f0eb92..5c1bace 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineOptions.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/CommandLineOptions.kt @@ -92,7 +92,7 @@ internal object CommandLineOptions { } if (last_cmd != null) { - CommandLineController.show_error("Command " + last_cmd + " had no parameter set.") + CommandLineController.show_error("Command $last_cmd had no parameter set.") } } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt index 5cdbb90..1fcd3b7 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Config.kt @@ -37,12 +37,12 @@ object Config { val FILE_FILES_BASE = "files" val FILE_STICKER_BASE = "stickers" - var DELAY_AFTER_GET_MESSAGES = 400 - var DELAY_AFTER_GET_FILE = 100 + var DELAY_AFTER_GET_MESSAGES: Long = 400 + var DELAY_AFTER_GET_FILE: Long = 100 var GET_MESSAGES_BATCH_SIZE = 200 var RENAMING_MAX_TRIES = 5 - var RENAMING_DELAY = 1000 + var RENAMING_DELAY: Long = 1000 val SECRET_GMAPS = "AIzaSyBEtUDhCQKEH6i2Mn1GAiQ9M_tLN0vxHIs" diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt index ef13532..fed8881 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Database.kt @@ -52,8 +52,7 @@ class Database private constructor(var client: TelegramClient) { private var stmt: Statement? = null var user_manager: UserManager - val topMessageID: Int - get() { + fun getTopMessageID(): Int { try { val rs = stmt!!.executeQuery("SELECT MAX(message_id) FROM messages WHERE source_type IN ('group', 'dialog')") rs.next() @@ -64,18 +63,15 @@ class Database private constructor(var client: TelegramClient) { } - val messageCount: Int - get() = queryInt("SELECT COUNT(*) FROM messages") - val chatCount: Int - get() = queryInt("SELECT COUNT(*) FROM chats") - val userCount: Int - get() = queryInt("SELECT COUNT(*) FROM users") + fun getMessageCount(): Int = queryInt("SELECT COUNT(*) FROM messages") + fun getChatCount(): Int = queryInt("SELECT COUNT(*) FROM chats") + fun getUserCount(): Int = queryInt("SELECT COUNT(*) FROM users") - val missingIDs: LinkedList + val missingIDs: LinkedList get() { try { - val missing = LinkedList() - val max = topMessageID + 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) @@ -99,10 +95,9 @@ class Database private constructor(var client: TelegramClient) { } - val messagesWithMedia: LinkedList - get() { + fun getMessagesWithMedia(): LinkedList { try { - val list = LinkedList() + val list = LinkedList() val rs = stmt!!.executeQuery("SELECT data FROM messages WHERE has_media=1") while (rs.next()) { list.add(bytesToTLMessage(rs.getBytes(1))) @@ -116,10 +111,9 @@ class Database private constructor(var client: TelegramClient) { } - val messagesFromUserCount: Int - get() { + fun getMessagesFromUserCount(): Int { try { - val rs = stmt!!.executeQuery("SELECT COUNT(*) FROM messages WHERE sender_id=" + user_manager.getUser().getId()) + val rs = stmt!!.executeQuery("SELECT COUNT(*) FROM messages WHERE sender_id=" + user_manager.user!!.getId()) rs.next() return rs.getInt(1) } catch (e: SQLException) { @@ -128,15 +122,12 @@ class Database private constructor(var client: TelegramClient) { } - val messageTypesWithCount: HashMap - get() = getMessageTypesWithCount(GlobalChat()) + fun getMessageTypesWithCount(): HashMap = getMessageTypesWithCount(GlobalChat()) - val messageMediaTypesWithCount: HashMap - get() = getMessageMediaTypesWithCount(GlobalChat()) + fun getMessageMediaTypesWithCount(): HashMap = getMessageMediaTypesWithCount(GlobalChat()) - val messageApiLayerWithCount: HashMap - get() { - val map = HashMap() + fun getMessageApiLayerWithCount(): HashMap { + val map = HashMap() try { val rs = stmt!!.executeQuery("SELECT COUNT(id), api_layer FROM messages GROUP BY api_layer ORDER BY api_layer") while (rs.next()) { @@ -149,17 +140,13 @@ class Database private constructor(var client: TelegramClient) { } catch (e: Exception) { throw RuntimeException(e) } - } - val messageAuthorsWithCount: HashMap - get() = getMessageAuthorsWithCount(GlobalChat()) + fun getMessageAuthorsWithCount(): HashMap = getMessageAuthorsWithCount(GlobalChat()) - val messageTimesMatrix: Array - get() = getMessageTimesMatrix(GlobalChat()) + fun getMessageTimesMatrix(): Array = getMessageTimesMatrix(GlobalChat()) - val encoding: String - get() { + fun getEncoding(): String { try { val rs = stmt!!.executeQuery("PRAGMA encoding") rs.next() @@ -172,8 +159,7 @@ class Database private constructor(var client: TelegramClient) { } - val listOfChatsForExport: LinkedList - get() { + fun getListOfChatsForExport(): LinkedList { val list = LinkedList() try { val rs = stmt!!.executeQuery("SELECT chats.id, chats.name, COUNT(messages.id) as c " + @@ -192,8 +178,7 @@ class Database private constructor(var client: TelegramClient) { } - val listOfDialogsForExport: LinkedList - get() { + fun getListOfDialogsForExport(): LinkedList { val list = LinkedList() try { val rs = stmt!!.executeQuery( @@ -221,9 +206,7 @@ class Database private constructor(var client: TelegramClient) { CommandLineController.show_error("Could not load jdbc-sqlite class.") } - val path = "jdbc:sqlite:" + - user_manager.getFileBase() + - Config.FILE_NAME_DB + val path = "jdbc:sqlite:${user_manager.fileBase}${Config.FILE_NAME_DB}" try { conn = DriverManager.getConnection(path) @@ -233,7 +216,7 @@ class Database private constructor(var client: TelegramClient) { } // Run updates - val updates = DatabaseUpdates(conn, this) + val updates = DatabaseUpdates(conn!!, this) updates.doUpdates() System.out.println("Database is ready.") @@ -243,8 +226,8 @@ class Database private constructor(var client: TelegramClient) { val filename = String.format(Config.FILE_NAME_DB_BACKUP, currentVersion) System.out.println(" Creating a backup of your database as " + filename) try { - val src = user_manager.getFileBase() + Config.FILE_NAME_DB - val dst = user_manager.getFileBase() + filename + val src = user_manager.fileBase + Config.FILE_NAME_DB + val dst = user_manager.fileBase + filename logger.debug("Copying {} to {}", src, dst) Files.copy( File(src).toPath(), @@ -289,7 +272,7 @@ class Database private constructor(var client: TelegramClient) { } @Synchronized - fun saveMessages(all: TLVector, api_layer: Integer) { + fun saveMessages(all: TLVector, api_layer: Int) { try { //"(id, dialog_id, from_id, from_type, text, time, has_media, data, sticker, type) " + //"VALUES " + @@ -312,16 +295,16 @@ class Database private constructor(var client: TelegramClient) { ps.setInt(4, (peer as TLPeerChat).getChatId()) } else if (peer is TLPeerUser) { var id = (peer as TLPeerUser).getUserId() - if (id == this.user_manager.getUser().getId()) { + if (id == this.user_manager.user!!.getId()) { id = msg.getFromId() } ps.setString(3, "dialog") ps.setInt(4, id) } else if (peer is TLPeerChannel) { ps.setString(3, "channel") - ps.setInt(4, (peer as TLPeerChannel).getChannelId()) + ps.setInt(4, peer.getChannelId()) } else { - throw RuntimeException("Unexpected Peer type: " + peer.getClass().getName()) + throw RuntimeException("Unexpected Peer type: " + peer.javaClass) } if (peer is TLPeerChannel) { @@ -355,9 +338,9 @@ class Database private constructor(var client: TelegramClient) { ps.setNull(12, Types.INTEGER) } else { ps.setBoolean(9, true) - ps.setString(10, f!!.getName()) - ps.setString(11, f!!.getTargetFilename()) - ps.setInt(12, f!!.getSize()) + ps.setString(10, f.name) + ps.setString(11, f.targetFilename) + ps.setInt(12, f.size) } val stream = ByteArrayOutputStream() msg.serializeBody(stream) @@ -397,7 +380,7 @@ class Database private constructor(var client: TelegramClient) { ps_insert_or_ignore.setInt(14, api_layer) ps_insert_or_ignore.addBatch() } else { - throw RuntimeException("Unexpected Message type: " + abs.getClass().getName()) + throw RuntimeException("Unexpected Message type: " + abs.javaClass) } } conn!!.setAutoCommit(false) @@ -452,7 +435,7 @@ class Database private constructor(var client: TelegramClient) { ps_insert_or_replace.setString(3, "channel") ps_insert_or_replace.addBatch() } else { - throw RuntimeException("Unexpected " + abs.getClass().getName()) + throw RuntimeException("Unexpected " + abs.javaClass) } } conn!!.setAutoCommit(false) @@ -501,7 +484,7 @@ class Database private constructor(var client: TelegramClient) { ps_insert_or_ignore.setNull(6, Types.VARCHAR) ps_insert_or_ignore.addBatch() } else { - throw RuntimeException("Unexpected " + abs.getClass().getName()) + throw RuntimeException("Unexpected " + abs.javaClass) } } conn!!.setAutoCommit(false) @@ -518,9 +501,9 @@ class Database private constructor(var client: TelegramClient) { } - fun getIdsFromQuery(query: String): LinkedList { + fun getIdsFromQuery(query: String): LinkedList { try { - val list = LinkedList() + val list = LinkedList() val rs = stmt!!.executeQuery(query) while (rs.next()) { list.add(rs.getInt(1)) @@ -533,8 +516,8 @@ class Database private constructor(var client: TelegramClient) { } - fun getMessageTypesWithCount(c: AbstractChat): HashMap { - val map = HashMap() + fun getMessageTypesWithCount(c: AbstractChat): HashMap { + val map = HashMap() try { val rs = stmt!!.executeQuery("SELECT message_type, COUNT(message_id) FROM messages WHERE " + c.query + " GROUP BY message_type") while (rs.next()) { @@ -547,8 +530,8 @@ class Database private constructor(var client: TelegramClient) { } - fun getMessageMediaTypesWithCount(c: AbstractChat): HashMap { - val map = HashMap() + fun getMessageMediaTypesWithCount(c: AbstractChat): HashMap { + val map = HashMap() try { var count = 0 val rs = stmt!!.executeQuery("SELECT media_type, COUNT(message_id) FROM messages WHERE " + c.query + " GROUP BY media_type") @@ -569,9 +552,9 @@ class Database private constructor(var client: TelegramClient) { } - fun getMessageAuthorsWithCount(c: AbstractChat): HashMap { - val map = HashMap() - val user_map = HashMap() + fun getMessageAuthorsWithCount(c: AbstractChat): HashMap { + val map = HashMap() + val user_map = HashMap() var count_others = 0 // Set a default value for 'me' to fix the charts for channels - cause I // possibly didn't send any messages there. @@ -596,7 +579,7 @@ class Database private constructor(var client: TelegramClient) { } } map.put("authors.count.others", count_others) - map.put("authors.all", user_map.entrySet()) + map.put("authors.all", user_map) return map } catch (e: Exception) { throw RuntimeException(e) @@ -621,7 +604,7 @@ class Database private constructor(var client: TelegramClient) { } - fun getMessagesForExport(c: AbstractChat): LinkedList> { + fun getMessagesForExport(c: AbstractChat): LinkedList> { try { val rs = stmt!!.executeQuery("SELECT messages.message_id as message_id, text, time*1000 as time, has_media, " + @@ -637,13 +620,13 @@ class Database private constructor(var client: TelegramClient) { val format_date = SimpleDateFormat("d MMM yy") val meta = rs.getMetaData() val columns = meta.getColumnCount() - val list = LinkedList>() + val list = LinkedList>() - var count: Integer = 0 + var count = 0 var old_date: String? = null - var old_user: Integer? = null + var old_user = 0 while (rs.next()) { - val h = HashMap(columns) + val h = HashMap(columns) for (i in 1..columns) { h.put(meta.getColumnName(i), rs.getObject(i)) } @@ -655,7 +638,7 @@ class Database private constructor(var client: TelegramClient) { if (rs.getString("media_type") != null) { h.put("media_" + rs.getString("media_type"), true) } - h.put("from_me", rs.getInt("user_id") === user_manager.getUser().getId()) + h.put("from_me", rs.getInt("user_id") === user_manager.user!!.getId()) h.put("is_new_date", !date.equals(old_date)) h.put("odd_even", if (count % 2 == 0) "even" else "odd") h.put("same_user", old_user != null && rs.getInt("user_id") === old_user) @@ -696,7 +679,7 @@ class Database private constructor(var client: TelegramClient) { var isMe: Boolean = false init { - isMe = id == user_manager.getUser().getId() + isMe = id == user_manager.user!!.getId() val s = StringBuilder() if (first_name != null) s.append(first_name + " ") if (last_name != null) s.append(last_name) @@ -711,7 +694,7 @@ class Database private constructor(var client: TelegramClient) { companion object { private val logger = LoggerFactory.getLogger(Database::class.java) - private var instance: Database? = null + internal var instance: Database? = null fun init(c: TelegramClient) { instance = Database(c) @@ -719,7 +702,7 @@ class Database private constructor(var client: TelegramClient) { fun getInstance(): Database { if (instance == null) throw RuntimeException("Database is not initialized but getInstance() was called.") - return instance + return instance!! } fun bytesToTLMessage(b: ByteArray?): TLMessage? { diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/DatabaseUpdates.kt b/src/main/kotlin/de/fabianonline/telegram_backup/DatabaseUpdates.kt index 51eeedc..3bfbddc 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/DatabaseUpdates.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/DatabaseUpdates.kt @@ -18,7 +18,7 @@ import de.fabianonline.telegram_backup.mediafilemanager.AbstractMediaFileManager class DatabaseUpdates(protected var conn: Connection, protected var db: Database) { private val maxPossibleVersion: Int - get() = updates.size() + get() = updates.size init { logger.debug("Registering Database Updates...") @@ -62,7 +62,7 @@ class DatabaseUpdates(protected var conn: Connection, protected var db: Database logger.debug("Update is necessary. {} => {}.", version, maxPossibleVersion) var backup = false for (i in version + 1..maxPossibleVersion) { - if (getUpdateToVersion(i).needsBackup()) { + if (getUpdateToVersion(i).needsBackup) { logger.debug("Update to version {} needs a backup", i) backup = true } @@ -100,9 +100,9 @@ class DatabaseUpdates(protected var conn: Connection, protected var db: Database } private fun register(d: DatabaseUpdate) { - logger.debug("Registering {} as update to version {}", d.getClass().getName(), d.version) - if (d.version != updates.size() + 1) { - throw RuntimeException("Tried to register DB update to version " + d.version + ", but would need update to version " + (updates.size() + 1)) + logger.debug("Registering {} as update to version {}", d.javaClass, d.version) + if (d.version != updates.size + 1) { + throw RuntimeException("Tried to register DB update to version ${d.version}, but would need update to version ${updates.size + 1}") } updates.add(d) } @@ -138,9 +138,7 @@ internal abstract class DatabaseUpdate(protected var conn: Connection, protected @Throws(SQLException::class) protected abstract fun _doUpdate() - fun needsBackup(): Boolean { - return false - } + open val needsBackup = false @Throws(SQLException::class) protected fun execute(sql: String) { @@ -233,9 +231,7 @@ internal class DB_Update_6(conn: Connection, db: Database) : DatabaseUpdate(conn override val version: Int get() = 6 - override fun needsBackup(): Boolean { - return true - } + override val needsBackup = true @Throws(SQLException::class) override fun _doUpdate() { @@ -269,14 +265,14 @@ internal class DB_Update_6(conn: Connection, db: Database) : DatabaseUpdate(conn val query = StringBuilder("INSERT INTO messages_new\n(") var first: Boolean first = true - for (s in mappings.keySet()) { + for (s in mappings.keys) { if (!first) query.append(", ") query.append(s) first = false } query.append(")\nSELECT \n") first = true - for (s in mappings.values()) { + for (s in mappings.values) { if (!first) query.append(", ") query.append(s) first = false @@ -289,7 +285,7 @@ internal class DB_Update_6(conn: Connection, db: Database) : DatabaseUpdate(conn val ps = conn.prepareStatement("UPDATE messages_new SET fwd_from_id=?, media_type=?, media_file=?, media_size=? WHERE id=?") while (rs.next()) { ps.setInt(5, rs.getInt(1)) - val msg = db.bytesToTLMessage(rs.getBytes(2)) + val msg = Database.bytesToTLMessage(rs.getBytes(2)) if (msg == null || msg!!.getFwdFrom() == null) { ps.setNull(1, Types.INTEGER) } else { @@ -301,9 +297,9 @@ internal class DB_Update_6(conn: Connection, db: Database) : DatabaseUpdate(conn ps.setNull(3, Types.VARCHAR) ps.setNull(4, Types.INTEGER) } else { - ps.setString(2, f!!.getName()) - ps.setString(3, f!!.getTargetFilename()) - ps.setInt(4, f!!.getSize()) + ps.setString(2, f.name) + ps.setString(3, f.targetFilename) + ps.setInt(4, f.size) } ps.addBatch() } @@ -321,9 +317,7 @@ internal class DB_Update_7(conn: Connection, db: Database) : DatabaseUpdate(conn override val version: Int get() = 7 - override fun needsBackup(): Boolean { - return true - } + override val needsBackup = true @Throws(SQLException::class) override fun _doUpdate() { @@ -337,9 +331,7 @@ internal class DB_Update_8(conn: Connection, db: Database) : DatabaseUpdate(conn override val version: Int get() = 8 - override fun needsBackup(): Boolean { - return true - } + override val needsBackup = true @Throws(SQLException::class) override fun _doUpdate() { diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/DownloadManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/DownloadManager.kt index 90f465c..0602f37 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/DownloadManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/DownloadManager.kt @@ -65,7 +65,7 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } @Throws(RpcErrorException::class, IOException::class) - fun downloadMessages(limit: Integer) { + fun downloadMessages(limit: Int?) { var completed = true do { completed = true @@ -95,7 +95,7 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } @Throws(RpcErrorException::class, IOException::class, TimeoutException::class) - fun _downloadMessages(limit: Integer?) { + fun _downloadMessages(limit: Int?) { logger.info("This is _downloadMessages with limit {}", limit) val dialog_limit = 100 logger.info("Downloading the last {} dialogs", dialog_limit) @@ -106,11 +106,11 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI 0, TLInputPeerEmpty(), dialog_limit) - logger.debug("Got {} dialogs", dialogs.getDialogs().size()) + logger.debug("Got {} dialogs", dialogs.getDialogs().size) for (d in dialogs.getDialogs()) { if (d.getTopMessage() > max_message_id && d.getPeer() !is TLPeerChannel) { - logger.trace("Updating top message id: {} => {}. Dialog type: {}", max_message_id, d.getTopMessage(), d.getPeer().getClass().getName()) + logger.trace("Updating top message id: {} => {}. Dialog type: {}", max_message_id, d.getTopMessage(), d.getPeer().javaClass) max_message_id = d.getTopMessage() } } @@ -174,10 +174,10 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI System.out.println("Processing channels and/or supergroups...") System.out.println("Please note that only channels/supergroups in the last 100 active chats are processed.") - val channel_access_hashes = HashMap() - val channel_names = HashMap() - val channels = LinkedList() - val supergroups = LinkedList() + val channel_access_hashes = HashMap() + val channel_names = HashMap() + val channels = LinkedList() + val supergroups = LinkedList() // TODO Add chat title (and other stuff?) to the database for (c in dialogs.getChats()) { @@ -224,21 +224,21 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } @Throws(RpcErrorException::class, IOException::class) - private fun downloadMessages(ids: List, channel: TLInputChannel?, source_string: String?) { - prog!!.onMessageDownloadStart(ids.size(), source_string) + private fun downloadMessages(ids: MutableList, channel: TLInputChannel?, source_string: String?) { + prog!!.onMessageDownloadStart(ids.size, source_string) logger.debug("Entering download loop") - while (ids.size() > 0) { + while (ids.size > 0) { logger.trace("Loop") val vector = TLIntVector() val download_count = Config.GET_MESSAGES_BATCH_SIZE logger.trace("download_count: {}", download_count) for (i in 0 until download_count) { - if (ids.size() === 0) break - vector.add(ids.remove(0)) + if (ids.size === 0) break + vector.add(ids.removeAt(0)) } - logger.trace("vector.size(): {}", vector.size()) - logger.trace("ids.size(): {}", ids.size()) + logger.trace("vector.size(): {}", vector.size) + logger.trace("ids.size(): {}", ids.size) var response: TLAbsMessages var tries = 0 @@ -265,12 +265,12 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } } - logger.trace("response.getMessages().size(): {}", response.getMessages().size()) - if (response.getMessages().size() !== vector.size()) { - CommandLineController.show_error("Requested " + vector.size() + " messages, but got " + response.getMessages().size() + ". That is unexpected. Quitting.") + logger.trace("response.getMessages().size(): {}", response.getMessages().size) + if (response.getMessages().size !== vector.size) { + CommandLineController.show_error("Requested ${vector.size} messages, but got ${response.getMessages().size}. That is unexpected. Quitting.") } - prog!!.onMessageDownloaded(response.getMessages().size()) + prog!!.onMessageDownloaded(response.getMessages().size) db!!.saveMessages(response.getMessages(), Kotlogram.API_LAYER) db!!.saveChats(response.getChats()) db!!.saveUsers(response.getUsers()) @@ -319,26 +319,27 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI logger.info("This is _downloadMedia") logger.info("Checking if there are messages in the DB with a too old API layer") val ids = db!!.getIdsFromQuery("SELECT id FROM messages WHERE has_media=1 AND api_layer<" + Kotlogram.API_LAYER) - if (ids.size() > 0) { - System.out.println("You have " + ids.size() + " messages in your db that need an update. Doing that now.") - logger.debug("Found {} messages", ids.size()) + if (ids.size > 0) { + System.out.println("You have ${ids.size} messages in your db that need an update. Doing that now.") + logger.debug("Found {} messages", ids.size) downloadMessages(ids, null, null) } val messages = this.db!!.getMessagesWithMedia() - logger.debug("Database returned {} messages with media", messages.size()) - prog!!.onMediaDownloadStart(messages.size()) + logger.debug("Database returned {} messages with media", messages.size) + prog!!.onMediaDownloadStart(messages.size) for (msg in messages) { - val m = FileManagerFactory.getFileManager(msg, user, client) + if (msg==null) continue + val m = FileManagerFactory.getFileManager(msg, user!!, client!!) logger.trace("message {}, {}, {}, {}, {}", msg.getId(), - msg.getMedia().getClass().getSimpleName().replace("TLMessageMedia", "…"), - m.getClass().getSimpleName(), - if (m.isEmpty()) "empty" else "non-empty", - if (m.isDownloaded()) "downloaded" else "not downloaded") - if (m.isEmpty()) { + msg.getMedia().javaClass.getSimpleName().replace("TLMessageMedia", "…"), + m!!.javaClass.getSimpleName(), + if (m.isEmpty) "empty" else "non-empty", + if (m.downloaded) "downloaded" else "not downloaded") + if (m.isEmpty) { prog!!.onMediaDownloadedEmpty() - } else if (m.isDownloaded()) { + } else if (m.downloaded) { prog!!.onMediaAlreadyPresent(m) } else { try { @@ -354,8 +355,8 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI prog!!.onMediaDownloadFinished() } - private fun makeIdList(start: Int, end: Int): List { - val a = LinkedList() + private fun makeIdList(start: Int, end: Int): MutableList { + val a = LinkedList() for (i in start..end) a.add(i) return a } @@ -378,7 +379,7 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } @Throws(RpcErrorException::class, IOException::class, TimeoutException::class) - private fun downloadFileFromDc(client: TelegramClient, target: String, loc: TLAbsInputFileLocation, dcID: Integer?, size: Int): Boolean { + private fun downloadFileFromDc(client: TelegramClient, target: String, loc: TLAbsInputFileLocation, dcID: Int, size: Int): Boolean { var fos: FileOutputStream? = null try { val temp_filename = target + ".downloading" @@ -388,7 +389,7 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI var offset = 0 if (File(temp_filename).isFile()) { logger.info("Temporary filename already exists; continuing this file") - offset = File(temp_filename).length() + offset = File(temp_filename).length() as Int if (offset >= size) { logger.warn("Temporary file size is >= the target size. Assuming corrupt file & deleting it") File(temp_filename).delete() @@ -422,8 +423,8 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } } - offset += response!!.getBytes().getData().length - logger.trace("response: {} total size: {}", response!!.getBytes().getData().length, offset) + offset += response!!.getBytes().getData().size + logger.trace("response: {} total size: {}", response!!.getBytes().getData().size, offset) fos!!.write(response!!.getBytes().getData()) fos!!.flush() @@ -432,7 +433,7 @@ class DownloadManager(internal var client: TelegramClient?, p: DownloadProgressI } catch (e: InterruptedException) { } - } while (offset < size && (response!!.getBytes().getData().length > 0 || try_again)) + } while (offset < size && (response!!.getBytes().getData().size > 0 || try_again)) fos!!.close() if (offset < size) { System.out.println("Requested file $target with $size bytes, but got only $offset bytes.") diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/DownloadProgressInterface.kt b/src/main/kotlin/de/fabianonline/telegram_backup/DownloadProgressInterface.kt index c255bf5..f86d0dd 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/DownloadProgressInterface.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/DownloadProgressInterface.kt @@ -19,7 +19,7 @@ package de.fabianonline.telegram_backup import de.fabianonline.telegram_backup.mediafilemanager.AbstractMediaFileManager interface DownloadProgressInterface { - fun onMessageDownloadStart(count: Int, source: String) + fun onMessageDownloadStart(count: Int, source: String?) fun onMessageDownloaded(number: Int) fun onMessageDownloadFinished() diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/GUIController.kt b/src/main/kotlin/de/fabianonline/telegram_backup/GUIController.kt index c41ad2e..7151266 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/GUIController.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/GUIController.kt @@ -24,7 +24,7 @@ import java.awt.event.ActionEvent import java.awt.event.ActionListener import java.util.Vector -class GUIController { +class GUIController() { init { showAccountChooserDialog() } @@ -50,24 +50,8 @@ class GUIController { accountChooser.add(vert) accountChooser.setVisible(true) accountChooser.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE) - - list.addListSelectionListener(object : ListSelectionListener() { - @Override - fun valueChanged(e: ListSelectionEvent) { - btnLogin.setEnabled(true) - } - }) - - btnAddAccount.addActionListener(object : ActionListener() { - @Override - fun actionPerformed(e: ActionEvent) { - accountChooser.setVisible(false) - accountChooser.dispose() - addAccountDialog() - } - }) - } - + } + private fun addAccountDialog() { val loginDialog = JDialog() loginDialog.setTitle("Add an account") diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/TLRequestAccountGetPasswordWithCurrentSalt.kt b/src/main/kotlin/de/fabianonline/telegram_backup/TLRequestAccountGetPasswordWithCurrentSalt.kt index 7c6f8b4..786e185 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/TLRequestAccountGetPasswordWithCurrentSalt.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/TLRequestAccountGetPasswordWithCurrentSalt.kt @@ -28,16 +28,15 @@ import com.github.badoualy.telegram.tl.StreamUtils.readTLObject class TLRequestAccountGetPasswordWithCurrentSalt : TLMethod() { private val _constructor = "account.getPassword#548a30f5" - val constructorId: Int - get() = CONSTRUCTOR_ID + override fun getConstructorId(): Int = CONSTRUCTOR_ID @Throws(IOException::class) - fun deserializeResponse(stream: InputStream, context: TLContext): TLPassword { + override fun deserializeResponse(stream: InputStream, context: TLContext): TLPassword { val response = (readTLObject(stream, context) ?: throw IOException("Unable to parse response")) as? TLPassword ?: throw IOException("Incorrect response type, expected getClass().getCanonicalName(), found response.getClass().getCanonicalName()") return response as TLPassword } - fun toString(): String { + override fun toString(): String { return _constructor } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/TelegramUpdateHandler.kt b/src/main/kotlin/de/fabianonline/telegram_backup/TelegramUpdateHandler.kt index 6ae0607..89f7113 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/TelegramUpdateHandler.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/TelegramUpdateHandler.kt @@ -37,18 +37,18 @@ internal class TelegramUpdateHandler : UpdateCallback { this.db = Database.getInstance() } - fun onUpdates(c: TelegramClient, u: TLUpdates) { + override fun onUpdates(c: TelegramClient, u: TLUpdates) { if (db == null) return - if (debug) System.out.println("onUpdates - " + u.getUpdates().size() + " Updates, " + u.getUsers().size() + " Users, " + u.getChats().size() + " Chats") + if (debug) System.out.println("onUpdates - " + u.getUpdates().size + " Updates, " + u.getUsers().size + " Users, " + u.getChats().size + " Chats") for (update in u.getUpdates()) { processUpdate(update, c) - if (debug) System.out.println(" " + update.getClass().getName()) + if (debug) System.out.println(" " + update.javaClass.getName()) } db!!.saveUsers(u.getUsers()) db!!.saveChats(u.getChats()) } - fun onUpdatesCombined(c: TelegramClient, u: TLUpdatesCombined) { + override fun onUpdatesCombined(c: TelegramClient, u: TLUpdatesCombined) { if (db == null) return if (debug) System.out.println("onUpdatesCombined") for (update in u.getUpdates()) { @@ -58,14 +58,14 @@ internal class TelegramUpdateHandler : UpdateCallback { db!!.saveChats(u.getChats()) } - fun onUpdateShort(c: TelegramClient, u: TLUpdateShort) { + override fun onUpdateShort(c: TelegramClient, u: TLUpdateShort) { if (db == null) return if (debug) System.out.println("onUpdateShort") processUpdate(u.getUpdate(), c) - if (debug) System.out.println(" " + u.getUpdate().getClass().getName()) + if (debug) System.out.println(" " + u.getUpdate().javaClass.getName()) } - fun onShortChatMessage(c: TelegramClient, m: TLUpdateShortChatMessage) { + override fun onShortChatMessage(c: TelegramClient, m: TLUpdateShortChatMessage) { if (db == null) return if (debug) System.out.println("onShortChatMessage - " + m.getMessage()) val msg = TLMessage( @@ -89,16 +89,16 @@ internal class TelegramUpdateHandler : UpdateCallback { System.out.print('.') } - fun onShortMessage(c: TelegramClient, m: TLUpdateShortMessage) { + override fun onShortMessage(c: TelegramClient, m: TLUpdateShortMessage) { if (db == null) return if (debug) System.out.println("onShortMessage - " + m.getOut() + " - " + m.getUserId() + " - " + m.getMessage()) val from_id: Int val to_id: Int if (m.getOut() === true) { - from_id = user!!.getUser().getId() + from_id = user!!.user!!.getId() to_id = m.getUserId() } else { - to_id = user!!.getUser().getId() + to_id = user!!.user!!.getId() from_id = m.getUserId() } val msg = TLMessage( @@ -122,12 +122,12 @@ internal class TelegramUpdateHandler : UpdateCallback { System.out.print('.') } - fun onShortSentMessage(c: TelegramClient, m: TLUpdateShortSentMessage) { + override fun onShortSentMessage(c: TelegramClient, m: TLUpdateShortSentMessage) { if (db == null) return System.out.println("onShortSentMessage") } - fun onUpdateTooLong(c: TelegramClient) { + override fun onUpdateTooLong(c: TelegramClient) { if (db == null) return System.out.println("onUpdateTooLong") } @@ -140,8 +140,8 @@ internal class TelegramUpdateHandler : UpdateCallback { db!!.saveMessages(vector, Kotlogram.API_LAYER) System.out.print('.') if (abs_msg is TLMessage) { - val fm = FileManagerFactory.getFileManager(abs_msg as TLMessage, user, client) - if (fm != null && !fm!!.isEmpty() && !fm!!.isDownloaded()) { + val fm = FileManagerFactory.getFileManager(abs_msg as TLMessage, user!!, client) + if (fm != null && !fm!!.isEmpty && !fm!!.downloaded) { try { fm!!.download() } catch (e: Exception) { diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/UserManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/UserManager.kt index 8fdd2ed..f2571f4 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/UserManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/UserManager.kt @@ -39,13 +39,13 @@ private constructor(c: TelegramClient) { var user: TLUser? = null var phone: String? = null private var code: String? = null - private val client: TelegramClient? = null + private val client: TelegramClient private var sent_code: TLSentCode? = null private var auth: TLAuthorization? = null var isPasswordNeeded = false private set - val isLoggedIn: Boolean + val loggedIn: Boolean get() = user != null val userString: String @@ -86,7 +86,7 @@ private constructor(c: TelegramClient) { @Throws(RpcErrorException::class, IOException::class) fun sendCodeToPhoneNumber(number: String) { this.phone = number - this.sent_code = this.client!!.authSendCode(false, this.phone, true) + this.sent_code = this.client!!.authSendCode(false, number, true) } @Throws(RpcErrorException::class, IOException::class) @@ -104,7 +104,7 @@ private constructor(c: TelegramClient) { @Throws(RpcErrorException::class, IOException::class) fun verifyPassword(pw: String) { - val password = pw.getBytes("UTF-8") + val password = pw.toByteArray(charset=Charsets.UTF_8) val salt = (client!!.accountGetPassword() as TLPassword).getCurrentSalt().getData() var md: MessageDigest? = null try { @@ -125,7 +125,7 @@ private constructor(c: TelegramClient) { companion object { private val logger = LoggerFactory.getLogger(UserManager::class.java) - private var instance: UserManager? = null + internal var instance: UserManager? = null @Throws(IOException::class) fun init(c: TelegramClient) { @@ -134,7 +134,7 @@ private constructor(c: TelegramClient) { fun getInstance(): UserManager { if (instance == null) throw RuntimeException("UserManager is not yet initialized.") - return instance + return instance!! } } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt b/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt index 48b9166..ba2145f 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/Utils.kt @@ -34,8 +34,7 @@ object Utils { private val logger = LoggerFactory.getLogger(Utils::class.java) as Logger - internal val accounts: Vector - get() { + fun getAccounts(): Vector { val accounts = Vector() val folder = File(Config.FILE_BASE) val files = folder.listFiles() @@ -48,8 +47,7 @@ object Utils { return accounts } - internal val newestVersion: Version? - get() { + fun getNewestVersion(): Version? { try { val data_url = "https://api.github.com/repos/fabianonline/telegram_backup/releases" logger.debug("Requesting current release info from {}", data_url) @@ -87,7 +85,7 @@ object Utils { @JvmOverloads internal fun obeyFloodWaitException(e: RpcErrorException?, silent: Boolean = false) { if (e == null || e!!.getCode() !== 420) return - val delay = e!!.getTagInteger() + val delay: Long = e!!.getTagInteger()!! as Long if (!silent) { System.out.println("") System.out.println( @@ -112,13 +110,13 @@ object Utils { logger.debug("Comparing versions {} and {}.", v1, v2) if (v1.equals(v2)) return VERSIONS_EQUAL - val v1_p = v1.split("-", 2) - val v2_p = v2.split("-", 2) + val v1_p = v1.split("-", limit=2) + val v2_p = v2.split("-", limit=2) logger.trace("Parts to compare without suffixes: {} and {}.", v1_p[0], v2_p[0]) - val v1_p2 = v1_p[0].split("\\.") - val v2_p2 = v2_p[0].split("\\.") + val v1_p2 = v1_p[0].split(".") + val v2_p2 = v2_p[0].split(".") logger.trace("Length of the parts without suffixes: {} and {}.", v1_p2.size, v2_p2.size) @@ -179,6 +177,6 @@ object Utils { } fun anonymize(str: String): String { - return if (!CommandLineOptions.cmd_anonymize) str else str.replaceAll("[0-9]", "1").replaceAll("[A-Z]", "A").replaceAll("[a-z]", "a") + " (ANONYMIZED)" + return if (!CommandLineOptions.cmd_anonymize) str else str.replace("[0-9]".toRegex(), "1").replace("[A-Z]".toRegex(), "A").replace("[a-z]".toRegex(), "a") + " (ANONYMIZED)" } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/exporter/HTMLExporter.kt b/src/main/kotlin/de/fabianonline/telegram_backup/exporter/HTMLExporter.kt index b6e83ab..d55a600 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/exporter/HTMLExporter.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/exporter/HTMLExporter.kt @@ -50,26 +50,26 @@ class HTMLExporter { // Create base dir logger.debug("Creating base dir") - val base = user.getFileBase() + "files" + File.separatorChar + val base = user.fileBase + "files" + File.separatorChar File(base).mkdirs() File(base + "dialogs").mkdirs() logger.debug("Fetching dialogs") val dialogs = db.getListOfDialogsForExport() - logger.trace("Got {} dialogs", dialogs.size()) + logger.trace("Got {} dialogs", dialogs.size) logger.debug("Fetching chats") val chats = db.getListOfChatsForExport() - logger.trace("Got {} chats", chats.size()) + logger.trace("Got {} chats", chats.size) logger.debug("Generating index.html") - val scope = HashMap() + val scope = HashMap() scope.put("user", user) scope.put("dialogs", dialogs) scope.put("chats", chats) // Collect stats data - scope.put("count.chats", chats.size()) - scope.put("count.dialogs", dialogs.size()) + scope.put("count.chats", chats.size) + scope.put("count.dialogs", dialogs.size) var count_messages_chats = 0 var count_messages_dialogs = 0 @@ -97,10 +97,10 @@ class HTMLExporter { mustache = mf.compile("templates/html/chat.mustache") var i = 0 - logger.debug("Generating {} dialog pages", dialogs.size()) + logger.debug("Generating {} dialog pages", dialogs.size) for (d in dialogs) { i++ - logger.trace("Dialog {}/{}: {}", i, dialogs.size(), Utils.anonymize("" + d.id)) + logger.trace("Dialog {}/{}: {}", i, dialogs.size, Utils.anonymize("" + d.id)) val messages = db.getMessagesForExport(d) scope.clear() scope.put("user", user) @@ -118,10 +118,10 @@ class HTMLExporter { } i = 0 - logger.debug("Generating {} chat pages", chats.size()) + logger.debug("Generating {} chat pages", chats.size) for (c in chats) { i++ - logger.trace("Chat {}/{}: {}", i, chats.size(), Utils.anonymize("" + c.id)) + logger.trace("Chat {}/{}: {}", i, chats.size, Utils.anonymize("" + c.id)) val messages = db.getMessagesForExport(c) scope.clear() scope.put("user", user) @@ -140,7 +140,7 @@ class HTMLExporter { logger.debug("Generating additional files") // Copy CSS - val cssFile = getClass().getResource("/templates/html/style.css") + val cssFile = javaClass.getResource("/templates/html/style.css") val dest = File(base + "style.css") FileUtils.copyURLToFile(cssFile, dest) logger.debug("Done exporting.") @@ -173,8 +173,8 @@ class HTMLExporter { private fun mapToString(map: Map): String { val sb = StringBuilder("[") - for (entry in map.entrySet()) { - sb.append("['" + entry.getKey() + "', " + entry.getValue() + "],") + for ((key, value) in map) { + sb.append("['$key', $value],") } sb.append("]") return sb.toString() diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/AbstractMediaFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/AbstractMediaFileManager.kt index 591987e..82c0f67 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/AbstractMediaFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/AbstractMediaFileManager.kt @@ -44,33 +44,34 @@ import java.util.concurrent.TimeoutException import org.apache.commons.io.FileUtils abstract class AbstractMediaFileManager(protected var message: TLMessage, protected var user: UserManager, protected var client: TelegramClient) { - var isEmpty = false + open var isEmpty = false abstract val size: Int abstract val extension: String - val downloaded: Boolean + open val downloaded: Boolean get() = File(targetPathAndFilename).isFile() val downloading: Boolean get() = File("${targetPathAndFilename}.downloading").isFile() - val targetPath: String + open val targetPath: String get() { - val path = user.getFileBase() + Config.FILE_FILES_BASE + File.separatorChar + val path = user.fileBase + Config.FILE_FILES_BASE + File.separatorChar File(path).mkdirs() return path } - val targetFilename: String + open val targetFilename: String get() { val message_id = message.getId() - if (message.getToId() is TLPeerChannel) { - val channel_id = message.getToId().getChannelId() + var to = message.getToId() + if (to is TLPeerChannel) { + val channel_id = to.getChannelId() return "channel_${channel_id}_${message_id}.$extension" } else return "${message_id}.$extension" } - val targetPathAndFilenam: String + open val targetPathAndFilename: String get() = targetPath + targetFilename abstract val letter: String @@ -91,7 +92,9 @@ abstract class AbstractMediaFileManager(protected var message: TLMessage, protec } - fun throwUnexpectedObjectError(o: Object) { - throw RuntimeException("Unexpected " + o.getClass().getName()) + companion object { + fun throwUnexpectedObjectError(o: Any) { + throw RuntimeException("Unexpected " + o.javaClass.getName()) + } } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/DocumentFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/DocumentFileManager.kt index 3b7dabc..bf0a67f 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/DocumentFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/DocumentFileManager.kt @@ -42,26 +42,23 @@ import java.util.concurrent.TimeoutException import org.apache.commons.io.FileUtils -class DocumentFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) : AbstractMediaFileManager(msg, user, client) { +open class DocumentFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) : AbstractMediaFileManager(msg, user, client) { protected var doc: TLDocument? = null - private var extension: String? = null + override lateinit var extension: String - val isSticker: Boolean + open val isSticker: Boolean get() { var sticker: TLDocumentAttributeSticker? = null if (this.isEmpty || doc == null) return false - return doc!!.getAttributes()?.filter{it is TLDocumentAttributeSticker}.isNotEmpty() + return doc!!.getAttributes()?.filter{it is TLDocumentAttributeSticker}?.isNotEmpty() ?: false } - val size: Int + override val size: Int get() = if (doc != null) doc!!.getSize() else 0 - val letter: String - get() = "d" - val name: String - get() = "document" - val description: String - get() = "Document" + open override val letter: String = "d" + open override val name: String = "document" + open override val description: String = "Document" init { val d = (msg.getMedia() as TLMessageMediaDocument).getDocument() @@ -72,9 +69,10 @@ class DocumentFileManager(msg: TLMessage, user: UserManager, client: TelegramCli } else { throwUnexpectedObjectError(d) } + extension = processExtension() } - fun getExtension(): String? { + private fun processExtension(): String { if (extension != null) return extension if (doc == null) return "empty" var ext: String? = null @@ -97,14 +95,13 @@ class DocumentFileManager(msg: TLMessage, user: UserManager, client: TelegramCli // Sometimes, extensions contain a trailing double quote. Remove this. Fixes #12. ext = ext!!.replace("\"", "") - this.extension = ext return ext } @Throws(RpcErrorException::class, IOException::class, TimeoutException::class) - fun download() { + override fun download() { if (doc != null) { - DownloadManager.downloadFile(client, getTargetPathAndFilename(), size, doc!!.getDcId(), doc!!.getId(), doc!!.getAccessHash()) + DownloadManager.downloadFile(client, targetPathAndFilename, size, doc!!.getDcId(), doc!!.getId(), doc!!.getAccessHash()) } } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/FileManagerFactory.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/FileManagerFactory.kt index 2a02ea5..0c18cab 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/FileManagerFactory.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/FileManagerFactory.kt @@ -50,7 +50,7 @@ object FileManagerFactory { return PhotoFileManager(m, u, c) } else if (media is TLMessageMediaDocument) { val d = DocumentFileManager(m, u, c) - return if (d.isSticker()) { + return if (d.isSticker) { StickerFileManager(m, u, c) } else d } else if (media is TLMessageMediaGeo) { diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/GeoFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/GeoFileManager.kt index 0ce3218..95b5a74 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/GeoFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/GeoFileManager.kt @@ -44,24 +44,21 @@ import java.util.concurrent.TimeoutException import org.apache.commons.io.FileUtils class GeoFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) : AbstractMediaFileManager(msg, user, client) { - protected var geo: TLGeoPoint + protected lateinit var geo: TLGeoPoint // We don't know the size, so we just guess. - val size: Int + override val size: Int get() { - val f = File(getTargetPathAndFilename()) - return if (f.isFile()) f.length() else 100000 + val f = File(targetPathAndFilename) + return if (f.isFile()) (f.length() as Int) else 100000 } - val extension: String + override val extension: String get() = "png" - val letter: String - get() = "g" - val name: String - get() = "geo" - val description: String - get() = "Geolocation" + override val letter = "g" + override val name = "geo" + override val description = "Geolocation" init { val g = (msg.getMedia() as TLMessageMediaGeo).getGeo() @@ -75,11 +72,11 @@ class GeoFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) } @Throws(IOException::class) - fun download() { + override fun download() { val url = "https://maps.googleapis.com/maps/api/staticmap?" + "center=" + geo.getLat() + "," + geo.getLong() + "&" + "zoom=14&size=300x150&scale=2&format=png&" + "key=" + Config.SECRET_GMAPS - DownloadManager.downloadExternalFile(getTargetPathAndFilename(), url) + DownloadManager.downloadExternalFile(targetPathAndFilename, url) } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/PhotoFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/PhotoFileManager.kt index c889b38..40969f2 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/PhotoFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/PhotoFileManager.kt @@ -43,18 +43,14 @@ import java.util.concurrent.TimeoutException import org.apache.commons.io.FileUtils class PhotoFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) : AbstractMediaFileManager(msg, user, client) { - private var photo: TLPhoto? = null - private var size: TLPhotoSize? = null + private lateinit var photo: TLPhoto + override var size = 0 + private lateinit var photo_size: TLPhotoSize - val extension: String - get() = "jpg" - - val letter: String - get() = "p" - val name: String - get() = "photo" - val description: String - get() = "Photo" + override val extension = "jpg" + override val letter = "p" + override val name = "photo" + override val description = "Photo" init { val p = (msg.getMedia() as TLMessageMediaPhoto).getPhoto() @@ -72,7 +68,8 @@ class PhotoFileManager(msg: TLMessage, user: UserManager, client: TelegramClient if (biggest == null) { throw RuntimeException("Could not find a size for a photo.") } - this.size = biggest + this.photo_size = biggest + this.size = biggest.getSize() } else if (p is TLPhotoEmpty) { this.isEmpty = true } else { @@ -80,14 +77,10 @@ class PhotoFileManager(msg: TLMessage, user: UserManager, client: TelegramClient } } - fun getSize(): Int { - return if (size != null) size!!.getSize() else 0 - } - @Throws(RpcErrorException::class, IOException::class, TimeoutException::class) - fun download() { + override fun download() { if (isEmpty) return - val loc = size!!.getLocation() as TLFileLocation - DownloadManager.downloadFile(client, getTargetPathAndFilename(), getSize(), loc.getDcId(), loc.getVolumeId(), loc.getLocalId(), loc.getSecret()) + val loc = photo_size.getLocation() as TLFileLocation + DownloadManager.downloadFile(client, targetPathAndFilename, size, loc.getDcId(), loc.getVolumeId(), loc.getLocalId(), loc.getSecret()) } } diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/StickerFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/StickerFileManager.kt index d6afa8b..40a7cdb 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/StickerFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/StickerFileManager.kt @@ -52,13 +52,12 @@ import org.apache.commons.io.FileUtils class StickerFileManager(msg: TLMessage, user: UserManager, client: TelegramClient) : DocumentFileManager(msg, user, client) { - val isSticker: Boolean - get() = true + override val isSticker = true private val filenameBase: String get() { var sticker: TLDocumentAttributeSticker? = null - for (attr in doc.getAttributes()) { + for (attr in doc!!.getAttributes()) { if (attr is TLDocumentAttributeSticker) { sticker = attr as TLDocumentAttributeSticker } @@ -75,34 +74,33 @@ class StickerFileManager(msg: TLMessage, user: UserManager, client: TelegramClie return file.toString() } - val targetFilename: String + override val targetFilename: String get() = filenameBase + "." + extension - val targetPath: String + override val targetPath: String get() { - val path = user.getFileBase() + Config.FILE_FILES_BASE + File.separatorChar + Config.FILE_STICKER_BASE + File.separatorChar + val path = user.fileBase + Config.FILE_FILES_BASE + File.separatorChar + Config.FILE_STICKER_BASE + File.separatorChar File(path).mkdirs() return path } - val extension: String - get() = "webp" + override var extension = "webp" - val letter: String + override val letter: String get() = "s" - val name: String + override val name: String get() = "sticker" - val description: String + override val description: String get() = "Sticker" @Throws(RpcErrorException::class, IOException::class, TimeoutException::class) - fun download() { + override fun download() { val old_file = Config.FILE_BASE + File.separatorChar + Config.FILE_STICKER_BASE + File.separatorChar + targetFilename logger.trace("Old filename exists: {}", File(old_file).exists()) if (File(old_file).exists()) { - Files.copy(Paths.get(old_file), Paths.get(getTargetPathAndFilename()), StandardCopyOption.REPLACE_EXISTING) + Files.copy(Paths.get(old_file), Paths.get(targetPathAndFilename), StandardCopyOption.REPLACE_EXISTING) return } super.download() diff --git a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/UnsupportedFileManager.kt b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/UnsupportedFileManager.kt index 34640f2..5f87775 100644 --- a/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/UnsupportedFileManager.kt +++ b/src/main/kotlin/de/fabianonline/telegram_backup/mediafilemanager/UnsupportedFileManager.kt @@ -44,34 +44,15 @@ import java.util.concurrent.TimeoutException import org.apache.commons.io.FileUtils class UnsupportedFileManager(msg: TLMessage, user: UserManager, client: TelegramClient, type: String) : AbstractMediaFileManager(msg, user, client) { - var name: String? = null - internal set - - val targetFilename: String - get() = "" - - val targetPath: String - get() = "" - - val extension: String - get() = "" - - val size: Int - get() = 0 - - val isEmpty: Boolean - get() = false - val isDownloaded: Boolean - get() = false - - val letter: String - get() = " " - val description: String - get() = "Unsupported / non-downloadable Media" - - init { - this.name = type - } - - fun download() {} + override var name = type + override val targetFilename = "" + override val targetPath = "" + override val extension = "" + override val size = 0 + override var isEmpty = false + override val downloaded = false + override val letter = " " + override val description = "Unsupported / non-downloadable Media" + + override fun download() {} }