From a0d98d1165c36317503f74e55a39f737999a5cbe Mon Sep 17 00:00:00 2001 From: HimanM <67066047+HimanM@users.noreply.github.com> Date: Sat, 11 Jul 2026 11:17:47 +0530 Subject: [PATCH 1/2] Add native Android drops miner --- .github/workflows/ci.yml | 31 + .gitignore | 7 +- .../.kotlin/errors/errors-1783691283914.log | 301 ++++ android/README.md | 40 + android/app/build.gradle.kts | 51 + android/app/src/main/AndroidManifest.xml | 43 + .../io/github/himanm/tdminer/CookieStore.kt | 43 + .../io/github/himanm/tdminer/MainActivity.kt | 41 + .../io/github/himanm/tdminer/MinerCore.kt | 154 ++ .../himanm/tdminer/MinerForegroundService.kt | 155 ++ .../io/github/himanm/tdminer/MinerSession.kt | 60 + .../himanm/tdminer/MinerSettingsStore.kt | 156 ++ .../himanm/tdminer/MinerWidgetProvider.kt | 70 + .../io/github/himanm/tdminer/TDMinerApp.kt | 1275 +++++++++++++++++ .../io/github/himanm/tdminer/TwitchAuth.kt | 27 + .../github/himanm/tdminer/TwitchCookieJar.kt | 39 + .../himanm/tdminer/TwitchDeviceLogin.kt | 84 ++ .../io/github/himanm/tdminer/TwitchGql.kt | 701 +++++++++ .../res/drawable-nodpi/tdminer_app_icon.png | Bin 0 -> 1211860 bytes .../tdminer_icon_foreground.png | Bin 0 -> 257619 bytes .../drawable-nodpi/tdminer_icon_source.png | Bin 0 -> 1043276 bytes .../res/drawable/ic_launcher_foreground.xml | 12 + .../src/main/res/drawable/launch_panel.xml | 7 + .../src/main/res/drawable/launch_progress.xml | 4 + .../src/main/res/drawable/launch_screen.xml | 8 + .../main/res/font/roboto_condensed_black.ttf | Bin 0 -> 113528 bytes .../main/res/font/roboto_condensed_bold.ttf | Bin 0 -> 113112 bytes .../res/font/roboto_condensed_regular.ttf | Bin 0 -> 112600 bytes .../app/src/main/res/layout/miner_widget.xml | 41 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 4 + android/app/src/main/res/values/colors.xml | 4 + android/app/src/main/res/values/strings.xml | 3 + android/app/src/main/res/values/styles.xml | 10 + .../src/main/res/xml/miner_widget_info.xml | 11 + .../github/himanm/tdminer/CookieStoreTest.kt | 24 + .../himanm/tdminer/DesktopCookieImportTest.kt | 15 + .../io/github/himanm/tdminer/MinerCoreTest.kt | 198 +++ .../github/himanm/tdminer/MinerSessionTest.kt | 31 + .../himanm/tdminer/MinerSettingsStoreTest.kt | 58 + .../github/himanm/tdminer/TwitchAuthTest.kt | 11 + .../himanm/tdminer/TwitchCookieJarTest.kt | 64 + .../io/github/himanm/tdminer/TwitchGqlTest.kt | 453 ++++++ android/build.gradle.kts | 5 + android/gradle.properties | 3 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + android/gradlew | 252 ++++ android/gradlew.bat | 94 ++ android/settings.gradle.kts | 18 + core/constants.py | 1 + docs/android-app-feasibility.md | 300 ++++ docs/android-category-flow.md | 36 + docs/android-ui-refinement-issues.md | 24 + gui/components.py | 8 + network/twitch.py | 16 +- tui/app.py | 9 + tui/cli.py | 4 + tui/manager.py | 5 + 58 files changed, 5015 insertions(+), 3 deletions(-) create mode 100644 android/.kotlin/errors/errors-1783691283914.log create mode 100644 android/README.md create mode 100644 android/app/build.gradle.kts create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/CookieStore.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MainActivity.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MinerCore.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MinerForegroundService.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MinerSession.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MinerSettingsStore.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/MinerWidgetProvider.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/TDMinerApp.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/TwitchAuth.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/TwitchCookieJar.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/TwitchDeviceLogin.kt create mode 100644 android/app/src/main/java/io/github/himanm/tdminer/TwitchGql.kt create mode 100644 android/app/src/main/res/drawable-nodpi/tdminer_app_icon.png create mode 100644 android/app/src/main/res/drawable-nodpi/tdminer_icon_foreground.png create mode 100644 android/app/src/main/res/drawable-nodpi/tdminer_icon_source.png create mode 100644 android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 android/app/src/main/res/drawable/launch_panel.xml create mode 100644 android/app/src/main/res/drawable/launch_progress.xml create mode 100644 android/app/src/main/res/drawable/launch_screen.xml create mode 100644 android/app/src/main/res/font/roboto_condensed_black.ttf create mode 100644 android/app/src/main/res/font/roboto_condensed_bold.ttf create mode 100644 android/app/src/main/res/font/roboto_condensed_regular.ttf create mode 100644 android/app/src/main/res/layout/miner_widget.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/main/res/xml/miner_widget_info.xml create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/CookieStoreTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/DesktopCookieImportTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/MinerCoreTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/MinerSessionTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/MinerSettingsStoreTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/TwitchAuthTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/TwitchCookieJarTest.kt create mode 100644 android/app/src/test/java/io/github/himanm/tdminer/TwitchGqlTest.kt create mode 100644 android/build.gradle.kts create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/settings.gradle.kts create mode 100644 docs/android-app-feasibility.md create mode 100644 docs/android-category-flow.md create mode 100644 docs/android-ui-refinement-issues.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93ed7ef..c6cf661 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,6 +127,36 @@ jobs: name: Twitch.Drops.Miner.Windows path: Twitch.Drops.Miner.Windows.zip + android: + name: Android + runs-on: ubuntu-latest + needs: + - validate + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + cache: gradle + + - name: Build and test Android app + working-directory: android + run: | + chmod +x gradlew + ./gradlew testDebugUnitTest assembleDebug --no-daemon + + - name: Upload Android APK + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + name: Twitch.Drops.Miner.Android + path: android/app/build/outputs/apk/debug/app-debug.apk + macos: name: macOS runs-on: macos-latest @@ -409,6 +439,7 @@ jobs: name: Upload builds to Releases if: github.event_name != 'pull_request' needs: + - android - windows - linux-pyinstaller - linux-appimage diff --git a/.gitignore b/.gitignore index 5992774..9b7db31 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,9 @@ settings.json *.app /.venv-linux-build /.venv-tui -/graphify-out \ No newline at end of file +/graphify-out + +# Android local SDK/build state +/android/.gradle +/android/local.properties +/android/app/build diff --git a/android/.kotlin/errors/errors-1783691283914.log b/android/.kotlin/errors/errors-1783691283914.log new file mode 100644 index 0000000..1d79576 --- /dev/null +++ b/android/.kotlin/errors/errors-1783691283914.log @@ -0,0 +1,301 @@ +kotlin version: 2.0.21 +error message: org.jetbrains.kotlin.util.FileAnalysisException: While analysing D:/Projects/Twitch Drops/TwitchDropsMiner/android/app/src/main/java/io/github/himanm/tdminer/TDMinerApp.kt:237:37: java.lang.IllegalStateException: Could not read file: D:/Projects/Twitch Drops/TwitchDropsMiner/android/app/build/tmp/kotlin-classes/debug/io/github/himanm/tdminer/TwitchAuthResult.class; size in bytes: -1; file type: CLASS + at org.jetbrains.kotlin.util.AnalysisExceptionsKt.wrapIntoFileAnalysisExceptionIfNeeded(AnalysisExceptions.kt:57) + at org.jetbrains.kotlin.fir.FirCliExceptionHandler.handleExceptionOnFileAnalysis(Utils.kt:249) + at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runCheckers(analyse.kt:46) + at org.jetbrains.kotlin.fir.pipeline.FirUtilsKt.resolveAndCheckFir(firUtils.kt:77) + at org.jetbrains.kotlin.fir.pipeline.FirUtilsKt.buildResolveAndCheckFirViaLightTree(firUtils.kt:88) + at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.compileModuleToAnalyzedFir(jvmCompilerPipeline.kt:319) + at org.jetbrains.kotlin.cli.jvm.compiler.pipeline.JvmCompilerPipelineKt.compileModulesUsingFrontendIrAndLightTree(jvmCompilerPipeline.kt:118) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:148) + at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:43) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:103) + at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:49) + at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:464) + at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:73) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.doCompile(IncrementalCompilerRunner.kt:506) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:423) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally$lambda$9$compile(IncrementalCompilerRunner.kt:249) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:267) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +Caused by: java.lang.IllegalStateException: Could not read file: D:/Projects/Twitch Drops/TwitchDropsMiner/android/app/build/tmp/kotlin-classes/debug/io/github/himanm/tdminer/TwitchAuthResult.class; size in bytes: -1; file type: CLASS + at org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass$Factory.logFileReadingErrorMessage(VirtualFileKotlinClass.kt:77) + at org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass$Factory.create$lambda$3(VirtualFileKotlinClass.kt:68) + at org.jetbrains.kotlin.util.PerformanceCounter.time(PerformanceCounter.kt:90) + at org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass$Factory.create$frontend_common_jvm(VirtualFileKotlinClass.kt:51) + at org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache$Companion.getKotlinBinaryClassOrClassFileContent$lambda$0(KotlinBinaryClassCache.kt:89) + at org.jetbrains.kotlin.com.intellij.mock.MockApplication.runReadAction(MockApplication.java:190) + at org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache$Companion.getKotlinBinaryClassOrClassFileContent(KotlinBinaryClassCache.kt:88) + at org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache$Companion.getKotlinBinaryClassOrClassFileContent$default(KotlinBinaryClassCache.kt:72) + at org.jetbrains.kotlin.load.kotlin.VirtualFileFinder.findKotlinClassOrContent(VirtualFileFinder.kt:37) + at org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider.extractClassMetadata(JvmClassFileBasedSymbolProvider.kt:161) + at org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider.findAndDeserializeClass(AbstractFirDeserializedSymbolProvider.kt:228) + at org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider.classCache$lambda$5(AbstractFirDeserializedSymbolProvider.kt:162) + at org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCacheWithPostCompute.getValue(FirThreadUnsafeCachesFactory.kt:58) + at org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider.getClass(AbstractFirDeserializedSymbolProvider.kt:314) + at org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider.getClass$default(AbstractFirDeserializedSymbolProvider.kt:297) + at org.jetbrains.kotlin.fir.deserialization.AbstractFirDeserializedSymbolProvider.getClassLikeSymbolByClassId(AbstractFirDeserializedSymbolProvider.kt:371) + at org.jetbrains.kotlin.fir.resolve.providers.impl.FirCachingCompositeSymbolProvider.computeClass(FirCachingCompositeSymbolProvider.kt:147) + at org.jetbrains.kotlin.fir.resolve.providers.impl.FirCachingCompositeSymbolProvider.access$computeClass(FirCachingCompositeSymbolProvider.kt:27) + at org.jetbrains.kotlin.fir.resolve.providers.impl.FirCachingCompositeSymbolProvider$special$$inlined$createCache$1.invoke(FirCachesFactory.kt:73) + at org.jetbrains.kotlin.fir.resolve.providers.impl.FirCachingCompositeSymbolProvider$special$$inlined$createCache$1.invoke(FirCachesFactory.kt:71) + at org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCache.getValue(FirThreadUnsafeCachesFactory.kt:40) + at org.jetbrains.kotlin.fir.resolve.providers.impl.FirCachingCompositeSymbolProvider.getClassLikeSymbolByClassId(FirCachingCompositeSymbolProvider.kt:174) + at org.jetbrains.kotlin.fir.resolve.LookupTagUtilsKt.toSymbol(LookupTagUtils.kt:59) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.addExperimentalities(FirOptInUsageBaseChecker.kt:265) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.addExperimentalities(FirOptInUsageBaseChecker.kt:269) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadCallableSpecificExperimentalities(FirOptInUsageBaseChecker.kt:219) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadExperimentalities(FirOptInUsageBaseChecker.kt:170) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.loadExperimentalities(FirOptInUsageBaseChecker.kt:142) + at org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageAccessChecker.check(FirOptInUsageAccessChecker.kt:43) + at org.jetbrains.kotlin.fir.analysis.collectors.components.ExpressionCheckersDiagnosticComponent.check(ExpressionCheckersDiagnosticComponent.kt:266) + at org.jetbrains.kotlin.fir.analysis.collectors.components.ExpressionCheckersDiagnosticComponent.visitFunctionCall(ExpressionCheckersDiagnosticComponent.kt:74) + at org.jetbrains.kotlin.fir.analysis.collectors.components.ExpressionCheckersDiagnosticComponent.visitFunctionCall(ExpressionCheckersDiagnosticComponent.kt:19) + at org.jetbrains.kotlin.fir.expressions.FirFunctionCall.accept(FirFunctionCall.kt:41) + at org.jetbrains.kotlin.fir.analysis.collectors.CheckerRunningDiagnosticCollectorVisitor.checkElement(CheckerRunningDiagnosticCollectorVisitor.kt:24) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:48) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithCallOrAssignment(AbstractDiagnosticCollectorVisitor.kt:346) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:255) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirFunctionCall.accept(FirFunctionCall.kt:41) + at org.jetbrains.kotlin.fir.declarations.impl.FirPropertyImpl.acceptChildren(FirPropertyImpl.kt:75) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitProperty(AbstractDiagnosticCollectorVisitor.kt:879) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitProperty(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.declarations.FirProperty.accept(FirProperty.kt:58) + at org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl.acceptChildren(FirBlockImpl.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:209) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirBlock.accept(FirBlock.kt:28) + at org.jetbrains.kotlin.fir.expressions.impl.FirTryExpressionImpl.acceptChildren(FirTryExpressionImpl.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:49) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirVisitor.visitTryExpression(FirVisitor.kt:132) + at org.jetbrains.kotlin.fir.expressions.FirTryExpression.accept(FirTryExpression.kt:32) + at org.jetbrains.kotlin.fir.expressions.impl.FirReturnExpressionImpl.acceptChildren(FirReturnExpressionImpl.kt:41) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitJump(FirDefaultVisitor.kt:54) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitReturnExpression(FirDefaultVisitor.kt:66) + at org.jetbrains.kotlin.fir.expressions.FirReturnExpression.accept(FirReturnExpression.kt:31) + at org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl.acceptChildren(FirBlockImpl.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:209) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirBlock.accept(FirBlock.kt:28) + at org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl.acceptChildren(FirAnonymousFunctionImpl.kt:75) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithDeclarationAndReceiver(AbstractDiagnosticCollectorVisitor.kt:311) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunction(AbstractDiagnosticCollectorVisitor.kt:141) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:134) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression.accept(FirAnonymousFunctionExpression.kt:30) + at org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList.acceptChildren(FirResolvedArgumentList.kt:35) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:53) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirVisitor.visitArgumentList(FirVisitor.kt:81) + at org.jetbrains.kotlin.fir.expressions.FirArgumentList.accept(FirArgumentList.kt:25) + at org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl.acceptChildren(FirFunctionCallImpl.kt:55) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:49) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithCallOrAssignment(AbstractDiagnosticCollectorVisitor.kt:346) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:255) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirFunctionCall.accept(FirFunctionCall.kt:41) + at org.jetbrains.kotlin.fir.expressions.impl.FirVariableAssignmentImpl.acceptChildren(FirVariableAssignmentImpl.kt:33) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:49) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithCallOrAssignment(AbstractDiagnosticCollectorVisitor.kt:346) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitVariableAssignment(AbstractDiagnosticCollectorVisitor.kt:271) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitVariableAssignment(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirVariableAssignment.accept(FirVariableAssignment.kt:27) + at org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl.acceptChildren(FirBlockImpl.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:209) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirBlock.accept(FirBlock.kt:28) + at org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl.acceptChildren(FirAnonymousFunctionImpl.kt:75) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithDeclarationAndReceiver(AbstractDiagnosticCollectorVisitor.kt:311) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunction(AbstractDiagnosticCollectorVisitor.kt:141) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:134) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression.accept(FirAnonymousFunctionExpression.kt:30) + at org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList.acceptChildren(FirResolvedArgumentList.kt:35) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:53) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirVisitor.visitArgumentList(FirVisitor.kt:81) + at org.jetbrains.kotlin.fir.expressions.FirArgumentList.accept(FirArgumentList.kt:25) + at org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl.acceptChildren(FirFunctionCallImpl.kt:55) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitElement(AbstractDiagnosticCollectorVisitor.kt:49) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithCallOrAssignment(AbstractDiagnosticCollectorVisitor.kt:346) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:255) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFunctionCall(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirFunctionCall.accept(FirFunctionCall.kt:41) + at org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl.acceptChildren(FirBlockImpl.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:209) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirBlock.accept(FirBlock.kt:28) + at org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl.acceptChildren(FirAnonymousFunctionImpl.kt:75) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithDeclarationAndReceiver(AbstractDiagnosticCollectorVisitor.kt:311) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunction(AbstractDiagnosticCollectorVisitor.kt:141) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:134) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnonymousFunctionExpression(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression.accept(FirAnonymousFunctionExpression.kt:30) + at org.jetbrains.kotlin.fir.declarations.impl.FirPropertyImpl.acceptChildren(FirPropertyImpl.kt:75) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitProperty(AbstractDiagnosticCollectorVisitor.kt:879) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitProperty(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.declarations.FirProperty.accept(FirProperty.kt:58) + at org.jetbrains.kotlin.fir.expressions.impl.FirBlockImpl.acceptChildren(FirBlockImpl.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:61) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitAnnotationContainer(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitStatement(FirDefaultVisitor.kt:33) + at org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor.visitExpression(FirDefaultVisitor.kt:36) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:209) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitBlock(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.expressions.FirBlock.accept(FirBlock.kt:28) + at org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl.acceptChildren(FirSimpleFunctionImpl.kt:68) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitWithDeclarationAndReceiver(AbstractDiagnosticCollectorVisitor.kt:311) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitSimpleFunction(AbstractDiagnosticCollectorVisitor.kt:118) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitSimpleFunction(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.declarations.FirSimpleFunction.accept(FirSimpleFunction.kt:51) + at org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl.acceptChildren(FirFileImpl.kt:57) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitNestedElements(AbstractDiagnosticCollectorVisitor.kt:38) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFile(AbstractDiagnosticCollectorVisitor.kt:1151) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor.visitFile(AbstractDiagnosticCollectorVisitor.kt:30) + at org.jetbrains.kotlin.fir.declarations.FirFile.accept(FirFile.kt:42) + at org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector.collectDiagnostics(AbstractDiagnosticCollector.kt:36) + at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runCheckers(analyse.kt:34) + ... 34 more +Caused by: java.nio.file.NoSuchFileException: D:\Projects\Twitch Drops\TwitchDropsMiner\android\app\build\tmp\kotlin-classes\debug\io\github\himanm\tdminer\TwitchAuthResult.class + at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85) + at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) + at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108) + at java.base/sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:234) + at java.base/java.nio.file.Files.newByteChannel(Files.java:379) + at java.base/java.nio.file.Files.newByteChannel(Files.java:431) + at java.base/java.nio.file.Files.readAllBytes(Files.java:3268) + at org.jetbrains.kotlin.com.intellij.openapi.vfs.local.CoreLocalVirtualFile.contentsToByteArray(CoreLocalVirtualFile.java:148) + at org.jetbrains.kotlin.com.intellij.openapi.vfs.VirtualFile.contentsToByteArray(VirtualFile.java:627) + at org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass$Factory.create$lambda$3(VirtualFileKotlinClass.kt:55) + ... 208 more + + +error message: Daemon compilation failed: null +java.lang.Exception + at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69) + at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65) + at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240) + at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159) + at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111) + at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76) + at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63) + at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66) + at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62) + at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100) + at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62) + at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44) + at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209) + at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) + at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) + at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) + at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) + at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41) + at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59) + at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) + at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:194) + at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:127) + at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:169) + at org.gradle.internal.Factories$1.create(Factories.java:31) + at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263) + at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127) + at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:132) + at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164) + at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:133) + at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) + at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) + at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +Caused by: java.nio.file.NoSuchFileException: C:\Users\mandu\AppData\Local\Temp\kotlin-backups6318218434951528065\2.backup -> D:\Projects\Twitch Drops\TwitchDropsMiner\android\app\build\tmp\kotlin-classes\debug\io\github\himanm\tdminer\ComposableSingletons$TDMinerAppKt$lambda-1$1.class + at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85) + at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) + at java.base/sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:414) + at java.base/sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:291) + at java.base/java.nio.file.Files.move(Files.java:1430) + at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.revertChanges(CompilationTransaction.kt:231) + at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:256) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747) + at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675) + at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92) + at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + ... 3 more + + diff --git a/android/README.md b/android/README.md new file mode 100644 index 0000000..f39b580 --- /dev/null +++ b/android/README.md @@ -0,0 +1,40 @@ +# TD Miner Android + +Command-line Android build. No Android Studio required. + +## Build + +```powershell +.\gradlew.bat testDebugUnitTest assembleDebug +``` + +APK: + +```text +app/build/outputs/apk/debug/app-debug.apk +``` + +## Install To Phone + +Enable USB debugging, then: + +```powershell +$adb = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" +& $adb devices +& $adb install -r app\build\outputs\apk\debug\app-debug.apk +& $adb shell am start -n io.github.himanm.tdminer/.MainActivity +``` + +## Seed Desktop Cookies For Debug Testing + +Do not bake cookies into the APK. For local testing, copy the existing desktop JSON cookie jar into the app-private files directory: + +```powershell +& $adb push ..\dist\cookies.jar /sdcard/Download/tdminer-cookies.jar +& $adb shell run-as io.github.himanm.tdminer sh -c "mkdir -p files && cp /sdcard/Download/tdminer-cookies.jar files/cookies.jar" +& $adb shell am start -n io.github.himanm.tdminer/.MainActivity +``` + +The app stores imported cookies in private `SharedPreferences`. They survive `adb install -r` updates and are cleared by Logout or app uninstall. + +The current app is a native responsive shell only. It does not run the real miner core yet. diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000..79d3ceb --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,51 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("org.jetbrains.kotlin.plugin.compose") +} + +android { + namespace = "io.github.himanm.tdminer" + compileSdk = 35 + + defaultConfig { + applicationId = "io.github.himanm.tdminer" + minSdk = 26 + targetSdk = 35 + versionCode = 1 + versionName = "0.1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildFeatures { + compose = true + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } +} + +dependencies { + implementation("androidx.activity:activity-compose:1.9.3") + implementation(platform("androidx.compose:compose-bom:2024.12.01")) + implementation("androidx.compose.foundation:foundation") + implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-extended") + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-tooling-preview") + debugImplementation("androidx.compose.ui:ui-tooling") + + testImplementation("junit:junit:4.13.2") + testImplementation("org.json:json:20240303") +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..33ec87b --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/io/github/himanm/tdminer/CookieStore.kt b/android/app/src/main/java/io/github/himanm/tdminer/CookieStore.kt new file mode 100644 index 0000000..9251499 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/CookieStore.kt @@ -0,0 +1,43 @@ +package io.github.himanm.tdminer + +import android.content.Context + +interface CookieStore { + fun loadCookies(): String? + fun saveCookies(cookies: String) + fun hasCookies(): Boolean = !loadCookies().isNullOrBlank() + fun loadCookieJar(): TwitchCookieJar? = loadCookies()?.let(TwitchCookieJar::parse) + fun logout() +} + +class SharedPrefsCookieStore(context: Context) : CookieStore { + private val prefs = context.getSharedPreferences("tdminer_auth", Context.MODE_PRIVATE) + + override fun loadCookies(): String? = prefs.getString(KEY_COOKIES, null) + + override fun saveCookies(cookies: String) { + prefs.edit().putString(KEY_COOKIES, cookies).apply() + } + + override fun logout() { + prefs.edit().remove(KEY_COOKIES).apply() + } + + companion object { + private const val KEY_COOKIES = "cookies" + } +} + +class MemoryCookieStore : CookieStore { + private var cookies: String? = null + + override fun loadCookies(): String? = cookies + + override fun saveCookies(cookies: String) { + this.cookies = cookies + } + + override fun logout() { + cookies = null + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MainActivity.kt b/android/app/src/main/java/io/github/himanm/tdminer/MainActivity.kt new file mode 100644 index 0000000..0a61ed9 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MainActivity.kt @@ -0,0 +1,41 @@ +package io.github.himanm.tdminer + +import android.Manifest +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.net.Uri +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (Build.VERSION.SDK_INT >= 33) { + requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 100) + } + val core = MinerCore(SharedPrefsCookieStore(this)) + intent.getStringExtra(EXTRA_COOKIES)?.takeIf { it.isNotBlank() }?.let(core::saveCookies) + setContent { + TDMinerApp( + core = core, + settingsStore = SharedPrefsMinerSettingsStore(this), + onStart = { + startForegroundService(Intent(this, MinerForegroundService::class.java)) + MinerWidgetProvider.updateAll(this, true) + }, + onStop = { + startService( + Intent(this, MinerForegroundService::class.java).setAction(ACTION_STOP), + ) + MinerWidgetProvider.updateAll(this, false) + }, + onOpenUrl = { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(it))) }, + ) + } + } + + companion object { + const val EXTRA_COOKIES = "io.github.himanm.tdminer.COOKIES" + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MinerCore.kt b/android/app/src/main/java/io/github/himanm/tdminer/MinerCore.kt new file mode 100644 index 0000000..d01ee77 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MinerCore.kt @@ -0,0 +1,154 @@ +package io.github.himanm.tdminer + +class MinerCore(private val cookieStore: CookieStore) { + var session: MinerSession = idleSession() + private set + + fun start(): MinerSession { + val jar = cookieStore.loadCookieJar() + val ready = jar?.hasAuthToken == true + session = MinerSession.running(loggedIn = ready, authReady = ready, userId = jar?.userId) + return session + } + + fun validateAuth(validator: (String) -> TwitchAuthResult = ::validateTwitchAuth): MinerSession { + val jar = cookieStore.loadCookieJar() + val token = jar?.authToken + if (token.isNullOrBlank()) { + session = session.copy(loggedIn = false, authReady = false, userId = null) + return session + } + val result = validator(token) + session = session.copy(loggedIn = result.valid, authReady = result.valid, userId = result.userId ?: jar.userId) + return session + } + + fun refreshDrops( + settings: MinerSettings = MinerSettings(), + onFetchProgress: (Int, Int) -> Unit = { _, _ -> }, + fetcher: (TwitchCookieJar, (Int, Int) -> Unit) -> List = { jar, progress -> + fetchInventorySnapshots(jar.authToken.orEmpty(), jar.userId, jar.cookieHeader, jar.deviceId, progress) + }, + ): MinerSession { + val jar = cookieStore.loadCookieJar() + if (jar?.authToken.isNullOrBlank()) return session + if (settings.priorityGames.isEmpty()) { + session = session.copy( + channel = "Priority empty", + game = "No priority selected", + campaign = "Add a priority game to start mining", + drop = "Waiting for priority", + gameImageUrl = null, + dropImageUrl = null, + rewards = emptyList(), + rewardImageUrls = emptyList(), + channels = emptyList(), + drops = emptyList(), + remainingSeconds = 0, + remaining = "--:--:--", + campaignProgress = 0f, + dropProgress = 0f, + ) + return session + } + val snapshots = fetcher(jar, onFetchProgress) + val visibleDrops = filterPrioritySnapshots(snapshots, settings.priorityGames, settings.excludedGames) + val snapshot = selectInventorySnapshot(snapshots, settings.priorityGames, settings.excludedGames) ?: run { + session = session.copy( + channel = "No matching drop", + game = "No priority drop", + campaign = "Priority/exclude filtered active drops", + drop = "Waiting for matching campaign", + gameImageUrl = null, + dropImageUrl = null, + rewards = emptyList(), + rewardImageUrls = emptyList(), + channels = emptyList(), + drops = visibleDrops, + remainingSeconds = 0, + remaining = "--:--:--", + campaignProgress = 0f, + dropProgress = 0f, + ) + return session + } + session = session.copy( + channel = if (snapshot.channel == "Twitch") session.channel.takeUnless { it == "Twitch" } ?: "Finding channel" else snapshot.channel, + game = snapshot.game, + campaign = snapshot.campaign, + drop = snapshot.drop, + gameImageUrl = snapshot.gameImageUrl, + dropImageUrl = snapshot.dropImageUrl, + rewards = snapshot.rewards, + rewardImageUrls = snapshot.rewardImageUrls, + drops = visibleDrops, + remainingSeconds = snapshot.remainingSeconds, + remaining = snapshot.remaining, + campaignProgress = snapshot.campaignProgress, + dropProgress = snapshot.dropProgress, + ) + return session + } + + fun watchOnce( + channelFetcher: (String, String) -> List = { token, game -> fetchLiveChannelsForGame(token, game) }, + watcher: (String, String, TwitchChannel) -> Boolean = ::sendWatchMinute, + ): MinerSession { + val jar = cookieStore.loadCookieJar() + val token = jar?.authToken + val userId = session.userId ?: jar?.userId + if (token.isNullOrBlank() || userId.isNullOrBlank() || !session.authReady) return session + if (!session.running) return session + if (session.game.isBlank() || session.game == "Loading drops" || session.game == "Unknown game") return session + if (session.drops.isEmpty()) return session.copy(channels = emptyList()) + val channels = channelFetcher(token, session.game) + val channel = channels.firstOrNull() ?: return session.copy(channel = "No live drops channel", channels = emptyList()) + watcher(token, userId, channel) + session = session.copy(channel = channel.displayName, channels = channels) + return session + } + + fun switchChannel( + channel: TwitchChannel, + watcher: (String, String, TwitchChannel) -> Boolean = ::sendWatchMinute, + ): MinerSession { + val jar = cookieStore.loadCookieJar() + val token = jar?.authToken + val userId = session.userId ?: jar?.userId + if (!token.isNullOrBlank() && !userId.isNullOrBlank() && session.authReady) { + watcher(token, userId, channel) + } + session = session.copy(channel = channel.displayName) + return session + } + + fun loadCategories(fetcher: (String, String?, String?, String?) -> List = ::fetchDropCategories): List { + val jar = cookieStore.loadCookieJar() ?: return emptyList() + val token = jar.authToken ?: return emptyList() + return fetcher(token, jar.userId, jar.cookieHeader, jar.deviceId) + } + + fun stop(): MinerSession { + session = idleSession() + return session + } + + fun saveCookies(cookies: String): MinerSession { + cookieStore.saveCookies(cookies) + val ready = TwitchCookieJar.parse(cookies).hasAuthToken + session = session.copy(loggedIn = ready, authReady = ready, userId = TwitchCookieJar.parse(cookies).userId) + return session + } + + fun logout(): MinerSession { + cookieStore.logout() + session = MinerSession.idle(false) + return session + } + + private fun idleSession(): MinerSession { + val jar = cookieStore.loadCookieJar() + val ready = jar?.hasAuthToken == true + return MinerSession.idle(loggedIn = ready, authReady = ready, userId = jar?.userId) + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MinerForegroundService.kt b/android/app/src/main/java/io/github/himanm/tdminer/MinerForegroundService.kt new file mode 100644 index 0000000..9089cb7 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MinerForegroundService.kt @@ -0,0 +1,155 @@ +package io.github.himanm.tdminer + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.Intent +import android.os.Build +import android.os.IBinder +import android.os.PowerManager +import androidx.core.app.NotificationCompat + +class MinerForegroundService : Service() { + private var wakeLock: PowerManager.WakeLock? = null + private var worker: Thread? = null + + override fun onCreate() { + super.onCreate() + createChannel() + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent?.action == ACTION_STOP) { + stopSession() + return START_NOT_STICKY + } + if (worker?.isAlive == true) return START_STICKY + if (SharedPrefsMinerSettingsStore(this).load().wakeLockEnabled) acquireWakeLock() + val core = MinerCore(SharedPrefsCookieStore(this)) + val session = core.start() + startForeground(NOTIFICATION_ID, notification("Validating Twitch session", session, indeterminate = true)) + MinerWidgetProvider.updateAll(this, session) + worker?.interrupt() + worker = Thread { + var firstRun = true + while (!Thread.currentThread().isInterrupted) { + if (firstRun) { + firstRun = false + try { + Thread.sleep(60_000) + } catch (_: InterruptedException) { + break + } + } + val refreshed = refresh(core, validate = false) + val title = if (refreshed.authReady) "TD Miner running" else "TD Miner login needed" + getSystemService(NotificationManager::class.java) + .notify(NOTIFICATION_ID, notification(title, refreshed, indeterminate = false)) + MinerWidgetProvider.updateAll(this, refreshed) + try { + Thread.sleep(60_000) + } catch (_: InterruptedException) { + break + } + } + }.apply { start() } + return START_STICKY + } + + override fun onDestroy() { + worker?.interrupt() + worker = null + wakeLock?.takeIf { it.isHeld }?.release() + wakeLock = null + MinerWidgetProvider.updateAll(this, false) + super.onDestroy() + } + + override fun onBind(intent: Intent?): IBinder? = null + + private fun acquireWakeLock() { + if (wakeLock?.isHeld == true) return + val power = getSystemService(POWER_SERVICE) as PowerManager + wakeLock = power.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tdminer:session").apply { + acquire(6 * 60 * 60 * 1000L) + } + } + + private fun createChannel() { + if (Build.VERSION.SDK_INT < 26) return + val channel = NotificationChannel( + CHANNEL_ID, + "TD Miner session", + NotificationManager.IMPORTANCE_LOW, + ) + getSystemService(NotificationManager::class.java).createNotificationChannel(channel) + } + + private fun notification(title: String, session: MinerSession, indeterminate: Boolean) = + NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_launcher_foreground) + .setContentTitle(title) + .setContentText(notificationText(session)) + .setOngoing(true) + .setOnlyAlertOnce(true) + .setProgress(100, (session.dropProgress * 100).toInt(), indeterminate) + .addAction(0, "STOP", stopIntent()) + .build() + + private fun notificationText(session: MinerSession): String = + if (session.authReady) { + "${session.channel} / ${session.drop} ${(session.dropProgress * 100).toInt()}%" + } else { + "Saved Twitch cookies are missing or expired" + } + + private fun refresh(core: MinerCore, validate: Boolean): MinerSession { + val validated = if (validate) { + try { + core.validateAuth() + } catch (_: Exception) { + core.session.copy(loggedIn = false, authReady = false) + } + } else { + core.session + } + return if (validated.authReady) { + try { + val settings = SharedPrefsMinerSettingsStore(this).load() + core.refreshDrops(settings) + core.watchOnce() + } catch (_: Exception) { + validated + } + } else { + validated + } + } + + private fun stopIntent(): PendingIntent { + val intent = Intent(this, MinerForegroundService::class.java).setAction(ACTION_STOP) + return PendingIntent.getService( + this, + 2, + intent, + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, + ) + } + + private fun stopSession() { + worker?.interrupt() + worker = null + stopForeground(STOP_FOREGROUND_REMOVE) + getSystemService(NotificationManager::class.java).cancel(NOTIFICATION_ID) + wakeLock?.takeIf { it.isHeld }?.release() + wakeLock = null + MinerWidgetProvider.updateAll(this, false) + stopSelf() + } + + companion object { + const val CHANNEL_ID = "tdminer-session" + const val NOTIFICATION_ID = 1 + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MinerSession.kt b/android/app/src/main/java/io/github/himanm/tdminer/MinerSession.kt new file mode 100644 index 0000000..058484b --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MinerSession.kt @@ -0,0 +1,60 @@ +package io.github.himanm.tdminer + +data class MinerSession( + val running: Boolean, + val channel: String, + val game: String, + val campaign: String, + val drop: String, + val gameImageUrl: String?, + val dropImageUrl: String?, + val rewards: List, + val rewardImageUrls: List, + val channels: List, + val drops: List, + val remainingSeconds: Int, + val remaining: String, + val campaignProgress: Float, + val dropProgress: Float, + val wakeLockActive: Boolean, + val notificationActive: Boolean, + val loggedIn: Boolean, + val authReady: Boolean, + val userId: String?, +) { + companion object { + fun running(loggedIn: Boolean = false, authReady: Boolean = loggedIn, userId: String? = null) = MinerSession( + running = true, + channel = "Finding channel", + game = "Loading drops", + campaign = "Validating Twitch session", + drop = "Waiting for inventory", + gameImageUrl = null, + dropImageUrl = null, + rewards = emptyList(), + rewardImageUrls = emptyList(), + channels = emptyList(), + drops = emptyList(), + remainingSeconds = 0, + remaining = "--:--:--", + campaignProgress = 0f, + dropProgress = 0f, + wakeLockActive = true, + notificationActive = true, + loggedIn = loggedIn, + authReady = authReady, + userId = userId, + ) + + fun idle(loggedIn: Boolean = false, authReady: Boolean = loggedIn, userId: String? = null) = running(loggedIn, authReady, userId).copy( + running = false, + channel = "Not watching", + game = "Ready", + campaign = "Press Start to mine drops", + drop = "No active drop", + remaining = "--:--:--", + wakeLockActive = false, + notificationActive = false, + ) + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MinerSettingsStore.kt b/android/app/src/main/java/io/github/himanm/tdminer/MinerSettingsStore.kt new file mode 100644 index 0000000..76d59e0 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MinerSettingsStore.kt @@ -0,0 +1,156 @@ +package io.github.himanm.tdminer + +import android.content.Context + +data class MinerSettings( + val priorityGames: List = emptyList(), + val excludedGames: List = emptyList(), + val farmUnlinkedDrops: Boolean = true, + val badgeEmoteSupport: Boolean = true, + val notificationsEnabled: Boolean = true, + val wakeLockEnabled: Boolean = true, +) + +data class CategoryCache( + val categories: List, + val savedAtMillis: Long, +) { + fun isFresh(nowMillis: Long, ttlMillis: Long = 60 * 60 * 1000L): Boolean = + categories.isNotEmpty() && nowMillis - savedAtMillis < ttlMillis +} + +interface MinerSettingsStore { + fun load(): MinerSettings + fun save(settings: MinerSettings) + fun loadCategoryCache(): CategoryCache + fun saveCategoryCache(categories: List, savedAtMillis: Long = System.currentTimeMillis()) +} + +class SharedPrefsMinerSettingsStore(context: Context) : MinerSettingsStore { + private val prefs = context.getSharedPreferences("tdminer_settings", Context.MODE_PRIVATE) + + override fun load(): MinerSettings { + migratePlaceholderDefaults() + return MinerSettings( + priorityGames = prefs.loadList(KEY_PRIORITY) ?: MinerSettings().priorityGames, + excludedGames = prefs.loadList(KEY_EXCLUDED) ?: MinerSettings().excludedGames, + farmUnlinkedDrops = prefs.getBoolean(KEY_FARM_UNLINKED, true), + badgeEmoteSupport = prefs.getBoolean(KEY_BADGE_EMOTE, true), + notificationsEnabled = prefs.getBoolean(KEY_NOTIFICATIONS, true), + wakeLockEnabled = prefs.getBoolean(KEY_WAKE_LOCK, true), + ) + } + + override fun save(settings: MinerSettings) { + prefs.edit() + .putString(KEY_PRIORITY, encodeSettingsList(settings.priorityGames)) + .putString(KEY_EXCLUDED, encodeSettingsList(settings.excludedGames)) + .putBoolean(KEY_FARM_UNLINKED, settings.farmUnlinkedDrops) + .putBoolean(KEY_BADGE_EMOTE, settings.badgeEmoteSupport) + .putBoolean(KEY_NOTIFICATIONS, settings.notificationsEnabled) + .putBoolean(KEY_WAKE_LOCK, settings.wakeLockEnabled) + .apply() + } + + override fun loadCategoryCache(): CategoryCache = + if (prefs.getInt(KEY_CATEGORIES_VERSION, 0) == CATEGORY_CACHE_VERSION) { + CategoryCache( + categories = prefs.loadCategories(KEY_CATEGORIES), + savedAtMillis = prefs.getLong(KEY_CATEGORIES_SAVED_AT, 0L), + ) + } else { + CategoryCache(emptyList(), 0L) + } + + override fun saveCategoryCache(categories: List, savedAtMillis: Long) { + prefs.edit() + .putString(KEY_CATEGORIES, encodeCategories(categories)) + .putLong(KEY_CATEGORIES_SAVED_AT, savedAtMillis) + .putInt(KEY_CATEGORIES_VERSION, CATEGORY_CACHE_VERSION) + .apply() + } + + private fun android.content.SharedPreferences.loadList(key: String): List? = + getString(key, null)?.lineSequence()?.toList()?.let(::normalizeSettingsList) + + private fun android.content.SharedPreferences.loadCategories(key: String): List = + getString(key, null) + ?.lineSequence() + ?.mapNotNull { row -> + val parts = row.split('\t', limit = 2) + if (parts.size == 2 && parts[0].isNotBlank() && parts[1].isNotBlank()) { + TwitchCategory(parts[0], parts[1]) + } else { + null + } + } + ?.toList() + ?: emptyList() + + private fun migratePlaceholderDefaults() { + val version = prefs.getInt(KEY_VERSION, 0) + if (version >= 3) return + val priority = prefs.loadList(KEY_PRIORITY) + val excluded = prefs.loadList(KEY_EXCLUDED) + val autoSeededPriority = setOf("Overwatch", "Overwatch 2", "Marvel Rivals") + prefs.edit() + .apply { + if (priority == listOf("Detroit: Become Human") || priority?.all { it in autoSeededPriority } == true) { + remove(KEY_PRIORITY) + } else { + priority?.filterNot { it == "Detroit: Become Human" }?.let { putString(KEY_PRIORITY, encodeSettingsList(it)) } + } + if (excluded == listOf("Just Chatting")) { + remove(KEY_EXCLUDED) + } else { + excluded?.filterNot { it == "Just Chatting" }?.let { putString(KEY_EXCLUDED, encodeSettingsList(it)) } + } + } + .putInt(KEY_VERSION, 3) + .apply() + } + + companion object { + private const val KEY_VERSION = "settings_version" + private const val KEY_PRIORITY = "priority_games" + private const val KEY_EXCLUDED = "excluded_games" + private const val KEY_FARM_UNLINKED = "farm_unlinked_drops" + private const val KEY_BADGE_EMOTE = "badge_emote_support" + private const val KEY_NOTIFICATIONS = "notifications_enabled" + private const val KEY_WAKE_LOCK = "wake_lock_enabled" + private const val KEY_CATEGORIES = "drop_categories" + private const val KEY_CATEGORIES_SAVED_AT = "drop_categories_saved_at" + private const val KEY_CATEGORIES_VERSION = "drop_categories_version" + private const val CATEGORY_CACHE_VERSION = 2 + } +} + +class MemoryMinerSettingsStore(settings: MinerSettings = MinerSettings()) : MinerSettingsStore { + private var settings = settings + + override fun load(): MinerSettings = settings + + override fun save(settings: MinerSettings) { + this.settings = settings.copy( + priorityGames = normalizeSettingsList(settings.priorityGames), + excludedGames = normalizeSettingsList(settings.excludedGames), + ) + } + + private var categoryCache = CategoryCache(emptyList(), 0L) + + override fun loadCategoryCache(): CategoryCache = categoryCache + + override fun saveCategoryCache(categories: List, savedAtMillis: Long) { + categoryCache = CategoryCache(categories, savedAtMillis) + } +} + +internal fun encodeSettingsList(items: Iterable): String = + normalizeSettingsList(items).joinToString("\n") + +internal fun normalizeSettingsList(items: Iterable): List = + items.map(String::trim).filter(String::isNotEmpty).distinct() + +private fun encodeCategories(categories: List): String = + categories.distinctBy { it.id }.joinToString("\n") { "${it.id}\t${it.name}" } diff --git a/android/app/src/main/java/io/github/himanm/tdminer/MinerWidgetProvider.kt b/android/app/src/main/java/io/github/himanm/tdminer/MinerWidgetProvider.kt new file mode 100644 index 0000000..e8269d0 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/MinerWidgetProvider.kt @@ -0,0 +1,70 @@ +package io.github.himanm.tdminer + +import android.app.NotificationManager +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.os.Build +import android.widget.RemoteViews + +const val ACTION_START = "io.github.himanm.tdminer.START" +const val ACTION_STOP = "io.github.himanm.tdminer.STOP" + +class MinerWidgetProvider : AppWidgetProvider() { + override fun onReceive(context: Context, intent: Intent) { + super.onReceive(context, intent) + when (intent.action) { + ACTION_START -> { + context.startForegroundService(Intent(context, MinerForegroundService::class.java)) + updateAll(context, true) + } + ACTION_STOP -> { + context.startService( + Intent(context, MinerForegroundService::class.java).setAction(ACTION_STOP), + ) + updateAll(context, false) + } + } + } + + override fun onUpdate(context: Context, manager: AppWidgetManager, ids: IntArray) { + ids.forEach { manager.updateAppWidget(it, views(context, MinerSession.idle())) } + } + + companion object { + fun updateAll(context: Context, running: Boolean) { + updateAll(context, MinerSession.idle().copy(running = running)) + } + + fun updateAll(context: Context, session: MinerSession) { + val manager = AppWidgetManager.getInstance(context) + val ids = manager.getAppWidgetIds(ComponentName(context, MinerWidgetProvider::class.java)) + ids.forEach { manager.updateAppWidget(it, views(context, session)) } + } + + private fun views(context: Context, session: MinerSession): RemoteViews { + val views = RemoteViews(context.packageName, R.layout.miner_widget) + views.setTextViewText(R.id.widget_status, if (session.running) "RUNNING" else "IDLE") + views.setTextViewText( + R.id.widget_detail, + if (session.running) "${session.channel} / ${session.drop} ${(session.dropProgress * 100).toInt()}%" else "Ready to start", + ) + views.setProgressBar(R.id.widget_progress, 100, if (session.running) (session.dropProgress * 100).toInt() else 0, false) + views.setTextViewText(R.id.widget_button, if (session.running) "STOP" else "START") + views.setOnClickPendingIntent( + R.id.widget_button, + PendingIntent.getBroadcast( + context, + if (session.running) 4 else 3, + Intent(context, MinerWidgetProvider::class.java) + .setAction(if (session.running) ACTION_STOP else ACTION_START), + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, + ), + ) + return views + } + } +} diff --git a/android/app/src/main/java/io/github/himanm/tdminer/TDMinerApp.kt b/android/app/src/main/java/io/github/himanm/tdminer/TDMinerApp.kt new file mode 100644 index 0000000..b6a6cbb --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/TDMinerApp.kt @@ -0,0 +1,1275 @@ +package io.github.himanm.tdminer + +import android.graphics.BitmapFactory +import androidx.compose.foundation.Image +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.automirrored.outlined.Logout +import androidx.compose.material.icons.automirrored.outlined.ViewList +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Campaign +import androidx.compose.material.icons.outlined.CheckCircle +import androidx.compose.material.icons.outlined.Close +import androidx.compose.material.icons.outlined.Dashboard +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.Terminal +import androidx.compose.material3.AssistChip +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemDefaults +import androidx.compose.material3.NavigationRail +import androidx.compose.material3.NavigationRailItem +import androidx.compose.material3.NavigationRailItemDefaults +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.draw.clip +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlin.math.roundToInt +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.net.URL + +private val Paper = Color(0xFFF1EBDD) +private val Ink = Color(0xFF101513) +private val Muted = Color(0xFF9DA8A1) +private val Rule = Color(0xFF34413C) +private val Green = Color(0xFF37E2B2) +private val Orange = Color(0xFFFF665A) +private val Panel = Color(0xFF18201D) +private val DisplayFont = FontFamily( + Font(R.font.roboto_condensed_regular, FontWeight.Normal), + Font(R.font.roboto_condensed_bold, FontWeight.Bold), + Font(R.font.roboto_condensed_black, FontWeight.Black), +) +private val AppColors = darkColorScheme( + primary = Green, + secondary = Green, + tertiary = Orange, + background = Ink, + surface = Panel, + surfaceVariant = Color(0xFF222C28), + onPrimary = Ink, + onSecondary = Ink, + onBackground = Paper, + onSurface = Paper, +) + +private data class AppTab(val title: String, val icon: ImageVector) + +private val Tabs = listOf( + AppTab("Home", Icons.Outlined.Dashboard), + AppTab("Drops", Icons.Outlined.Campaign), + AppTab("Channels", Icons.AutoMirrored.Outlined.ViewList), + AppTab("Prefs", Icons.Outlined.Settings), + AppTab("Logs", Icons.Outlined.Terminal), +) + +@Composable +fun TDMinerApp( + core: MinerCore, + settingsStore: MinerSettingsStore, + onStart: () -> Unit, + onStop: () -> Unit, + onOpenUrl: (String) -> Unit, +) { + var selected by remember { mutableIntStateOf(0) } + var session by remember { mutableStateOf(core.session) } + var showLogoutConfirm by remember { mutableStateOf(false) } + var notice by remember { mutableStateOf(null) } + val savedSettings = remember { settingsStore.load() } + val scope = rememberCoroutineScope() + val priority = remember { mutableStateListOf().also { it.addAll(savedSettings.priorityGames) } } + val excluded = remember { mutableStateListOf().also { it.addAll(savedSettings.excludedGames) } } + var priorityInput by remember { mutableStateOf("") } + var excludedInput by remember { mutableStateOf("") } + var availableCategories by remember { mutableStateOf(emptyList()) } + var priorityResults by remember { mutableStateOf(emptyList()) } + var excludedResults by remember { mutableStateOf(emptyList()) } + var categoriesLoading by remember { mutableStateOf(true) } + var miningLoading by remember { mutableStateOf(false) } + var loginCode by remember { mutableStateOf(null) } + var loginLoading by remember { mutableStateOf(false) } + var loginError by remember { mutableStateOf(null) } + var farmUnlinked by remember { mutableStateOf(savedSettings.farmUnlinkedDrops) } + var badgeEmote by remember { mutableStateOf(savedSettings.badgeEmoteSupport) } + var notifications by remember { mutableStateOf(savedSettings.notificationsEnabled) } + var wakeLock by remember { mutableStateOf(savedSettings.wakeLockEnabled) } + suspend fun fetchAndCacheCategories(showNotice: Boolean) { + categoriesLoading = true + try { + val categories = withContext(Dispatchers.IO) { core.loadCategories() } + if (categories.isNotEmpty()) { + availableCategories = categories + settingsStore.saveCategoryCache(categories) + if (showNotice) notice = "Drop game list reloaded" + } else if (showNotice) { + notice = "No drop games returned" + } + } catch (_: Exception) { + if (showNotice) notice = "Could not reload drop games" + } finally { + categoriesLoading = false + } + } + fun reloadCategories(showNotice: Boolean = true) { + scope.launch { fetchAndCacheCategories(showNotice) } + } + LaunchedEffect(Unit) { + val cache = settingsStore.loadCategoryCache() + availableCategories = cache.categories + if (!cache.isFresh(System.currentTimeMillis())) { + fetchAndCacheCategories(showNotice = false) + } else { + categoriesLoading = false + } + } + LaunchedEffect(priorityInput, availableCategories) { + priorityResults = matchLoadedCategories(availableCategories, priorityInput) + } + LaunchedEffect(excludedInput, availableCategories) { + excludedResults = matchLoadedCategories(availableCategories, excludedInput) + } + LaunchedEffect(session.running, session.game, session.campaign, session.drop) { + while (session.running) { + delay(1000) + session = session.let { current -> + if (!current.running || current.remainingSeconds <= 0) { + current + } else { + val next = (current.remainingSeconds - 1).coerceAtLeast(0) + val drops = current.drops.map { drop -> + if (drop.game == current.game && drop.campaign == current.campaign && drop.drop == current.drop) { + drop.copy(remainingSeconds = next) + } else { + drop + } + } + current.copy(drops = drops, remainingSeconds = next, remaining = formatRemainingSeconds(next)) + } + } + } + } + fun currentSettings(): MinerSettings { + val cleanPriority = normalizeSettingsList(priority) + return MinerSettings( + priorityGames = cleanPriority, + excludedGames = normalizeSettingsList(excluded).filterNot { it in cleanPriority.toSet() }, + farmUnlinkedDrops = farmUnlinked, + badgeEmoteSupport = badgeEmote, + notificationsEnabled = notifications, + wakeLockEnabled = wakeLock, + ) + } + fun onFetchProgress(done: Int, total: Int) { + scope.launch { + val progress = if (total <= 0) 0f else done.toFloat() / total.toFloat() + session = core.session.copy( + campaign = "Fetching drop campaigns", + drop = "$done/$total campaigns loaded", + campaignProgress = progress, + dropProgress = progress, + ) + } + } + val start = { + if (!miningLoading && !categoriesLoading) { + session = core.start() + miningLoading = true + scope.launch { + session = withContext(Dispatchers.IO) { + try { + val validated = core.validateAuth() + if (validated.authReady) { + core.refreshDrops(currentSettings(), onFetchProgress = ::onFetchProgress) + core.watchOnce() + } else { + validated + } + } catch (_: Exception) { + core.session + } + } + miningLoading = false + if (session.authReady && session.running) onStart() + } + } + Unit + } + val stop = { + session = core.stop() + onStop() + } + val logout = { + session = core.logout() + showLogoutConfirm = false + notice = "Saved Twitch session cleared" + onStop() + } + fun beginLogin() { + if (loginLoading) return + loginLoading = true + loginError = null + scope.launch { + try { + val code = withContext(Dispatchers.IO) { requestTwitchDeviceCode() } + loginCode = code + onOpenUrl(code.verificationUrl) + val cookies = withContext(Dispatchers.IO) { awaitTwitchDeviceLogin(code) } + session = core.saveCookies(cookies) + loginCode = null + notice = "Twitch account connected" + reloadCategories(showNotice = false) + } catch (error: Exception) { + loginError = error.message?.take(120) ?: "Could not start Twitch login" + } finally { + loginLoading = false + } + } + } + fun refreshSessionFromSettings() { + scope.launch { + session = withContext(Dispatchers.IO) { + try { + core.refreshDrops(currentSettings(), onFetchProgress = ::onFetchProgress) + core.watchOnce() + } catch (_: Exception) { + core.session + } + } + } + } + fun saveLists() { + saveSettings(settingsStore, priority, excluded, farmUnlinked, badgeEmote, notifications, wakeLock) + refreshSessionFromSettings() + } + fun movePriority(from: Int, to: Int) { + if (from !in priority.indices || to !in priority.indices || from == to) return + val item = priority.removeAt(from) + priority.add(to, item) + saveLists() + notice = "Priority order updated" + } + + MaterialTheme(colorScheme = AppColors) { + Surface(color = Ink, modifier = Modifier.fillMaxSize()) { + if (!session.loggedIn) { + LoginScreen(loginCode, loginLoading, loginError, ::beginLogin, onOpenUrl) + return@Surface + } + BoxWithConstraints(Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing)) { + val wide = maxWidth >= 720.dp + Scaffold( + modifier = Modifier.fillMaxSize(), + containerColor = Ink, + contentWindowInsets = WindowInsets(0, 0, 0, 0), + bottomBar = { + if (!wide) { + NavigationBar(containerColor = Ink, tonalElevation = 0.dp) { + Tabs.forEachIndexed { index, tab -> + NavigationBarItem( + selected = selected == index, + onClick = { selected = index }, + icon = { Icon(tab.icon, contentDescription = tab.title) }, + label = { Text(tab.title) }, + colors = NavigationBarItemDefaults.colors( + selectedIconColor = Green, + selectedTextColor = Green, + indicatorColor = Color.Transparent, + unselectedIconColor = Muted, + unselectedTextColor = Muted, + ), + ) + } + } + } + }, + ) { padding -> + Row(Modifier.fillMaxSize().padding(padding)) { + if (wide) { + NavigationRail(containerColor = Ink) { + Tabs.forEachIndexed { index, tab -> + NavigationRailItem( + selected = selected == index, + onClick = { selected = index }, + icon = { Icon(tab.icon, contentDescription = tab.title) }, + label = { Text(tab.title) }, + colors = NavigationRailItemDefaults.colors( + selectedIconColor = Green, + selectedTextColor = Green, + indicatorColor = Color.Transparent, + unselectedIconColor = Muted, + unselectedTextColor = Muted, + ), + ) + } + } + } + Box(Modifier.fillMaxSize()) { + when (selected) { + 0 -> Dashboard(session, miningLoading, categoriesLoading, start, stop) + 1 -> Campaigns(session, availableCategories) + 2 -> Channels(session) { channel -> + scope.launch { + session = withContext(Dispatchers.IO) { core.switchChannel(channel) } + } + notice = "Watching ${channel.displayName}" + } + 3 -> Settings( + session = session, + priority = priority, + excluded = excluded, + priorityInput = priorityInput, + excludedInput = excludedInput, + availableCategories = availableCategories, + priorityResults = priorityResults, + excludedResults = excludedResults, + categoriesLoading = categoriesLoading, + farmUnlinked = farmUnlinked, + badgeEmote = badgeEmote, + notifications = notifications, + wakeLock = wakeLock, + onPriorityInput = { priorityInput = it }, + onExcludedInput = { excludedInput = it }, + onPickPriority = { category -> + normalizeSettingsList(listOf(category.name) + priority).also { + priority.clear() + priority.addAll(it) + } + excluded.remove(category.name) + priorityInput = "" + priorityResults = emptyList() + saveLists() + notice = "Priority list updated" + }, + onPickExcluded = { category -> + normalizeSettingsList(excluded + category.name).also { + excluded.clear() + excluded.addAll(it) + } + priority.remove(category.name) + excludedInput = "" + excludedResults = emptyList() + saveLists() + notice = "Excluded list updated" + }, + onRemovePriority = { + priority.remove(it) + saveLists() + notice = "Priority list updated" + }, + onMovePriority = ::movePriority, + onRemoveExcluded = { + excluded.remove(it) + saveLists() + notice = "Excluded list updated" + }, + onFarmUnlinkedChange = { + farmUnlinked = it + saveLists() + }, + onBadgeEmoteChange = { + badgeEmote = it + saveLists() + }, + onNotificationsChange = { + notifications = it + saveLists() + }, + onWakeLockChange = { + wakeLock = it + saveLists() + }, + onReloadCategories = { reloadCategories(showNotice = true) }, + onLogoutClick = { showLogoutConfirm = true }, + ) + else -> Logs(session, availableCategories.size) + } + if (showLogoutConfirm) { + LogoutDialog( + onCancel = { showLogoutConfirm = false }, + onConfirm = logout, + ) + } + notice?.let { + Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { + NoticeBanner(it) + } + LaunchedEffect(it) { + delay(1800) + notice = null + } + } + } + } + } + } + } + } +} + +@Composable +private fun LoginScreen( + code: TwitchDeviceCode?, + loading: Boolean, + error: String?, + onBegin: () -> Unit, + onOpenUrl: (String) -> Unit, +) { + Column( + Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing).padding(28.dp), + verticalArrangement = Arrangement.SpaceBetween, + ) { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Text("TDM / MOBILE", style = mono(17, FontWeight.Black), color = Green) + Text("CONNECT\nTWITCH", style = swiss(48, FontWeight.Black)) + Text("One account. Stored privately on this device.", style = swiss(15), color = Muted) + } + ModernCard { + if (code == null) { + Text("DEVICE LOGIN", style = mono(12, FontWeight.Bold), color = Green) + Text("Twitch opens in your browser. Approve this device, then return here.", style = swiss(16, FontWeight.Bold)) + } else { + Text("ENTER THIS CODE", style = mono(12, FontWeight.Bold), color = Green) + Text(code.userCode, style = mono(38, FontWeight.Black)) + Text("Waiting for Twitch approval...", style = swiss(14), color = Muted) + } + error?.let { Text(it, style = swiss(13, FontWeight.Bold), color = Orange) } + PrimaryButton( + text = when { + code != null -> "OPEN TWITCH AGAIN" + loading -> "REQUESTING CODE" + else -> "CONNECT TWITCH" + }, + color = Green, + onClick = { if (code == null) onBegin() else onOpenUrl(code.verificationUrl) }, + enabled = code != null || !loading, + ) + } + Text("No password is entered into TD Miner.", style = mono(11), color = Muted) + } +} + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun Dashboard(session: MinerSession, miningLoading: Boolean, categoriesLoading: Boolean, onStart: () -> Unit, onStop: () -> Unit) { + val busy = miningLoading || categoriesLoading + Column(Modifier.fillMaxSize()) { + Row(Modifier.fillMaxWidth().height(68.dp).padding(horizontal = 20.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Text("TDM / MOBILE", style = mono(18, FontWeight.Black)) + Text("v19.3 ●", style = mono(13, FontWeight.Bold), color = Green) + } + Box(Modifier.fillMaxWidth().weight(1f).background(Panel)) { + NetworkImage(session.gameImageUrl, Modifier.fillMaxSize(), alignment = Alignment.TopCenter) + Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = if (session.gameImageUrl == null) 0.25f else 0.48f))) + Column(Modifier.align(Alignment.BottomStart).padding(22.dp), verticalArrangement = Arrangement.spacedBy(7.dp)) { + Text(session.game.uppercase(), style = swiss(42, FontWeight.Black)) + Text("CAMPAIGN", style = mono(12, FontWeight.Bold), color = Green) + Text(session.campaign, style = swiss(22, FontWeight.Black)) + Spacer(Modifier.height(6.dp)) + Text("WATCHING", style = mono(12, FontWeight.Bold), color = Green) + Text(session.channel, style = swiss(22, FontWeight.Black)) + } + } + Column(Modifier.padding(horizontal = 20.dp, vertical = 12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(14.dp), verticalAlignment = Alignment.CenterVertically) { + Reward(session.drop.take(10), session.dropImageUrl) + Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(5.dp)) { + Text("ACTIVE REWARD", style = mono(11, FontWeight.Bold), color = Green) + Text(session.drop, style = swiss(18, FontWeight.Black)) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + Text("${(session.dropProgress * 100).toInt()}%", style = mono(24, FontWeight.Bold), color = Green) + Text(session.remaining, style = mono(19, FontWeight.Bold)) + } + } + } + if (categoriesLoading) { + LinearProgressIndicator( + modifier = Modifier.fillMaxWidth(), + color = Green, + trackColor = Rule, + ) + } else { + ProgressLine("", "", session.dropProgress) + } + PrimaryButton( + text = if (categoriesLoading) "LOADING DROP GAMES" else if (miningLoading) "LOADING CAMPAIGNS" else if (session.running) "STOP MINING" else "START MINING", + color = if (session.running && !busy) Orange else Green, + onClick = if (session.running && !busy) onStop else onStart, + enabled = !busy, + ) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { + Metric("${session.drops.map { it.game }.distinct().size}", "DROP GAMES") + Metric("${session.channels.size}", "LIVE CHANNELS") + Metric(if (session.wakeLockActive) "ON" else "OFF", "WAKE LOCK") + } + } + } +} + +@Composable +private fun Campaigns(session: MinerSession, categories: List) = LockedPage( + title = "CAMPAIGNS", + subtitle = "${categories.size} searchable drop games · ${session.drops.size} timed drops · ${session.channels.size} live", +) { + if (session.drops.isEmpty()) { + Text("Add a priority game to show drops here. Cached games are only search suggestions.", style = swiss(14), color = Muted) + } + session.drops.groupBy { it.game }.forEach { (_, drops) -> + DropGroupCard(drops, session) + } +} + +@Composable +private fun Channels(session: MinerSession, onSwitch: (TwitchChannel) -> Unit) = LockedPage( + title = "CHANNEL SIGNAL", + subtitle = "${session.game} · Drops enabled · ${session.channels.size} online", +) { + if (session.channels.isEmpty()) { + Text("No live channels loaded yet. Press Start to fetch drops-enabled channels for ${session.game}.", style = swiss(14), color = Muted) + } + session.channels.forEach { channel -> + val watching = channel.displayName == session.channel + Row( + Modifier.fillMaxWidth().clickable { onSwitch(channel) }.border(if (watching) 1.dp else 0.dp, if (watching) Green else Color.Transparent).padding(12.dp), + horizontalArrangement = Arrangement.spacedBy(14.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Box(Modifier.size(58.dp).border(1.dp, Rule), contentAlignment = Alignment.Center) { + Text(channel.displayName.take(1).uppercase(), style = swiss(24, FontWeight.Black), color = if (watching) Green else Paper) + } + Column(Modifier.weight(1f)) { + Text(channel.displayName, style = swiss(17, FontWeight.Black)) + Text(channel.gameName, style = mono(12), color = Muted) + if (watching) Text("WATCHING", style = mono(11, FontWeight.Bold), color = Green) + } + Column(horizontalAlignment = Alignment.End) { + Text("${channel.viewers}", style = mono(14, FontWeight.Bold)) + Text("● DROPS ON", style = mono(11, FontWeight.Bold), color = Green) + } + } + } +} + +@Composable +private fun Settings( + session: MinerSession, + priority: List, + excluded: List, + priorityInput: String, + excludedInput: String, + availableCategories: List, + priorityResults: List, + excludedResults: List, + categoriesLoading: Boolean, + farmUnlinked: Boolean, + badgeEmote: Boolean, + notifications: Boolean, + wakeLock: Boolean, + onPriorityInput: (String) -> Unit, + onExcludedInput: (String) -> Unit, + onPickPriority: (TwitchCategory) -> Unit, + onPickExcluded: (TwitchCategory) -> Unit, + onRemovePriority: (String) -> Unit, + onMovePriority: (Int, Int) -> Unit, + onRemoveExcluded: (String) -> Unit, + onFarmUnlinkedChange: (Boolean) -> Unit, + onBadgeEmoteChange: (Boolean) -> Unit, + onNotificationsChange: (Boolean) -> Unit, + onWakeLockChange: (Boolean) -> Unit, + onReloadCategories: () -> Unit, + onLogoutClick: () -> Unit, +) { + var expanded by remember { mutableIntStateOf(0) } + var browser by remember { mutableIntStateOf(-1) } + Column(Modifier.fillMaxSize().padding(horizontal = 16.dp, vertical = 12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Column(Modifier.weight(1f)) { + Text("GAME ROUTING", style = swiss(30, FontWeight.Black)) + Text( + "PRIORITIZE WHAT TO MINE. EXCLUDED GAMES WON'T BE WATCHED.", + style = mono(8, FontWeight.Bold), + color = Muted, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + Spacer(Modifier.width(10.dp)) + OutlinedButton( + onClick = onReloadCategories, + enabled = !categoriesLoading, + shape = RoundedCornerShape(2.dp), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Green), + border = BorderStroke(1.dp, Green), + contentPadding = PaddingValues(0.dp), + modifier = Modifier.width(84.dp).height(40.dp), + ) { + Text(if (categoriesLoading) "LOADING" else "RELOAD", style = mono(11, FontWeight.Bold)) + } + } + CategoryListEditor( + title = "PRIORITY QUEUE", + helper = "Drag to reorder · mines top available", + addLabel = "ADD PRIORITY GAME", + items = priority, + value = priorityInput, + placeholder = "Search loaded drop game", + results = priorityResults, + categoriesLoaded = availableCategories.isNotEmpty(), + categoriesLoading = categoriesLoading, + onValueChange = onPriorityInput, + onPick = onPickPriority, + onRemove = onRemovePriority, + onMove = onMovePriority, + imageUrl = { name -> availableCategories.firstOrNull { it.name == name }?.boxArtUrl() }, + expanded = expanded == 0, + browserOpen = browser == 0, + onHeaderClick = { expanded = 0; browser = -1 }, + onAddClick = { expanded = 0; browser = if (browser == 0) -1 else 0 }, + modifier = if (expanded == 0) Modifier.weight(1f) else Modifier.height(62.dp), + ) + CategoryListEditor( + title = "EXCLUDED GAMES", + helper = "Never watched or mined", + addLabel = "ADD EXCLUDED GAME", + items = excluded, + value = excludedInput, + placeholder = "Search loaded drop game", + results = excludedResults, + categoriesLoaded = availableCategories.isNotEmpty(), + categoriesLoading = categoriesLoading, + onValueChange = onExcludedInput, + onPick = onPickExcluded, + onRemove = onRemoveExcluded, + imageUrl = { name -> availableCategories.firstOrNull { it.name == name }?.boxArtUrl() }, + expanded = expanded == 1, + browserOpen = browser == 1, + onHeaderClick = { expanded = 1; browser = -1 }, + onAddClick = { expanded = 1; browser = if (browser == 1) -1 else 1 }, + modifier = if (expanded == 1) Modifier.weight(1f) else Modifier.height(62.dp), + ) + ModernCard( + (if (expanded == 2) Modifier.weight(1f) else Modifier.height(62.dp)).clickable { expanded = 2; browser = -1 }, + ) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Column { + Text("BEHAVIOR", style = swiss(16, FontWeight.Black), color = Green) + Text("Notifications, partial rewards and power", style = swiss(10), color = Muted) + } + Text(if (expanded == 2) "−" else "+", style = mono(18, FontWeight.Bold), color = Green) + } + if (expanded == 2) { + ToggleRow("Partial badges & emotes", badgeEmote, onBadgeEmoteChange, "Accept partial progress") + ToggleRow("Farm unlinked", farmUnlinked, onFarmUnlinkedChange, "Allow drops from unlinked channels") + ToggleRow("Notifications", notifications, onNotificationsChange, "Show mining alerts") + ToggleRow("Wake lock", wakeLock, onWakeLockChange, "Keep device awake while mining") + Text("${availableCategories.size} DROP GAMES CACHED", style = mono(10, FontWeight.Bold), color = Muted) + } + } + OutlinedButton( + onClick = onLogoutClick, + shape = RoundedCornerShape(2.dp), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Orange), + border = BorderStroke(1.dp, Orange), + modifier = Modifier.fillMaxWidth().height(44.dp), + ) { + Icon(Icons.AutoMirrored.Outlined.Logout, contentDescription = null, tint = Orange) + Spacer(Modifier.size(6.dp)) + Text("LOG OUT", color = Orange) + } + } +} + +@Composable +private fun Logs(session: MinerSession, categoryCount: Int) = LockedPage( + title = "EVENT STREAM", + trailing = "● LIVE", +) { + Row(Modifier.fillMaxWidth().border(1.dp, Rule).padding(16.dp), horizontalArrangement = Arrangement.SpaceEvenly) { + Metric(if (session.running) "RUN" else "IDLE", session.remaining) + Metric("NET", "OK") + Metric("COOKIE", if (session.loggedIn) "SAVED" else "MISSING") + } + listOf( + "10:42:31" to "Watching ${session.channel}", + "10:41:07" to "Selected ${session.game}", + "10:40:22" to "Loaded ${session.drops.size} drops", + "10:39:41" to "Found $categoryCount drop games", + "10:38:56" to if (session.authReady) "Authentication restored" else "Authentication required", + ).forEachIndexed { index, event -> + Row(Modifier.fillMaxWidth().height(72.dp).border(0.dp, Color.Transparent), verticalAlignment = Alignment.CenterVertically) { + Text(event.first, style = mono(13), color = Muted, modifier = Modifier.width(92.dp)) + Text(if (index == 0) "◉" else "◇", color = Green, style = mono(18), modifier = Modifier.width(44.dp)) + Text(event.second, style = mono(14), modifier = Modifier.weight(1f)) + } + Box(Modifier.fillMaxWidth().height(1.dp).background(Rule)) + } +} + +@Composable +private fun LockedPage( + title: String, + subtitle: String? = null, + trailing: String? = null, + content: @Composable ColumnScope.() -> Unit, +) { + Column( + Modifier.fillMaxSize().padding(horizontal = 20.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp), + ) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Text(title, style = swiss(34, FontWeight.Black)) + trailing?.let { Text(it, style = mono(12, FontWeight.Bold), color = Green) } + } + subtitle?.let { Text(it, style = mono(12), color = Muted) } + Box(Modifier.fillMaxWidth().height(1.dp).background(Rule)) + Column( + Modifier.fillMaxWidth().weight(1f).verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(16.dp), + content = content, + ) + } +} + +@Composable +private fun ModernCard(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { + ElevatedCard( + colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface), + shape = RoundedCornerShape(4.dp), + elevation = CardDefaults.elevatedCardElevation(0.dp), + modifier = modifier.fillMaxWidth().border(1.dp, Rule, RoundedCornerShape(4.dp)), + ) { + Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp), content = content) + } +} + +@Composable +private fun Artwork(session: MinerSession) { + Row(horizontalArrangement = Arrangement.spacedBy(14.dp), verticalAlignment = Alignment.CenterVertically) { + ArtworkBlock(session.game.replace(": ", ":\n"), session.gameImageUrl) + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + Text(session.campaign, style = swiss(22, FontWeight.Bold)) + RewardRow(session) + } + } +} + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun DropGroupCard(drops: List, session: MinerSession) { + val first = drops.first() + Column(Modifier.fillMaxWidth().border(1.dp, Rule)) { + Box(Modifier.fillMaxWidth().height(150.dp).background(Panel)) { + NetworkImage(first.gameImageUrl, Modifier.fillMaxSize()) + Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.45f))) + Column(Modifier.align(Alignment.BottomStart).padding(16.dp)) { + Text(first.game.uppercase(), style = swiss(28, FontWeight.Black)) + Text("${drops.map { it.campaign }.distinct().size} CAMPAIGNS · ${drops.size} TIMED DROPS", style = mono(11), color = Muted) + if (drops.any { it.game == session.game }) Text("● MINING", style = mono(12, FontWeight.Bold), color = Green) + } + } + drops.forEach { drop -> + val selected = drop.game == session.game && drop.campaign == session.campaign && drop.drop == session.drop + DropItemRow(drop, selected, session.running, if (selected) session.remaining else drop.remaining) + } + } +} + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun DropItemRow(drop: TwitchDropSnapshot, selected: Boolean, running: Boolean, remaining: String) { + Row( + Modifier.fillMaxWidth().background(if (selected) Green.copy(alpha = 0.07f) else Panel).border(if (selected) 1.dp else 0.dp, if (selected) Green else Color.Transparent).padding(10.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + NetworkImage(drop.dropImageUrl ?: drop.rewardImageUrls.firstOrNull(), Modifier.size(58.dp).clip(RoundedCornerShape(3.dp))) + Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) { + Text(drop.drop, style = swiss(14, FontWeight.Bold)) + Text(drop.campaign, style = swiss(11), color = Muted) + ProgressLine("", "", drop.dropProgress) + } + Column(horizontalAlignment = Alignment.End) { + Text("${(drop.dropProgress * 100).toInt()}%", style = mono(16, FontWeight.Bold), color = if (selected) Green else Paper) + Text(remaining, style = mono(12, FontWeight.Bold), color = if (selected && running) Green else Muted) + } + } +} + +@Composable +private fun ArtworkBlock(text: String, imageUrl: String? = null, modifier: Modifier = Modifier.size(width = 96.dp, height = 128.dp)) { + Box( + modifier.background(Ink, RoundedCornerShape(2.dp)), + contentAlignment = Alignment.BottomStart, + ) { + NetworkImage(imageUrl, Modifier.fillMaxSize()) + if (imageUrl != null) Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.25f))) + Text(text, style = swiss(14, FontWeight.Bold), color = Paper, modifier = Modifier.padding(10.dp)) + } +} + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun RewardRow(session: MinerSession) { + val rewards = session.rewards.ifEmpty { listOf(session.drop) } + FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { + rewards.take(4).forEachIndexed { index, reward -> + Reward(reward.take(10), session.rewardImageUrls.getOrNull(index)) + } + } +} + +@Composable +private fun SettingRow(label: String, value: String) { + Row(Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surface, RoundedCornerShape(20.dp)).padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween) { + Text(label, style = swiss(15, FontWeight.Bold)) + Text(value, style = swiss(15), color = Muted) + } +} + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun CategoryListEditor( + title: String, + helper: String, + addLabel: String, + items: List, + value: String, + placeholder: String, + results: List, + categoriesLoaded: Boolean, + categoriesLoading: Boolean, + onValueChange: (String) -> Unit, + onPick: (TwitchCategory) -> Unit, + onRemove: (String) -> Unit, + onMove: ((Int, Int) -> Unit)? = null, + imageUrl: (String) -> String? = { null }, + expanded: Boolean, + browserOpen: Boolean, + onHeaderClick: () -> Unit, + onAddClick: () -> Unit, + modifier: Modifier = Modifier, +) { + ModernCard(modifier) { + Row( + Modifier.fillMaxWidth().clickable(onClick = onHeaderClick), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Column { + Text(title, style = swiss(16, FontWeight.Black), color = Green) + Text(helper, style = swiss(11), color = Muted) + } + Text("${items.size} ${if (expanded) "−" else "+"}", style = mono(13, FontWeight.Bold), color = Green) + } + if (expanded) { + if (!browserOpen) { + LazyColumn( + modifier = Modifier.fillMaxWidth().weight(1f).border(1.dp, Rule, RoundedCornerShape(2.dp)), + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { + itemsIndexed(items) { index, item -> + if (onMove == null) { + CompactListRow(item, imageUrl(item), onRemove) + } else { + DraggablePriorityRow( + item = item, + imageUrl = imageUrl(item), + index = index, + lastIndex = items.lastIndex, + onMove = onMove, + onRemove = onRemove, + ) + } + } + } + OutlinedButton( + onClick = onAddClick, + shape = RoundedCornerShape(2.dp), + colors = ButtonDefaults.outlinedButtonColors(contentColor = Green), + border = BorderStroke(1.dp, Green), + modifier = Modifier.fillMaxWidth().height(46.dp), + ) { Text("+ $addLabel", style = mono(12, FontWeight.Bold)) } + } else { + BrowseCategoryPanel( + title = if (onMove == null) "ADD TO EXCLUDED" else "ADD TO PRIORITY", + value = value, + results = results, + categoriesLoaded = categoriesLoaded, + categoriesLoading = categoriesLoading, + onValueChange = onValueChange, + onPick = onPick, + onClose = onAddClick, + modifier = Modifier.weight(1f), + ) + } + } + } +} + +@Composable +private fun BrowseCategoryPanel( + title: String, + value: String, + results: List, + categoriesLoaded: Boolean, + categoriesLoading: Boolean, + onValueChange: (String) -> Unit, + onPick: (TwitchCategory) -> Unit, + onClose: () -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier.border(1.dp, Rule).padding(10.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) { + Text(title, style = mono(12, FontWeight.Bold), color = Green) + TextButton(onClick = onClose) { Text("×", style = swiss(20), color = Green) } + } + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = { Text("Search drop games") }, + singleLine = true, + shape = RoundedCornerShape(2.dp), + colors = TextFieldDefaults.colors( + focusedContainerColor = Color.Transparent, + unfocusedContainerColor = Color.Transparent, + focusedIndicatorColor = Green, + unfocusedIndicatorColor = Rule, + cursorColor = Green, + ), + modifier = Modifier.fillMaxWidth().height(56.dp), + ) + when { + categoriesLoading -> Text("Loading drop categories first...", style = swiss(13), color = Muted) + value.length >= 2 && !categoriesLoaded -> Text("Drop categories are still loading", style = swiss(13, FontWeight.Bold), color = Orange) + value.length >= 2 && results.isEmpty() -> Text("No active or upcoming drop game found", style = swiss(13, FontWeight.Bold), color = Orange) + } + LazyColumn(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) { + itemsIndexed(results) { _, category -> + OutlinedButton( + onClick = { onPick(category) }, + colors = ButtonDefaults.outlinedButtonColors(contentColor = Paper), + border = BorderStroke(1.dp, Rule), + shape = RoundedCornerShape(2.dp), + modifier = Modifier.fillMaxWidth().height(46.dp), + ) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + Row(Modifier.weight(1f), horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) { + NetworkImage(category.boxArtUrl(), Modifier.size(width = 54.dp, height = 34.dp).clip(RoundedCornerShape(2.dp))) + Text(category.name, style = swiss(14, FontWeight.Bold), maxLines = 1, overflow = TextOverflow.Ellipsis) + } + Text(if (title.contains("EXCLUDED")) "EXCLUDE" else "ADD", style = swiss(12, FontWeight.Bold), color = Green) + } + } + } + } + } +} + +@Composable +private fun DraggablePriorityRow( + item: String, + imageUrl: String?, + index: Int, + lastIndex: Int, + onMove: (Int, Int) -> Unit, + onRemove: (String) -> Unit, +) { + var dragY by remember { mutableStateOf(0f) } + Row( + Modifier + .fillMaxWidth() + .offset { IntOffset(0, dragY.roundToInt()) } + .background(Panel) + .padding(horizontal = 10.dp, vertical = 7.dp) + .pointerInput(index, lastIndex) { + detectDragGesturesAfterLongPress( + onDragEnd = { dragY = 0f }, + onDragCancel = { dragY = 0f }, + onDrag = { change, dragAmount -> + change.consume() + dragY += dragAmount.y + when { + dragY > 48f && index < lastIndex -> { + onMove(index, index + 1) + dragY = 0f + } + dragY < -48f && index > 0 -> { + onMove(index, index - 1) + dragY = 0f + } + } + }, + ) + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row(horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) { + Text("⋮⋮", style = mono(16, FontWeight.Bold), color = Green) + NetworkImage(imageUrl, Modifier.size(width = 68.dp, height = 42.dp).clip(RoundedCornerShape(2.dp))) + Text("${(index + 1).toString().padStart(2, '0')}", style = mono(13, FontWeight.Bold), color = Muted) + Text(item, style = swiss(14, FontWeight.Bold)) + } + TextButton(onClick = { onRemove(item) }) { + Text("×", style = swiss(20), color = Green) + } + } +} + +@Composable +private fun CompactListRow(item: String, imageUrl: String?, onRemove: (String) -> Unit) { + Row( + Modifier.fillMaxWidth().background(Panel).padding(horizontal = 10.dp, vertical = 7.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + NetworkImage(imageUrl, Modifier.size(width = 68.dp, height = 42.dp).clip(RoundedCornerShape(2.dp))) + Spacer(Modifier.width(10.dp)) + Text(item, style = swiss(14, FontWeight.Bold), modifier = Modifier.weight(1f)) + TextButton(onClick = { onRemove(item) }) { Text("×", style = swiss(20), color = Green) } + } +} + +@Composable +private fun ToggleRow(label: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, subtitle: String? = null) { + Row( + Modifier.fillMaxWidth().height(if (subtitle == null) 44.dp else 48.dp).border(1.dp, Rule) + .clickable { onCheckedChange(!checked) }.padding(horizontal = 10.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Column(Modifier.weight(1f)) { + Text(label, style = swiss(12, FontWeight.Bold)) + subtitle?.let { Text(it, style = swiss(9), color = Muted) } + } + Box( + Modifier.size(36.dp) + .background(if (checked) Green else Ink) + .border(1.dp, if (checked) Green else Muted), + contentAlignment = Alignment.Center, + ) { + Text(if (checked) "ON" else "OFF", style = mono(9, FontWeight.Black), color = if (checked) Ink else Muted) + } + } +} + +@Composable +private fun NoticeBanner(text: String) { + Surface( + color = Panel, + shape = RoundedCornerShape(4.dp), + border = BorderStroke(1.dp, Green), + shadowElevation = 0.dp, + ) { + Row(Modifier.padding(horizontal = 16.dp, vertical = 12.dp), horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Outlined.CheckCircle, contentDescription = null, tint = Green, modifier = Modifier.size(18.dp)) + Column { + Text("TD MINER", style = mono(9, FontWeight.Bold), color = Green) + Text(text, style = swiss(13, FontWeight.Bold), color = Paper) + } + } + } +} + +@Composable +private fun LogoutDialog(onCancel: () -> Unit, onConfirm: () -> Unit) { + Dialog(onDismissRequest = onCancel) { + Column( + Modifier.fillMaxWidth().background(Panel).border(1.dp, Green).padding(22.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Text("ACCOUNT / SESSION", style = mono(10, FontWeight.Bold), color = Green) + Text("LOG OUT?", style = swiss(30, FontWeight.Black), color = Paper) + Text( + "This clears saved Twitch cookies from private app storage. You will need to login again.", + style = swiss(14), + color = Muted, + ) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { + OutlinedButton( + onClick = onCancel, + shape = RoundedCornerShape(2.dp), + border = BorderStroke(1.dp, Rule), + modifier = Modifier.weight(1f), + ) { + Text("CANCEL", style = mono(11, FontWeight.Bold), color = Paper) + } + OutlinedButton( + onClick = onConfirm, + shape = RoundedCornerShape(2.dp), + border = BorderStroke(1.dp, Orange), + modifier = Modifier.weight(1f), + ) { + Text("LOG OUT", style = mono(11, FontWeight.Bold), color = Orange) + } + } + } + } +} + +@Composable +private fun PrimaryButton(text: String, color: Color, onClick: () -> Unit, enabled: Boolean = true) { + Button( + onClick = onClick, + enabled = enabled, + colors = ButtonDefaults.buttonColors(containerColor = color), + shape = RoundedCornerShape(2.dp), + modifier = Modifier.fillMaxWidth().height(58.dp), + ) { + Text(text, style = mono(16, FontWeight.Bold), color = Ink) + } +} + +@Composable +private fun Metric(value: String, label: String) { + Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(2.dp)) { + Text(value, style = mono(18, FontWeight.Black), color = Green) + Text(label, style = mono(9, FontWeight.Bold), color = Muted) + } +} + +@Composable +private fun ProgressLine(label: String, value: String, progress: Float) { + val clamped = progress.coerceIn(0f, 1f) + Text("$label $value", style = swiss(14, FontWeight.Bold)) + Box(Modifier.fillMaxWidth().height(4.dp).background(Rule)) { + Box(Modifier.fillMaxWidth(clamped).height(4.dp).background(Green)) + } +} + +@Composable +private fun Chip(text: String, color: Color) { + Text(text, color = color, style = swiss(12, FontWeight.Bold), modifier = Modifier.border(1.dp, color).padding(horizontal = 8.dp, vertical = 4.dp)) +} + +@Composable +private fun Reward(text: String, imageUrl: String? = null) { + Box(Modifier.size(54.dp).background(Panel).border(1.dp, Rule), contentAlignment = Alignment.Center) { + NetworkImage(imageUrl, Modifier.fillMaxSize()) + if (imageUrl != null) Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.18f))) + Text(text, style = swiss(10, FontWeight.Bold), color = if (imageUrl == null) Ink else Paper, textAlign = TextAlign.Center, modifier = Modifier.padding(4.dp)) + } +} + +@Composable +private fun NetworkImage(url: String?, modifier: Modifier = Modifier, alignment: Alignment = Alignment.Center) { + var bitmap by remember(url) { mutableStateOf(null) } + LaunchedEffect(url) { + bitmap = if (url.isNullOrBlank()) { + null + } else { + withContext(Dispatchers.IO) { + runCatching { URL(url).openStream().use(BitmapFactory::decodeStream) }.getOrNull() + } + } + } + bitmap?.let { + Image(it.asImageBitmap(), contentDescription = null, contentScale = ContentScale.Crop, alignment = alignment, modifier = modifier) + } +} + +private fun matchLoadedCategories(categories: List, query: String): List { + val trimmed = query.trim() + if (trimmed.length < 2) return emptyList() + return categories.filter { it.name.contains(trimmed, ignoreCase = true) }.take(8) +} + +private fun TwitchCategory.boxArtUrl() = "https://static-cdn.jtvnw.net/ttv-boxart/$id-285x380.jpg" + +private fun saveSettings( + settingsStore: MinerSettingsStore, + priority: List, + excluded: List, + farmUnlinked: Boolean, + badgeEmote: Boolean, + notifications: Boolean, + wakeLock: Boolean, +) { + val cleanPriority = normalizeSettingsList(priority) + val cleanExcluded = normalizeSettingsList(excluded).filterNot { it in cleanPriority.toSet() } + settingsStore.save( + MinerSettings( + priorityGames = cleanPriority, + excludedGames = cleanExcluded, + farmUnlinkedDrops = farmUnlinked, + badgeEmoteSupport = badgeEmote, + notificationsEnabled = notifications, + wakeLockEnabled = wakeLock, + ), + ) +} + +private fun swiss(size: Int, weight: FontWeight = FontWeight.Normal) = + androidx.compose.ui.text.TextStyle(fontSize = size.sp, fontWeight = weight, fontFamily = DisplayFont, color = Paper) + +private fun mono(size: Int, weight: FontWeight = FontWeight.Normal) = + androidx.compose.ui.text.TextStyle(fontSize = size.sp, fontWeight = weight, fontFamily = FontFamily.Monospace, color = Paper) diff --git a/android/app/src/main/java/io/github/himanm/tdminer/TwitchAuth.kt b/android/app/src/main/java/io/github/himanm/tdminer/TwitchAuth.kt new file mode 100644 index 0000000..04c5e1a --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/TwitchAuth.kt @@ -0,0 +1,27 @@ +package io.github.himanm.tdminer + +import java.net.HttpURLConnection +import java.net.URL + +data class TwitchAuthResult(val valid: Boolean, val userId: String? = null) + +fun validateTwitchAuth(authToken: String): TwitchAuthResult { + val connection = (URL("https://id.twitch.tv/oauth2/validate").openConnection() as HttpURLConnection).apply { + requestMethod = "GET" + connectTimeout = 10_000 + readTimeout = 10_000 + setRequestProperty("Authorization", "OAuth $authToken") + } + return try { + if (connection.responseCode != HttpURLConnection.HTTP_OK) { + TwitchAuthResult(false) + } else { + TwitchAuthResult(true, connection.inputStream.bufferedReader().use { it.readText() }.jsonValue("user_id")) + } + } finally { + connection.disconnect() + } +} + +internal fun String.jsonValue(name: String): String? = + Regex(""""${Regex.escape(name)}"\s*:\s*"([^"]*)"""").find(this)?.groupValues?.get(1) diff --git a/android/app/src/main/java/io/github/himanm/tdminer/TwitchCookieJar.kt b/android/app/src/main/java/io/github/himanm/tdminer/TwitchCookieJar.kt new file mode 100644 index 0000000..e8bf91f --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/TwitchCookieJar.kt @@ -0,0 +1,39 @@ +package io.github.himanm.tdminer + +data class TwitchCookieJar( + val raw: String, + val authToken: String?, + val userId: String?, + val deviceId: String?, + val cookieHeader: String, +) { + val hasAuthToken: Boolean = !authToken.isNullOrBlank() + + companion object { + fun parse(raw: String): TwitchCookieJar { + return TwitchCookieJar( + raw = raw, + authToken = raw.cookieValue("auth-token"), + userId = raw.cookieValue("persistent"), + deviceId = raw.cookieValue("unique_id"), + cookieHeader = raw.cookiePairs().associate { it.first to it.second }.entries.joinToString("; ") { "${it.key}=${it.value}" }, + ) + } + } +} + +private fun String.cookieValue(name: String): String? { + val match = Regex( + """"${Regex.escape(name)}"\s*:\s*\{[^}]*"value"\s*:\s*"([^"]*)"""", + RegexOption.DOT_MATCHES_ALL, + ).find(this) + return match?.groupValues?.get(1)?.replace("\\\"", "\"") +} + +private fun String.cookiePairs(): List> = + Regex( + """"key"\s*:\s*"([^"]+)"[\s\S]*?"value"\s*:\s*"([^"]*)"""", + RegexOption.DOT_MATCHES_ALL, + ).findAll(this).map { match -> + match.groupValues[1].replace("\\\"", "\"") to match.groupValues[2].replace("\\\"", "\"") + }.toList() diff --git a/android/app/src/main/java/io/github/himanm/tdminer/TwitchDeviceLogin.kt b/android/app/src/main/java/io/github/himanm/tdminer/TwitchDeviceLogin.kt new file mode 100644 index 0000000..1315adf --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/TwitchDeviceLogin.kt @@ -0,0 +1,84 @@ +package io.github.himanm.tdminer + +import java.net.HttpURLConnection +import java.net.URL +import java.net.URLEncoder +import java.util.UUID + +data class TwitchDeviceCode( + val deviceCode: String, + val userCode: String, + val verificationUrl: String, + val intervalSeconds: Int, + val expiresInSeconds: Int, + val deviceId: String, +) + +fun requestTwitchDeviceCode(): TwitchDeviceCode { + val deviceId = UUID.randomUUID().toString().replace("-", "") + val response = postForm( + "https://id.twitch.tv/oauth2/device", + mapOf("client_id" to ANDROID_APP_CLIENT_ID, "scopes" to ""), + deviceId, + ) + return TwitchDeviceCode( + deviceCode = response.jsonValue("device_code") ?: error("Twitch did not return a device code"), + userCode = response.jsonValue("user_code") ?: error("Twitch did not return a user code"), + verificationUrl = response.jsonValue("verification_uri") ?: "https://www.twitch.tv/activate", + intervalSeconds = response.jsonInt("interval") ?: 5, + expiresInSeconds = response.jsonInt("expires_in") ?: 1800, + deviceId = deviceId, + ) +} + +fun awaitTwitchDeviceLogin(code: TwitchDeviceCode): String { + val deadline = System.currentTimeMillis() + code.expiresInSeconds * 1000L + while (System.currentTimeMillis() < deadline) { + Thread.sleep(code.intervalSeconds * 1000L) + val result = runCatching { + postForm( + "https://id.twitch.tv/oauth2/token", + mapOf( + "client_id" to ANDROID_APP_CLIENT_ID, + "device_code" to code.deviceCode, + "grant_type" to "urn:ietf:params:oauth:grant-type:device_code", + ), + code.deviceId, + ) + }.getOrNull() ?: continue + val token = result.jsonValue("access_token") ?: continue + val userId = validateTwitchAuth(token).userId.orEmpty() + return deviceLoginCookies(token, userId, code.deviceId) + } + error("Twitch login code expired") +} + +internal fun deviceLoginCookies(token: String, userId: String, deviceId: String): String = + """{"twitch.tv|":{"auth-token":{"key":"auth-token","value":"$token"},"persistent":{"key":"persistent","value":"$userId"},"unique_id":{"key":"unique_id","value":"$deviceId"}}}""" + +private fun postForm(url: String, fields: Map, deviceId: String): String { + val body = fields.entries.joinToString("&") { (key, value) -> + "${URLEncoder.encode(key, "UTF-8")}=${URLEncoder.encode(value, "UTF-8")}" + } + val connection = (URL(url).openConnection() as HttpURLConnection).apply { + requestMethod = "POST" + connectTimeout = 10_000 + readTimeout = 10_000 + doOutput = true + setRequestProperty("Client-Id", ANDROID_APP_CLIENT_ID) + setRequestProperty("Content-Type", "application/x-www-form-urlencoded") + setRequestProperty("X-Device-Id", deviceId) + } + return try { + connection.outputStream.use { it.write(body.toByteArray()) } + val stream = if (connection.responseCode < 400) connection.inputStream else connection.errorStream + val response = stream?.bufferedReader()?.use { it.readText() }.orEmpty() + if (connection.responseCode >= 400) error(response) + response + } finally { + connection.disconnect() + } +} + +private fun String.jsonInt(name: String): Int? = + Regex(""""${Regex.escape(name)}"\s*:\s*(\d+)""").find(this)?.groupValues?.get(1)?.toIntOrNull() diff --git a/android/app/src/main/java/io/github/himanm/tdminer/TwitchGql.kt b/android/app/src/main/java/io/github/himanm/tdminer/TwitchGql.kt new file mode 100644 index 0000000..10d69c0 --- /dev/null +++ b/android/app/src/main/java/io/github/himanm/tdminer/TwitchGql.kt @@ -0,0 +1,701 @@ +package io.github.himanm.tdminer + +import org.json.JSONArray +import org.json.JSONObject +import org.json.JSONTokener +import java.io.ByteArrayOutputStream +import java.net.HttpURLConnection +import java.net.URL +import java.time.Instant +import java.util.Base64 +import java.util.zip.GZIPOutputStream + +data class TwitchCategory(val id: String, val name: String) +data class TwitchChannel( + val id: String, + val login: String, + val displayName: String, + val broadcastId: String, + val gameId: String, + val gameName: String, + val viewers: Int, +) + +data class TwitchDropSnapshot( + val campaignId: String = "", + val dropId: String = "", + val game: String, + val campaign: String, + val drop: String, + val channel: String = "Twitch", + val gameImageUrl: String? = null, + val dropImageUrl: String? = null, + val rewards: List = emptyList(), + val rewardImageUrls: List = emptyList(), + val currentMinutes: Int, + val requiredMinutes: Int, + val remainingSeconds: Int = (requiredMinutes - currentMinutes).coerceAtLeast(0) * 60, + val campaignProgress: Float, +) { + val dropProgress: Float = progress(currentMinutes, requiredMinutes) + val remaining: String = formatRemainingSeconds(remainingSeconds) + val dropKey: String = listOf(campaignId, dropId, game, campaign, drop).joinToString("\u0000") +} + +fun fetchInventorySnapshots(authToken: String): List { + return fetchInventorySnapshots(authToken, userId = null, cookieHeader = null, deviceId = null) +} + +fun fetchInventorySnapshots( + authToken: String, + userId: String?, + cookieHeader: String?, + deviceId: String?, + onCampaignProgress: (Int, Int) -> Unit = { _, _ -> }, +): List { + val body = JSONObject() + .put("operationName", "Inventory") + .put("variables", JSONObject().put("fetchRewardCampaigns", false)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", INVENTORY_HASH), + ), + ) + .toString() + val campaignsBody = JSONObject() + .put("operationName", "ViewerDropsDashboard") + .put("variables", JSONObject().put("fetchRewardCampaigns", false)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", CAMPAIGNS_HASH), + ), + ) + .toString() + val inventoryRaw = postGql(authToken, body, cookieHeader, deviceId) + val campaignsRaw = postGql(authToken, campaignsBody, cookieHeader, deviceId) + val claimedBenefits = parseClaimedBenefits(inventoryRaw) + return (parseInventorySnapshots(inventoryRaw) + + fetchCampaignDetailSnapshots(authToken, userId, cookieHeader, deviceId, parseDropCampaignIds(campaignsRaw), claimedBenefits, onCampaignProgress)) + .distinctBy { it.dropKey } +} + +fun fetchInventorySnapshot( + authToken: String, + priorityGames: List = emptyList(), + excludedGames: List = emptyList(), +): TwitchDropSnapshot? { + return selectInventorySnapshot(fetchInventorySnapshots(authToken), priorityGames, excludedGames) +} + +fun fetchDropCategories(authToken: String, userId: String? = null): List { + return fetchDropCategories(authToken, userId, cookieHeader = null, deviceId = null) +} + +fun fetchDropCategories( + authToken: String, + userId: String?, + cookieHeader: String?, + deviceId: String?, +): List { + val inventoryBody = JSONObject() + .put("operationName", "Inventory") + .put("variables", JSONObject().put("fetchRewardCampaigns", false)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", INVENTORY_HASH), + ), + ) + .toString() + val campaignsBody = JSONObject() + .put("operationName", "ViewerDropsDashboard") + .put("variables", JSONObject().put("fetchRewardCampaigns", false)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", CAMPAIGNS_HASH), + ), + ) + .toString() + val inventoryRaw = postGql(authToken, inventoryBody, cookieHeader, deviceId) + val campaignsRaw = postGql(authToken, campaignsBody, cookieHeader, deviceId) + return normalizeCategories( + parseInventoryCategories(inventoryRaw) + + parseDropCategories(campaignsRaw) + + fetchCampaignDetailCategories(authToken, userId, cookieHeader, deviceId, parseDropCampaignIds(campaignsRaw)), + ) +} + +private fun fetchCampaignDetailCategories( + authToken: String, + userId: String?, + cookieHeader: String?, + deviceId: String?, + campaignIds: List, +): List { + if (campaignIds.isEmpty()) return emptyList() + val channelLogin = userId.orEmpty() + return campaignIds.flatMap { campaignId -> + val body = JSONObject() + .put("operationName", "DropCampaignDetails") + .put("variables", JSONObject().put("channelLogin", channelLogin).put("dropID", campaignId)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", CAMPAIGN_DETAILS_HASH), + ), + ) + .toString() + runCatching { parseCampaignDetailCategories(postGql(authToken, body, cookieHeader, deviceId)) }.getOrDefault(emptyList()) + } +} + +private fun fetchCampaignDetailSnapshots( + authToken: String, + userId: String?, + cookieHeader: String?, + deviceId: String?, + campaignIds: List, + claimedBenefits: Map, + onProgress: (Int, Int) -> Unit, +): List { + if (campaignIds.isEmpty()) return emptyList() + val channelLogin = userId.orEmpty() + val total = campaignIds.size + return campaignIds.flatMapIndexed { index, campaignId -> + val body = JSONObject() + .put("operationName", "DropCampaignDetails") + .put("variables", JSONObject().put("channelLogin", channelLogin).put("dropID", campaignId)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", CAMPAIGN_DETAILS_HASH), + ), + ) + .toString() + runCatching { parseCampaignDetailSnapshots(postGql(authToken, body, cookieHeader, deviceId), claimedBenefits) } + .also { onProgress(index + 1, total) } + .getOrDefault(emptyList()) + } +} + +fun fetchLiveChannelsForGame(authToken: String, gameName: String, limit: Int = 30): List { + val slug = fetchGameSlug(authToken, gameName) ?: gameName.toGameSlug() + val body = JSONObject() + .put("operationName", "DirectoryPage_Game") + .put( + "variables", + JSONObject() + .put("limit", limit) + .put("slug", slug) + .put("imageWidth", 50) + .put("includeCostreaming", false) + .put( + "options", + JSONObject() + .put("broadcasterLanguages", JSONArray()) + .put("freeformTags", JSONObject.NULL) + .put("includeRestricted", JSONArray().put("SUB_ONLY_LIVE")) + .put("recommendationsContext", JSONObject().put("platform", "web")) + .put("sort", "RELEVANCE") + .put("systemFilters", JSONArray().put("DROPS_ENABLED")) + .put("tags", JSONArray()) + .put("requestID", "JIRA-VXP-2397"), + ) + .put("sortTypeIsRecency", false), + ) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", GAME_DIRECTORY_HASH), + ), + ) + .toString() + return parseLiveChannels(postGql(authToken, body)) +} + +fun fetchGameSlug(authToken: String, gameName: String): String? { + val body = JSONObject() + .put("operationName", "DirectoryGameRedirect") + .put("variables", JSONObject().put("name", gameName)) + .put( + "extensions", + JSONObject().put( + "persistedQuery", + JSONObject() + .put("version", 1) + .put("sha256Hash", GAME_REDIRECT_HASH), + ), + ) + .toString() + return parseGameSlug(postGql(authToken, body)) +} + +internal fun parseGameSlug(raw: String): String? = + JSONObject(raw) + .optJSONObject("data") + ?.optJSONObject("game") + ?.optString("slug") + ?.takeIf(String::isNotBlank) + +fun sendWatchMinute(authToken: String, userId: String, channel: TwitchChannel): Boolean { + val event = JSONObject() + .put("event", "minute-watched") + .put( + "properties", + JSONObject() + .put("broadcast_id", channel.broadcastId) + .put("channel_id", channel.id) + .put("channel", channel.login) + .put("client_time", Instant.now().toString()) + .put("game", channel.gameName) + .put("game_id", channel.gameId) + .put("hidden", false) + .put("is_live", true) + .put("live", true) + .put("logged_in", true) + .put("minutes_logged", 1) + .put("muted", false) + .put("user_id", userId), + ) + val body = JSONObject() + .put("query", "\n mutation SendEvents(${'$'}input: SendSpadeEventsInput!) {\n sendSpadeEvents(input: ${'$'}input) {\n statusCode\n}\n}\n") + .put( + "variables", + JSONObject().put( + "input", + JSONObject() + .put("data", gzipBase64(JSONArray().put(event).toString())) + .put("repository", "twilight") + .put("encoding", "GZIP_B64"), + ), + ) + .toString() + val statusCode = JSONObject(postGql(authToken, body)) + .optJSONObject("data") + ?.optJSONObject("sendSpadeEvents") + ?.optInt("statusCode", 0) + ?: 0 + return statusCode == 204 +} + +internal fun parseLiveChannels(raw: String): List { + val edges = JSONObject(raw) + .optJSONObject("data") + ?.optJSONObject("game") + ?.optJSONObject("streams") + ?.optJSONArray("edges") + ?: return emptyList() + return buildList { + for (index in 0 until edges.length()) { + val node = edges.optJSONObject(index)?.optJSONObject("node") ?: continue + val broadcaster = node.optJSONObject("broadcaster") ?: continue + val game = node.optJSONObject("game") ?: continue + val channelId = broadcaster.optString("id") + val login = broadcaster.optString("login") + val broadcastId = node.optString("id") + val gameId = game.optString("id") + val name = gameName(game).orFallback("") + if (channelId.isBlank() || login.isBlank() || broadcastId.isBlank() || gameId.isBlank() || name.isBlank()) continue + add( + TwitchChannel( + id = channelId, + login = login, + displayName = broadcaster.optString("displayName").orFallback(login), + broadcastId = broadcastId, + gameId = gameId, + gameName = name, + viewers = node.optInt("viewersCount", 0), + ), + ) + } + } +} + +internal fun parseInventoryCategories(raw: String): List { + val campaigns = JSONObject(raw) + .optJSONObject("data") + ?.optJSONObject("currentUser") + ?.optJSONObject("inventory") + ?.optJSONArray("dropCampaignsInProgress") + ?: return emptyList() + val activeOrUpcoming = JSONArray() + for (index in 0 until campaigns.length()) { + val campaign = campaigns.optJSONObject(index) ?: continue + if (campaign.isActiveOrUpcomingCampaign()) activeOrUpcoming.put(campaign) + } + return campaignGames(activeOrUpcoming) +} + +internal fun parseDropCategories(raw: String): List { + val campaigns = JSONObject(raw) + .optJSONObject("data") + ?.optJSONObject("currentUser") + ?.optJSONArray("dropCampaigns") + ?: return emptyList() + val activeCampaigns = JSONArray() + for (index in 0 until campaigns.length()) { + val campaign = campaigns.optJSONObject(index) ?: continue + if (campaign.optString("status") in setOf("ACTIVE", "UPCOMING", "") && campaign.isActiveOrUpcomingCampaign()) { + activeCampaigns.put(campaign) + } + } + return campaignGames(activeCampaigns) +} + +internal fun parseDropCampaignIds(raw: String): List { + val campaigns = JSONObject(raw) + .optJSONObject("data") + ?.optJSONObject("currentUser") + ?.optJSONArray("dropCampaigns") + ?: return emptyList() + return buildList { + for (index in 0 until campaigns.length()) { + val campaign = campaigns.optJSONObject(index) ?: continue + val id = campaign.optString("id") + if (id.isNotBlank() && campaign.optString("status") in setOf("ACTIVE", "UPCOMING", "") && campaign.isActiveOrUpcomingCampaign()) { + add(id) + } + } + } +} + +internal fun parseCampaignDetailCategories(raw: String): List { + val value = JSONTokener(raw).nextValue() + val responses = when (value) { + is JSONArray -> value.objects() + is JSONObject -> listOf(value) + else -> emptyList() + } + return responses.mapNotNull { response -> + val campaign = response + .optJSONObject("data") + ?.optJSONObject("user") + ?.optJSONObject("dropCampaign") + categoryFromGame(campaign?.optJSONObject("game")) + } +} + +internal fun parseCampaignDetailSnapshots(raw: String, claimedBenefits: Map = emptyMap()): List { + val value = JSONTokener(raw).nextValue() + val responses = when (value) { + is JSONArray -> value.objects() + is JSONObject -> listOf(value) + else -> emptyList() + } + return responses.flatMap { response -> + val campaign = response + .optJSONObject("data") + ?.optJSONObject("user") + ?.optJSONObject("dropCampaign") + campaignSnapshot(campaign, claimedBenefits)?.let(::listOf) ?: emptyList() + } +} + +private fun campaignSnapshot(campaign: JSONObject?, claimedBenefits: Map = emptyMap()): TwitchDropSnapshot? { + if (campaign == null || !campaign.isActiveCampaign()) return null + val drops = campaign.optJSONArray("timeBasedDrops") ?: JSONArray() + val drop = firstEarnableDrop(drops, claimedBenefits) ?: return null + val current = drop.optJSONObject("self")?.optInt("currentMinutesWatched", 0) ?: 0 + val required = drop.optInt("requiredMinutesWatched", 0) + if (required <= 0) return null + val game = campaign.optJSONObject("game") + val rewards = rewardNames(drop) + val rewardImages = rewardImages(drop) + return TwitchDropSnapshot( + campaignId = campaign.optString("id"), + dropId = drop.optString("id").orFallback(drop.optString("dropID")), + game = gameName(game).orFallback("Unknown game"), + campaign = campaign.optString("name").orFallback("Drops campaign"), + drop = drop.optString("name").orFallback(rewards.firstOrNull() ?: "Drop reward"), + gameImageUrl = imageUrl(game?.optString("boxArtURL")), + dropImageUrl = imageUrl(drop.deepString("imageAssetURL", "imageURL", "imageUrl") ?: rewardImages.firstOrNull()), + rewards = rewards, + rewardImageUrls = rewardImages, + currentMinutes = current, + requiredMinutes = required, + campaignProgress = campaignProgress(drops), + ) +} + +private fun campaignGames(campaigns: JSONArray): List { + return buildList { + for (index in 0 until campaigns.length()) { + val game = campaigns.optJSONObject(index)?.optJSONObject("game") ?: continue + categoryFromGame(game)?.let(::add) + } + } +} + +private fun categoryFromGame(game: JSONObject?): TwitchCategory? { + val id = game?.optString("id").orEmpty() + val name = gameName(game).orFallback("") + return if (id.isNotBlank() && name.isNotBlank()) TwitchCategory(id, name) else null +} + +private fun normalizeCategories(categories: List): List = + categories.distinctBy { it.id }.sortedBy { it.name.lowercase() } + +internal fun String.toGameSlug(): String = + lowercase() + .replace("'", "") + .replace(Regex("\\W+"), "-") + .trim('-') + .replace(Regex("-{2,}"), "-") + +private fun gzipBase64(text: String): String { + val output = ByteArrayOutputStream() + GZIPOutputStream(output).use { it.write(text.toByteArray(Charsets.UTF_8)) } + return Base64.getEncoder().encodeToString(output.toByteArray()) +} + +private fun gameName(game: JSONObject?): String? = + game?.optString("displayName").orFallback(game?.optString("name") ?: "") + +internal fun parseInventorySnapshot(raw: String): TwitchDropSnapshot? { + return parseInventorySnapshots(raw).minByOrNull { it.remainingSeconds } +} + +internal fun parseInventorySnapshots(raw: String): List { + val root = JSONObject(raw) + val claimedBenefits = parseClaimedBenefits(root) + val campaigns = root + .optJSONObject("data") + ?.optJSONObject("currentUser") + ?.optJSONObject("inventory") + ?.optJSONArray("dropCampaignsInProgress") + ?: return emptyList() + return buildList { + for (campaignIndex in 0 until campaigns.length()) { + val campaign = campaigns.optJSONObject(campaignIndex) ?: continue + if (!campaign.isActiveCampaign()) continue + val drops = campaign.optJSONArray("timeBasedDrops") ?: JSONArray() + val drop = firstEarnableDrop(drops, claimedBenefits) ?: continue + val current = drop.optJSONObject("self")?.optInt("currentMinutesWatched", 0) ?: 0 + val required = drop.optInt("requiredMinutesWatched", 0) + if (required <= 0) continue + val game = campaign.optJSONObject("game") + val rewards = rewardNames(drop) + val rewardImages = rewardImages(drop) + add( + TwitchDropSnapshot( + campaignId = campaign.optString("id"), + dropId = drop.optString("id").orFallback(drop.optString("dropID")), + game = gameName(game).orFallback("Unknown game"), + campaign = campaign.optString("name").orFallback("Drops campaign"), + drop = drop.optString("name").orFallback(rewards.firstOrNull() ?: "Drop reward"), + gameImageUrl = imageUrl(game?.optString("boxArtURL")), + dropImageUrl = imageUrl(drop.deepString("imageAssetURL", "imageURL", "imageUrl") ?: rewardImages.firstOrNull()), + rewards = rewards, + rewardImageUrls = rewardImages, + currentMinutes = current, + requiredMinutes = required, + campaignProgress = campaignProgress(drops), + ), + ) + } + } +} + +private fun JSONObject.isActiveCampaign(now: Instant = Instant.now()): Boolean { + if (optString("status").equals("EXPIRED", ignoreCase = true)) return false + val start = parseInstant("startAt") + val end = parseInstant("endAt") + return (start == null || !now.isBefore(start)) && (end == null || now.isBefore(end)) +} + +private fun JSONObject.isActiveOrUpcomingCampaign(now: Instant = Instant.now()): Boolean { + if (optString("status").equals("EXPIRED", ignoreCase = true)) return false + val end = parseInstant("endAt") + return end == null || now.isBefore(end) +} + +private fun JSONObject.parseInstant(key: String): Instant? = + optString(key).takeIf(String::isNotBlank)?.let { runCatching { Instant.parse(it) }.getOrNull() } + +internal fun selectInventorySnapshot( + snapshots: List, + priorityGames: List, + excludedGames: List, +): TwitchDropSnapshot? { + val priority = priorityGames.map { it.lowercase() } + if (priority.isEmpty()) return null + val allowed = filterPrioritySnapshots(snapshots, priorityGames, excludedGames) + return priority.firstNotNullOfOrNull { wanted -> + allowed + .filter { gameMatches(wanted, it.game.lowercase()) && it.requiredMinutes > 0 && it.currentMinutes < it.requiredMinutes } + .minByOrNull { it.remainingSeconds } + } +} + +internal fun filterPrioritySnapshots( + snapshots: List, + priorityGames: List, + excludedGames: List, +): List { + val priority = priorityGames.map { it.lowercase() } + if (priority.isEmpty()) return emptyList() + val excluded = excludedGames.map { it.lowercase() }.toSet() + return priority.flatMap { wanted -> + snapshots + .filterNot { it.game.lowercase() in excluded } + .filter { gameMatches(wanted, it.game.lowercase()) } + .sortedWith(compareBy { it.currentMinutes >= it.requiredMinutes }.thenBy { it.remainingSeconds }) + } +} + +private fun gameMatches(wanted: String, actual: String): Boolean = + wanted == actual || wanted in actual || actual in wanted + +private fun postGql(authToken: String, body: String, cookieHeader: String? = null, deviceId: String? = null): String { + val connection = (URL("https://gql.twitch.tv/gql").openConnection() as HttpURLConnection).apply { + requestMethod = "POST" + connectTimeout = 10_000 + readTimeout = 10_000 + doOutput = true + setRequestProperty("Client-Id", ANDROID_APP_CLIENT_ID) + setRequestProperty("User-Agent", ANDROID_APP_USER_AGENT) + setRequestProperty("Accept", "*/*") + setRequestProperty("Accept-Language", "en-US") + setRequestProperty("Pragma", "no-cache") + setRequestProperty("Cache-Control", "no-cache") + setRequestProperty("Authorization", "OAuth $authToken") + setRequestProperty("Origin", "https://www.twitch.tv") + setRequestProperty("Referer", "https://www.twitch.tv") + setRequestProperty("Content-Type", "application/json") + if (!cookieHeader.isNullOrBlank()) setRequestProperty("Cookie", cookieHeader) + if (!deviceId.isNullOrBlank()) setRequestProperty("X-Device-Id", deviceId) + } + return try { + connection.outputStream.use { it.write(body.toByteArray(Charsets.UTF_8)) } + val stream = if (connection.responseCode < 400) connection.inputStream else connection.errorStream + stream.bufferedReader().use { it.readText() } + } finally { + connection.disconnect() + } +} + +private fun firstEarnableDrop(drops: JSONArray, claimedBenefits: Map = emptyMap()): JSONObject? { + for (index in 0 until drops.length()) { + val drop = drops.optJSONObject(index) ?: continue + if (drop.optInt("requiredMinutesWatched", 0) <= 0) continue + val self = drop.optJSONObject("self") + val current = self?.optInt("currentMinutesWatched", 0) ?: 0 + val claimed = self?.optBoolean("isClaimed", false) ?: drop.wasClaimedAsGameEvent(claimedBenefits) + if (!claimed && current < drop.optInt("requiredMinutesWatched", 0)) return drop + } + return null +} + +private fun parseClaimedBenefits(raw: String): Map = parseClaimedBenefits(JSONObject(raw)) + +private fun parseClaimedBenefits(root: JSONObject): Map { + val events = root.optJSONObject("data")?.optJSONObject("currentUser")?.optJSONObject("inventory") + ?.optJSONArray("gameEventDrops") ?: return emptyMap() + return buildMap { + for (index in 0 until events.length()) { + val event = events.optJSONObject(index) ?: continue + val id = event.optString("id") + val awarded = event.parseInstant("lastAwardedAt") + if (id.isNotBlank() && awarded != null) put(id, awarded) + } + } +} + +private fun JSONObject.wasClaimedAsGameEvent(claimedBenefits: Map): Boolean { + val start = parseInstant("startAt") ?: return false + val end = parseInstant("endAt") ?: return false + val benefits = optJSONArray("benefitEdges") ?: return false + val awards = benefits.objects().mapNotNull { edge -> + claimedBenefits[edge.optJSONObject("benefit")?.optString("id")] + } + return awards.isNotEmpty() && awards.all { !it.isBefore(start) && it.isBefore(end) } +} + +private fun campaignProgress(drops: JSONArray): Float { + var current = 0 + var required = 0 + for (index in 0 until drops.length()) { + val drop = drops.optJSONObject(index) ?: continue + val dropRequired = drop.optInt("requiredMinutesWatched", 0).coerceAtLeast(0) + required += dropRequired + current += (drop.optJSONObject("self")?.optInt("currentMinutesWatched", 0) ?: 0).coerceAtMost(dropRequired) + } + return progress(current, required) +} + +private fun rewardNames(drop: JSONObject): List = + drop.optJSONArray("benefitEdges")?.objects() + ?.mapNotNull { it.optJSONObject("benefit")?.optString("name")?.takeIf(String::isNotBlank) } + ?: emptyList() + +private fun rewardImages(drop: JSONObject): List = + drop.optJSONArray("benefitEdges")?.objects() + ?.mapNotNull { it.optJSONObject("benefit")?.deepString("imageAssetURL", "imageURL", "imageUrl")?.let(::imageUrl) } + ?: emptyList() + +private fun JSONArray.objects(): List = + buildList { + for (index in 0 until length()) optJSONObject(index)?.let(::add) + } + +private fun JSONObject.deepString(vararg keys: String): String? { + for (key in keys) optString(key).takeIf(String::isNotBlank)?.let { return it } + for (key in keys()) { + when (val value = opt(key)) { + is JSONObject -> value.deepString(*keys)?.let { return it } + is JSONArray -> value.objects().firstNotNullOfOrNull { it.deepString(*keys) }?.let { return it } + } + } + return null +} + +private fun imageUrl(url: String?): String? = + url?.takeIf(String::isNotBlank) + ?.replace("{width}", "300") + ?.replace("{height}", "400") + +private fun progress(current: Int, required: Int): Float = + if (required <= 0) 0f else (current.toFloat() / required.toFloat()).coerceIn(0f, 1f) + +internal fun formatRemainingSeconds(seconds: Int): String { + val safeSeconds = seconds.coerceAtLeast(0) + val hours = safeSeconds / 3600 + val mins = (safeSeconds % 3600) / 60 + val secs = safeSeconds % 60 + return "%02d:%02d:%02d".format(hours, mins, secs) +} + +private fun String?.orFallback(fallback: String): String = + if (isNullOrBlank()) fallback else this + +internal const val ANDROID_APP_CLIENT_ID = "kd1unb4b3q4t58fwlpcbzcbnm76a8fp" +private const val ANDROID_APP_USER_AGENT = "Dalvik/2.1.0 (Linux; U; Android 16; SM-S911B Build/TP1A.220624.014) tv.twitch.android.app/25.3.0/2503006" +private const val INVENTORY_HASH = "d86775d0ef16a63a33ad52e80eaff963b2d5b72fada7c991504a57496e1d8e4b" +private const val CAMPAIGNS_HASH = "5a4da2ab3d5b47c9f9ce864e727b2cb346af1e3ea8b897fe8f704a97ff017619" +private const val CAMPAIGN_DETAILS_HASH = "039277bf98f3130929262cc7c6efd9c141ca3749cb6dca442fc8ead9a53f77c1" +private const val GAME_DIRECTORY_HASH = "cb5dc816e139dcb8a118f14b4b677d59abc224a4b016c4bc2bb00a47fe0ddec4" +private const val GAME_REDIRECT_HASH = "1f0300090caceec51f33c5e20647aceff9017f740f223c3c532ba6fa59f6b6cc" diff --git a/android/app/src/main/res/drawable-nodpi/tdminer_app_icon.png b/android/app/src/main/res/drawable-nodpi/tdminer_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4893d4e9763ef8096ce83a8bbbc6e80334c9f796 GIT binary patch literal 1211860 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 z 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