mirror of
https://github.com/fabianonline/telegram_backup.git
synced 2024-12-25 14:25:35 +00:00
WIP: Started rewriting the code to make it more null-safe.
This commit is contained in:
parent
6276651b84
commit
97cf26b46d
@ -0,0 +1,5 @@
|
||||
package de.fabianonline.telegram_backup
|
||||
|
||||
class Account(val file_base: String, val phone_number: String) {
|
||||
|
||||
}
|
@ -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 <x>' to use account <x>.\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 <x>' 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") {}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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<Int>
|
||||
get() {
|
||||
try {
|
||||
val missing = LinkedList<Int>()
|
||||
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<Int>()
|
||||
try {
|
||||
val missing = LinkedList<Int>()
|
||||
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<TLMessage?> {
|
||||
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<Int> {
|
||||
@ -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
|
||||
|
@ -34,9 +34,23 @@ object Utils {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(Utils::class.java) as Logger
|
||||
|
||||
fun getAccounts(): Vector<String> {
|
||||
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 <x>' 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<String> {
|
||||
val accounts = Vector<String>()
|
||||
val folder = File(Config.FILE_BASE)
|
||||
val folder = File(file_base)
|
||||
val files = folder.listFiles()
|
||||
if (files != null)
|
||||
for (f in files) {
|
||||
|
Loading…
Reference in New Issue
Block a user