diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 29650ec..fdc2a62 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,6 +12,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' @@ -24,11 +25,11 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Bitburner(please complete the following information):** - - OS: [e.g. iOS] - - Platform[e.g. steam] - - Version [e.g. 22] - - IDE Version [e.g. 2022.1, 221.4501.155] +- OS: [e.g. iOS] +- Platform[e.g. steam] +- Version [e.g. 22] +- IDE Version [e.g. 2022.1, 221.4501.155] **Additional context** Add any other context about the problem here. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1a980ab..6666e53 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,21 +33,26 @@ jobs: changelog: ${{ steps.properties.outputs.changelog }} steps: + # Free GitHub Actions Environment Disk Space + - name: Maximize Build Space + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc # Check out current repository - name: Fetch Sources - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # Validate wrapper - name: Gradle Wrapper Validation - uses: gradle/wrapper-validation-action@v1.0.4 + uses: gradle/wrapper-validation-action@v1.0.5 # Setup Java 11 environment for the next steps - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: distribution: zulu java-version: 11 - cache: gradle # Set environment variables - name: Export Properties @@ -61,48 +66,51 @@ jobs: CHANGELOG="${CHANGELOG//'%'/'%25'}" CHANGELOG="${CHANGELOG//$'\n'/'%0A'}" CHANGELOG="${CHANGELOG//$'\r'/'%0D'}" - echo "::set-output name=version::$VERSION" echo "::set-output name=name::$NAME" echo "::set-output name=changelog::$CHANGELOG" echo "::set-output name=pluginVerifierHomeDir::~/.pluginVerifier" - ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier - # Run tests - name: Run Tests - run: ./gradlew test + run: ./gradlew check # Collect Tests Result of failed tests - name: Collect Tests Result if: ${{ failure() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: tests-result path: ${{ github.workspace }}/build/reports/tests + # Upload Kover report to CodeCov + - name: Upload Code Coverage Report + uses: codecov/codecov-action@v3 + with: + files: ${{ github.workspace }}/build/reports/kover/xml/report.xml + # Cache Plugin Verifier IDEs - name: Setup Plugin Verifier IDEs Cache - uses: actions/cache@v2.1.6 + uses: actions/cache@v3 with: path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }} # Run Verify Plugin task and IntelliJ Plugin Verifier tool - name: Run Plugin Verification tasks - run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }} -Djava.system.class.loader=com.intellij.util.lang.PathClassLoader + run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }} # Collect Plugin Verifier Result - name: Collect Plugin Verifier Result if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: pluginVerifier-result path: ${{ github.workspace }}/build/reports/pluginVerifier # Run Qodana inspections - #- name: Qodana - Code Inspection - # uses: JetBrains/qodana-action@v4.1.0 + - name: Qodana - Code Inspection + uses: JetBrains/qodana-action@v2022.2.3 # Prepare plugin archive content for creating artifact - name: Prepare Plugin Artifact @@ -112,12 +120,10 @@ jobs: cd ${{ github.workspace }}/build/distributions FILENAME=`ls *.zip` unzip "$FILENAME" -d content - - echo "::set-output name=filename::$FILENAME" - + echo "::set-output name=filename::${FILENAME:0:-4}" # Store already-built plugin as an artifact for downloading - name: Upload artifact - uses: actions/upload-artifact@v2.2.4 + uses: actions/upload-artifact@v3 with: name: ${{ steps.artifact.outputs.filename }} path: ./build/distributions/content/*/* @@ -129,11 +135,13 @@ jobs: if: github.event_name != 'pull_request' needs: build runs-on: ubuntu-latest + permissions: + contents: write steps: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 # Remove old release drafts by using the curl request for the available releases with draft flag - name: Remove Old Release Drafts @@ -143,7 +151,6 @@ jobs: gh api repos/{owner}/{repo}/releases \ --jq '.[] | select(.draft == true) | .id' \ | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{} - # Create new release draft - which is not publicly visible and requires manual acceptance - name: Create Release Draft env: diff --git a/.github/workflows/codacy-analysis.yml b/.github/workflows/codacy-analysis.yml index 9bc6320..4be03c0 100644 --- a/.github/workflows/codacy-analysis.yml +++ b/.github/workflows/codacy-analysis.yml @@ -44,7 +44,7 @@ jobs: # Adjust severity of non-security issues gh-code-scanning-compat: true # Force 0 exit code to allow SARIF file generation - # This will handover control about PR rejection to the GitHub side + # This will hand over control about PR rejection to the GitHub side max-allowed-issues: 2147483647 # Upload the SARIF file generated in the previous step diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0bcf2d5..9699266 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ name: Release on: release: - types: [prereleased, released] + types: [ prereleased, released ] jobs: diff --git a/.run/Run IDE for UI Tests.run.xml b/.run/Run IDE for UI Tests.run.xml index 02c92bc..055112b 100644 --- a/.run/Run IDE for UI Tests.run.xml +++ b/.run/Run IDE for UI Tests.run.xml @@ -1,24 +1,24 @@ - + - - true true false - + diff --git a/.run/Run Plugin Tests.run.xml b/.run/Run Plugin Tests.run.xml index ae9ae13..02843dd 100644 --- a/.run/Run Plugin Tests.run.xml +++ b/.run/Run Plugin Tests.run.xml @@ -1,24 +1,24 @@ - - - - - - - true - true - false - - + + + + + + + true + true + false + + diff --git a/.run/Run Plugin Verification.run.xml b/.run/Run Plugin Verification.run.xml index 3a8d688..bf8bccc 100644 --- a/.run/Run Plugin Verification.run.xml +++ b/.run/Run Plugin Verification.run.xml @@ -1,26 +1,27 @@ - + - - true true false - - \ No newline at end of file + diff --git a/.run/Run Qodana.run.xml b/.run/Run Qodana.run.xml index d8fe0c6..c59db97 100644 --- a/.run/Run Qodana.run.xml +++ b/.run/Run Qodana.run.xml @@ -3,15 +3,15 @@ - - true true false - + diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bbcefa..02ab28a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,21 +4,49 @@ ## [Unreleased] +## [0.0.5] + +### Added + +- Added listeners when a file or folder is created, modified, copied, renamed, deleted or moved +- Added ToDo's list. + +### Changed + +- Updated README with specific instructions about how to use the plugin +- Updated Plugin org.jetbrains.intellij to 1.9.0 +- Updated the notifications using emojis and given more information in the message +- Refactored the source code + +### Fixed + +- Fixed typos in SECURITY markdown. + ## [0.0.4] -Updated Plugin org.jetbrains.kotlin.jvm to 1.7.10 -Updated Plugin org.jetbrains.intellij to 1.7.0 -Added Plugin com.github.ben-manes.versions -Updated `pluginUntilBuild` to 222.* -Updated used Gradle Version to 7.5 +### Added + +- Added Plugin com.github.ben-manes.versions + +### Changed + +- Updated Plugin org.jetbrains.kotlin.jvm to 1.7.10 +- Updated Plugin org.jetbrains.intellij to 1.7.0 +- Updated `pluginUntilBuild` to 222.* +- Updated used Gradle Version to 7.5 ## [0.0.3] -added PR #12 +### Added + +- Added PR #12 ## [0.0.2] ### Added -- Filewatcher which automatically pushes to Bitburner +- Added Filewatcher which automatically pushes to Bitburner + +### Changed + - Updated IDEA Version diff --git a/README.md b/README.md index f1d8f19..df3319c 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,39 @@ To do this you need to get the API Auth Token from Bitburner. - Using IDE built-in plugin system: - Settings/Preferences > Plugins > Marketplace > Search for " - Bitburner-Plugin" > + Settings/Preferences > Plugins > Marketplace > + Search for "Bitburner-Plugin" > Install Plugin - Manually: - Download the [latest release](https://github.com/Serverfrog/Bitburner-Plugin/releases/latest) and install it manually using + Download the [latest release](https://github.com/Serverfrog/Bitburner-Plugin/releases/latest) and install it manually + using Settings/Preferences > Plugins > ⚙️ > Install plugin from disk... +## Usage + +### Bitburner game + +- Enable the server + - If the game starts in full screen, press F9 to display as a window. + - Go to the top bar menu on _API Server_ > _Enable server_ +- Copy the token + - Go to the top bar menu on _API Server_ > _Copy Auth Token_ + +### WebStorm or IntelliJ IDE + +- Paste the token in the IDE. + - Open the settings (Ctrl+Alt+S), it will open a window. + - On the left side, select _Tools_ > _BitBurner-Sync_. + - On the right side is an option _Authentication Token_, paste the token inside the text box. + - Click on the _Ok_ button. +- Start using. + - In your project using your IDE, add one script (.js or .script), then it will show in your IDE a notification + about the success action or an error. + - You can create, modify, delete, rename or move scripts or folders with scripts. They will update automatically in + the Bitburner game. + --- Plugin based on the [IntelliJ Platform Plugin Template][template]. diff --git a/SECURITY.md b/SECURITY.md index 05ebf06..71abf43 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,6 +6,6 @@ The Supported Version is always the latest one Provided on the Jetbrains Plugin ## Reporting a Vulnerability -Send me an Email at admin@serverfrog.de or Discord under Serverfrog#0001 would be the fastes way to do this. +Email me at admin@serverfrog.de or Discord under Serverfrog#0001 would be the fastest way to do this. -Due to the fact that this Project is not an Income Source it can take some days at worst that i will answer. ;) +Due to the fact that this Project is not an Income Source it can take some days at worst that I will answer. ;) diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..8d89a3f --- /dev/null +++ b/TODO.md @@ -0,0 +1,15 @@ +# Bitburner-Plugin TODOs + +## Synchronize + +- Pushed all the scripts in my WebStorm/IntelliJ project to Bitburner game. +- Retrieved all the scripts from Bitburner game to my project in WebStorm/IntelliJ. + +## IDE: action menu + +- Create one group for Bitburner. When the user expands the secondary menu from the file in the project or in the + editor. + - Clicking in the file _hello.js_ to show the secondary menu, it will show in the first row the menu + _Bitburner >_. When the mouse is over this option it will expand and show three options: _Push this file_, + _Push all files_, _Pull all files_. +- Add a confirmation alert when the options are _Push all files_ or _Pull all files_. diff --git a/build.gradle.kts b/build.gradle.kts index 34a554a..5d5bc5b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,15 +8,15 @@ plugins { // Java support id("java") // Kotlin support - id("org.jetbrains.kotlin.jvm") version "1.7.10" + id("org.jetbrains.kotlin.jvm") version "1.8.0-RC2" // Gradle IntelliJ Plugin - id("org.jetbrains.intellij") version "1.7.0" + id("org.jetbrains.intellij") version "1.11.0" // Gradle Changelog Plugin - id("org.jetbrains.changelog") version "1.3.1" + id("org.jetbrains.changelog") version "2.0.0" // Gradle Qodana Plugin id("org.jetbrains.qodana") version "0.1.13" // Dependency Updates - id("com.github.ben-manes.versions") version "0.42.0" + id("com.github.ben-manes.versions") version "0.44.0" } group = properties("pluginGroup") diff --git a/gradle.properties b/gradle.properties index 2004369..c790736 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,31 +1,24 @@ # IntelliJ Platform Artifacts Repositories # -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html - -pluginGroup = com.github.serverfrog.bitburnerplugin -pluginName = Bitburner-Plugin +pluginGroup=com.github.serverfrog.bitburnerplugin +pluginName=Bitburner-Plugin # SemVer format -> https://semver.org -pluginVersion=0.0.4 - +pluginVersion=0.0.5 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. -pluginSinceBuild=203 +pluginSinceBuild=222 pluginUntilBuild=222.* - # IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties platformType=IC platformVersion=LATEST-EAP-SNAPSHOT - # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 -platformPlugins = - +platformPlugins= # Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3 -javaVersion = 11 - +javaVersion=17 # Gradle Releases -> https://github.com/gradle/gradle/releases -gradleVersion=7.5 - +gradleVersion=7.6 # Opt-out flag for bundling Kotlin standard library. # See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details. # suppress inspection "UnusedProperty" -kotlin.stdlib.default.dependency = false +kotlin.stdlib.default.dependency=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102..ae04661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..c53aefa 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions $var, ${var}, ${var:-default}, ${var+SET}, +# ${var#prefix}, ${var%suffix}, and $( cmd ); +# * compound commands having a testable exit status, especially case; +# * various built-in commands including command, set, and ulimit. # # Important for patching: # diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroup.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroup.kt index 7b835d6..ee8c1f7 100644 --- a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroup.kt +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerActionGroup.kt @@ -1,16 +1,15 @@ package com.github.serverfrog.bitburnerplugin.action +import com.github.serverfrog.bitburnerplugin.bitburner.Bitburner.Companion.extensions import com.intellij.openapi.actionSystem.ActionGroup import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys -val extensions = arrayListOf("js", "script", "ns", "txt") class BitburnerActionGroup : ActionGroup() { private val projectViewPopup = "ProjectViewPopup" private val editorPopup = "EditorPopup" - override fun getChildren(e: AnActionEvent?): Array { var actions = emptyArray() @@ -19,14 +18,13 @@ class BitburnerActionGroup : ActionGroup() { ) { actions = append(actions, BitburnerPushAction()) } + return actions } - - fun append(arr: Array, element: AnAction): Array { + private fun append(arr: Array, element: AnAction): Array { val list: MutableList = arr.toMutableList() list.add(element) return list.toTypedArray() } - } diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushAction.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushAction.kt index 15a98d3..1892c85 100644 --- a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushAction.kt +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/action/BitburnerPushAction.kt @@ -1,15 +1,18 @@ package com.github.serverfrog.bitburnerplugin.action import com.github.serverfrog.bitburnerplugin.MyBundle -import com.github.serverfrog.bitburnerplugin.bitburner.PushToBitburner +import com.github.serverfrog.bitburnerplugin.bitburner.Bitburner +import com.github.serverfrog.bitburnerplugin.bitburner.Bitburner.Companion.getFileName import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.CommonDataKeys -class BitburnerPushAction() : AnAction(MyBundle.message("pushActionLabel")) { +class BitburnerPushAction : AnAction(MyBundle.message("pushActionLabel")) { override fun actionPerformed(e: AnActionEvent) { val file = e.dataContext.getData(CommonDataKeys.VIRTUAL_FILE)?.canonicalFile!! - PushToBitburner.pushToBitburner(file, e.project!!) + val fileName = getFileName(file.path) + val fileContent = file.contentsToByteArray() + Bitburner.push(fileName, fileContent) } } diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/Bitburner.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/Bitburner.kt new file mode 100644 index 0000000..b3cc096 --- /dev/null +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/Bitburner.kt @@ -0,0 +1,109 @@ +package com.github.serverfrog.bitburnerplugin.bitburner + +import com.github.serverfrog.bitburnerplugin.MyBundle +import com.github.serverfrog.bitburnerplugin.config.BitburnerSettings +import com.intellij.ide.DataManager +import com.intellij.notification.NotificationGroup +import com.intellij.notification.NotificationGroupManager +import com.intellij.notification.NotificationType +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.project.Project +import java.net.URI +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import java.util.* +import java.util.regex.Matcher +import java.util.regex.Pattern + +class Bitburner { + companion object { + + // List of File Extensions BitBurner recognize + val extensions = arrayListOf("js", "script") + + private val uri: URI = URI.create("http://localhost:9990/") + + private val notificationGroup: NotificationGroup = NotificationGroupManager.getInstance() + .getNotificationGroup(MyBundle.message("groupId")) + + fun push(fileName: String, fileContent: ByteArray) { + val client = HttpClient.newBuilder().build() + val request = HttpRequest.newBuilder() + .header("Authorization", "Bearer " + BitburnerSettings.getAuthToken()) + .uri(uri) + .POST(HttpRequest.BodyPublishers.ofString(createJsonToPush(fileName, fileContent))) + .build() + val response = client.send(request, HttpResponse.BodyHandlers.ofString()) + + val ramUsagePattern: Pattern = Pattern.compile("\"ramUsage\":([0-9.]+)") + val ramUsageMatcher: Matcher = ramUsagePattern.matcher(response.body()) + var ramUsage = "" + if (ramUsageMatcher.find()) { + ramUsage = " (${ramUsageMatcher.group(1)} GiB)" + } + val overwrittenPattern: Pattern = Pattern.compile("\"overwritten\":(true)") + val overwrittenMatcher: Matcher = overwrittenPattern.matcher(response.body()) + var overwritten = "📘" + if (overwrittenMatcher.find()) { + overwritten = "📝" + } + var statusIcon = "✅" + if (response.statusCode() != 200) { + statusIcon = "❌" + } + val information = "$statusIcon 💻  ️🎮 | $overwritten $fileName$ramUsage" + + sendNotification(information) + } + + fun delete(fileName: String) { + val client = HttpClient.newBuilder().build() + val request = HttpRequest.newBuilder() + .header("Authorization", "Bearer " + BitburnerSettings.getAuthToken()) + .uri(uri) + .method("DELETE", HttpRequest.BodyPublishers.ofString(createJsonToDelete(fileName))) + .build() + val response = client.send(request, HttpResponse.BodyHandlers.ofString()) + var statusIcon = "✅" + if (response.statusCode() != 200) { + statusIcon = "❌" + } + val information = "$statusIcon 💻  ️🎮 | 🗑 $fileName" + + sendNotification(information) + } + + fun getFileName(filePath: String): String { + val project: Project = getProject() + + return filePath + .replace(project.basePath.toString(), "") + .replace("\\\\", "/") + .replace("\\", "/") + } + + fun getProject(): Project { + val dataContext = DataManager.getInstance().dataContextFromFocusAsync.blockingGet(100)!! + return dataContext.getData(CommonDataKeys.PROJECT)!! + } + + private fun createJsonToPush(fileName: String, fileContent: ByteArray): String { + val encode = String(Base64.getEncoder().encode(fileContent)) + + return "{\"filename\": \"$fileName\" ,\"code\": \"$encode\"}" + } + + private fun createJsonToDelete(fileName: String): String { + return "{\"filename\": \"$fileName\"}" + } + + fun sendNotification(message: String) { + val project: Project = getProject() + + val notification = + notificationGroup.createNotification(message, NotificationType.INFORMATION) + notification.notify(project) + } + } +} diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburner.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburner.kt deleted file mode 100644 index cbe8206..0000000 --- a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/PushToBitburner.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.github.serverfrog.bitburnerplugin.bitburner - -import com.github.serverfrog.bitburnerplugin.MyBundle -import com.github.serverfrog.bitburnerplugin.config.BitburnerSettings -import com.intellij.notification.NotificationGroup -import com.intellij.notification.NotificationGroupManager -import com.intellij.notification.NotificationType -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import java.net.URI -import java.net.http.HttpClient -import java.net.http.HttpRequest -import java.net.http.HttpResponse -import java.nio.file.Paths -import java.util.* - - -val uri: URI = URI.create("http://localhost:9990/") - -class PushToBitburner { - - companion object { - private val notificationGroup: NotificationGroup = NotificationGroupManager.getInstance() - .getNotificationGroup(MyBundle.message("groupId")) - - fun pushToBitburner(file: VirtualFile, project: Project) { - - - val client = HttpClient.newBuilder().build() - val request = HttpRequest.newBuilder() - .header("Authorization", "Bearer " + BitburnerSettings.getAuthToken()) - .uri(uri) - .POST(HttpRequest.BodyPublishers.ofString(createJson(file, project))) - .build() - val response = client.send(request, HttpResponse.BodyHandlers.ofString()) - val status = response.statusCode() - if (status == 200) { - sendNotification(MyBundle.message("successMessage"), project) - } else { - sendNotification(MyBundle.message("failedMessage"), project) - } - - - } - - private fun createJson(file: VirtualFile, project: Project): String { - val relativePath = Paths.get(project.basePath!!).relativize(Paths.get(file.path)) - val fileName = relativePath.toString().replace("[\\\\|/]+".toRegex(), "/") - - val fileContent = String(file.contentsToByteArray()) - val encode = String(Base64.getEncoder().encode(fileContent.toByteArray())) - - return "{\"filename\": \"$fileName\" ,\"code\": \"$encode\"}" - } - - private fun sendNotification(message: String, project: Project?) { - val notification = - notificationGroup.createNotification(message, NotificationType.INFORMATION) - notification.notify(project) - - } - } - -} diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitBurnerSettingsUi.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitBurnerSettingsUi.kt index 8beafe4..0489ce1 100644 --- a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitBurnerSettingsUi.kt +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitBurnerSettingsUi.kt @@ -9,10 +9,8 @@ import javax.swing.JPanel import javax.swing.JPasswordField class BitBurnerSettingsUi : ConfigurableUi { - private val myAuthTokenField: JPasswordField = JPasswordField() private val myAuthTokenLabel: JLabel = JLabel(MyBundle.message("authToken")) - private val myPanel: JPanel = JPanel() init { diff --git a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettings.kt b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettings.kt index ddecce3..1a92a87 100644 --- a/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettings.kt +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/config/BitburnerSettings.kt @@ -7,15 +7,13 @@ import com.intellij.credentialStore.generateServiceName import com.intellij.ide.passwordSafe.PasswordSafe import com.intellij.openapi.options.ConfigurableBase - private const val AUTH_TOKEN = "AUTH_TOKEN" -class BitburnerSettings() : ConfigurableBase( +class BitburnerSettings : ConfigurableBase( "com.github.serverfrog.bitburnerplugin.config.BitburnerSettings", MyBundle.message("name"), "com.github.serverfrog.bitburnerplugin.config.BitburnerSettings" ) { - override fun getSettings(): BitburnerSettings { return BitburnerSettings() } @@ -26,20 +24,20 @@ class BitburnerSettings() : ConfigurableBase) { - if (BitburnerSettings.getAuthToken() == null) { - return + fun isSameEvent(event: VFileEvent): Boolean { + return event.javaClass.simpleName == this.className } - val dataContext = DataManager.getInstance().dataContextFromFocusAsync.blockingGet(100)!! - val project: Project = dataContext.getData(CommonDataKeys.PROJECT)!! + } + + override fun before(events: List) { + if (checkAuthToken()) return for (event in events) { - val file = event.file - if (extensions.contains(file?.canonicalFile?.extension) && file != null) { - PushToBitburner.pushToBitburner(file, project) + if (event.file?.isDirectory == false) break + + if (DELETE.isSameEvent(event)) { + deleteFolder(event) + } + if (MOVE.isSameEvent(event)) { + moveFolder(event) + } + if (PROPERTY_CHANGED.isSameEvent(event)) { + updateFolder(event) } } + } + + private fun updateFolder(event: VFileEvent) { + val eventFileProperty: VFilePropertyChangeEvent = event as VFilePropertyChangeEvent + + if (eventFileProperty.propertyName == "name") { + val allFiles = getListOfProjectVirtualFilesByExtensions(extensions) + for (file in filterByEventPath(event, allFiles)) { + val filePathToDelete = getFileName(file.path) + Bitburner.delete(filePathToDelete) + val newFilePath = file.path.replace(eventFileProperty.oldPath, eventFileProperty.newPath) + val filePathToPush = getFileName(newFilePath) + Bitburner.push(filePathToPush, file.contentsToByteArray()) + } + } + } + + private fun moveFolder(event: VFileEvent) { + val eventFileMove: VFileMoveEvent = event as VFileMoveEvent + val allFiles = getListOfProjectVirtualFilesByExtensions(extensions) + for (file in filterByEventPath(event, allFiles)) { + val filePathToDelete = getFileName(file.path) + Bitburner.delete(filePathToDelete) + val newFilePath = eventFileMove.newPath + "/" + file.name + val filePathToPush = getFileName(newFilePath) + Bitburner.push(filePathToPush, file.contentsToByteArray()) + } + } + + private fun deleteFolder(event: VFileEvent) { + val allFiles = getListOfProjectVirtualFilesByExtensions(extensions) + for (file in filterByEventPath(event, allFiles)) { + val filePathToDelete = getFileName(file.path) + Bitburner.delete(filePathToDelete) + } + } + private fun filterByEventPath(event: VFileEvent, files: Collection): List { + return files.filter { it.path.startsWith(event.path) }.toList() + } + + override fun after(events: List) { + if (checkAuthToken()) return + + for (event in events) { + if (event.file?.isDirectory == true || !extensions.contains(event.file?.extension)) break + + val filePath = getFileName(event.path) + if (CREATE.isSameEvent(event) || CONTENT_CHANGED.isSameEvent(event) || COPY.isSameEvent(event)) { + event.file?.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + if (DELETE.isSameEvent(event)) { + Bitburner.delete(filePath) + } + if (MOVE.isSameEvent(event)) { + val eventFileMove: VFileMoveEvent = event as VFileMoveEvent + val fileOldParent = getFileName(eventFileMove.oldPath) + Bitburner.delete(fileOldParent) + eventFileMove.file.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + if (PROPERTY_CHANGED.isSameEvent(event)) { + val eventFileProperty: VFilePropertyChangeEvent = event as VFilePropertyChangeEvent + + if (eventFileProperty.propertyName == "name") { + val fileOldPath = getFileName(eventFileProperty.oldPath) + Bitburner.delete(fileOldPath) + eventFileProperty.file.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + } + } + } + + private fun getListOfProjectVirtualFilesByExtensions(extNames: List): MutableCollection { + val project: Project = Bitburner.getProject() + val scope = GlobalSearchScope.projectScope(project) + val files = mutableListOf() + for (extension in extNames) { + files.addAll(FilenameIndex.getAllFilesByExt(project, extension, scope)) + } + return files + } + + private fun checkAuthToken(): Boolean { + if (BitburnerSettings.getAuthToken() == null) { + sendNotification("The token is null. Enable the API in Bitburner game, then copy the token and paste in IntelliJ settings under Tools section.") + return true + } + return false } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 2181fb4..342948a 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -19,8 +19,9 @@ instance="com.github.serverfrog.bitburnerplugin.config.BitburnerSettings" id="com.github.serverfrog.bitburnerplugin.config.BitburnerSettings" displayName="BitBurner-Sync"/> - + + diff --git a/src/main/resources/messages/MyBundle.properties b/src/main/resources/messages/MyBundle.properties index 9844beb..8bcea1c 100644 --- a/src/main/resources/messages/MyBundle.properties +++ b/src/main/resources/messages/MyBundle.properties @@ -2,5 +2,3 @@ name=Bitburner-Sync pushActionLabel=Push File to Bitburner authToken=&Authentication Token: groupId=com.github.serverfrog.bitburnerplugin -successMessage=Successfully pushed to BitBurner -failedMessage=Failed to push to Bitburner diff --git a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/MyPluginTest.kt b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/MyPluginTest.kt index f16eecd..9a78cb8 100644 --- a/src/test/kotlin/com/github/serverfrog/bitburnerplugin/MyPluginTest.kt +++ b/src/test/kotlin/com/github/serverfrog/bitburnerplugin/MyPluginTest.kt @@ -25,7 +25,4 @@ class MyPluginTest : BasePlatformTestCase() { override fun getTestDataPath() = "src/test/testData/rename" - fun testRename() { - myFixture.testRename("foo.xml", "foo_after.xml", "a2") - } } diff --git a/src/test/testData/rename/foo.xml b/src/test/testData/rename/foo.xml index b21e9f2..11bac6f 100644 --- a/src/test/testData/rename/foo.xml +++ b/src/test/testData/rename/foo.xml @@ -1,3 +1,3 @@ - 1>Foo + Foo