diff --git a/config.properties.template b/config.properties.template index 02653007c..20ad20213 100644 --- a/config.properties.template +++ b/config.properties.template @@ -117,6 +117,12 @@ timer_walk_to_start_pokestop=-1 # Set profile update timer (Default: 60) profile_update_timer=60 +# Number of exceptions allowed to occur until the bot is restarted (-1 to disable auto restarts, suggested value: 5) +auto_restart_threshold=-1 + +# Period (in seconds) in which the exceptions must occur to restart the bot (Default: 300) +auto_restart_period=300 + # Minimum IV percentage to keep a pokemon (to ignore IV: use -1) # between 0 and 100, suggested 80 transfer_iv_threshold=80 diff --git a/json-template.json b/json-template.json index 1a61c3446..e4142680c 100644 --- a/json-template.json +++ b/json-template.json @@ -47,6 +47,8 @@ "allowLeaveStartArea" : false, "spawnRadius" : -1, "banSpinCount" : 0, + "autoRestartThreshold" : -1, + "autoRestartPeriod" : 300, "transferCpThreshold" : 400, "transferIvThreshold" : 80, "ignoredPokemon" : [ "EEVEE", "MEWTWO", "CHARMANDER" ], diff --git a/src/main/kotlin/ink/abb/pogo/scraper/Bot.kt b/src/main/kotlin/ink/abb/pogo/scraper/Bot.kt index e610d818a..0876f94cd 100644 --- a/src/main/kotlin/ink/abb/pogo/scraper/Bot.kt +++ b/src/main/kotlin/ink/abb/pogo/scraper/Bot.kt @@ -35,6 +35,7 @@ class Bot(val api: PokemonGo, val settings: Settings) { private var runningLatch = CountDownLatch(0) var prepareWalkBack = AtomicBoolean(false) var walkBackLock = AtomicBoolean(true) + var exceptionHandler: ((Throwable) -> Unit)? = null lateinit private var phaser: Phaser @@ -188,6 +189,7 @@ class Bot(val api: PokemonGo, val settings: Settings) { } catch (t: Throwable) { Log.red("Error running loop $name!") t.printStackTrace() + exceptionHandler?.invoke(t) } if (cancelled) continue diff --git a/src/main/kotlin/ink/abb/pogo/scraper/Main.kt b/src/main/kotlin/ink/abb/pogo/scraper/Main.kt index 0432731ec..8d41d9a48 100644 --- a/src/main/kotlin/ink/abb/pogo/scraper/Main.kt +++ b/src/main/kotlin/ink/abb/pogo/scraper/Main.kt @@ -40,14 +40,14 @@ fun getAuth(settings: Settings, http: OkHttpClient, writeToken: (String) -> Unit if (credentials.token.isBlank()) { val provider = GoogleUserCredentialProvider(http, time) - println("Please go to " + GoogleUserCredentialProvider.LOGIN_URL) - println("Enter authorisation code:") + Log.yellow("Please go to " + GoogleUserCredentialProvider.LOGIN_URL) + Log.yellow("Enter authorisation code:") val access = readLine() // we should be able to login with this token provider.login(access) - println("Refresh token:" + provider.refreshToken) + Log.yellow("Refresh token:" + provider.refreshToken) Log.normal("Setting Google refresh token in your config") credentials.token = provider.refreshToken writeToken(credentials.token) @@ -96,7 +96,7 @@ fun startDefaultBot(http: OkHttpClient, service: BotService) { try { properties = loadProperties(filename) } catch (e: FileNotFoundException) { - Log.red("${filename} file not found. Trying config.properties.txt...") + Log.red("$filename file not found. Trying config.properties.txt...") try { // Fix for Windows users... filename += ".txt" @@ -161,12 +161,12 @@ fun startBot(settings: Settings, http: OkHttpClient, writeToken: (String) -> Uni Log.normal("Logged in successfully") - print("Getting profile data from pogo server") + Log.normal("Getting profile data from pogo server...") while (api.playerProfile == null) { - print(".") + Log.normal("Still waiting for profile data...") Thread.sleep(1000) } - println(".") + Log.normal("Received profile data...") Thread.sleep(1000) val stats = try { diff --git a/src/main/kotlin/ink/abb/pogo/scraper/Settings.kt b/src/main/kotlin/ink/abb/pogo/scraper/Settings.kt index a7a6a577d..ff160d322 100644 --- a/src/main/kotlin/ink/abb/pogo/scraper/Settings.kt +++ b/src/main/kotlin/ink/abb/pogo/scraper/Settings.kt @@ -104,7 +104,11 @@ class SettingsParser(val properties: Properties) { guiPortSocket = getPropertyIfSet("Port where the socketserver should listen", "gui_port_socket", defaults.guiPortSocket, String::toInt), - initialMapSize = getPropertyIfSet("Initial map size (S2 tiles) to fetch", "initial_map_size", defaults.initialMapSize, String::toInt) + initialMapSize = getPropertyIfSet("Initial map size (S2 tiles) to fetch", "initial_map_size", defaults.initialMapSize, String::toInt), + + autoRestartThreshold = getPropertyIfSet("Number of exceptions allowed to occur until the bot is restarted", "auto_restart_threshold", defaults.autoRestartThreshold, String::toInt), + autoRestartPeriod = getPropertyIfSet ("Period (in seconds) in which the exceptions must occur to restart the bot", "auto_restart_period", defaults.autoRestartPeriod, String::toLong) + ) } @@ -217,6 +221,9 @@ data class Settings( var initialMapSize: Int = 9, + val autoRestartThreshold: Int = -1, + val autoRestartPeriod: Long = 300, + val version: String = Settings.version ) { fun withName(name: String): Settings { diff --git a/src/main/kotlin/ink/abb/pogo/scraper/services/BotService.kt b/src/main/kotlin/ink/abb/pogo/scraper/services/BotService.kt index 1788cf9f0..1666dd0b0 100644 --- a/src/main/kotlin/ink/abb/pogo/scraper/services/BotService.kt +++ b/src/main/kotlin/ink/abb/pogo/scraper/services/BotService.kt @@ -14,10 +14,12 @@ import ink.abb.pogo.scraper.Bot import ink.abb.pogo.scraper.Settings import ink.abb.pogo.scraper.util.credentials.* import ink.abb.pogo.scraper.startBot +import ink.abb.pogo.scraper.util.Log import okhttp3.OkHttpClient import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.io.File +import java.time.LocalDateTime import java.util.concurrent.CountDownLatch import javax.annotation.PreDestroy import kotlin.concurrent.thread @@ -44,6 +46,41 @@ class BotService { @Synchronized fun addBot(bot: Bot) { bots.add(bot) + + if (bot.settings.autoRestartThreshold > -1) { + Log.normal("Enabling bot auto restart") + + var counter = 0 + var counterReset = LocalDateTime.now().plusSeconds(bot.settings.autoRestartPeriod) + var stopped = false + + bot.exceptionHandler = { throwable -> + synchronized(bot) { + if (!stopped && bot.isRunning()) { + if (LocalDateTime.now().isAfter(counterReset)) { + counter = 0 + counterReset = LocalDateTime.now().plusSeconds(bot.settings.autoRestartPeriod) + Log.normal("Reset restart counter. Next reset: $counterReset") + } + + counter++ + Log.normal("Increasing restart counter to $counter/${bot.settings.autoRestartThreshold}") + + if (counter > bot.settings.autoRestartThreshold) { + Log.yellow("Restarting bot due to reached restart threshold!") + thread { + bot.stop() + removeBot(bot) + Log.yellow("Stopped bot") + Log.yellow("Restarting...") + submitBot(bot.settings) + } + stopped = true + } + } + } + } + } } @Synchronized