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..991bdd7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ name: Build on: # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g. for dependabot pull requests) push: - branches: [main] + branches: [ main ] # Trigger the workflow on any pull request pull_request: 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..39f1a12 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 - - + + + + + + + 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..daf5e0b 100644 --- a/.run/Run Plugin Verification.run.xml +++ b/.run/Run Plugin Verification.run.xml @@ -1,26 +1,27 @@ - - - - - - - true - true - false - - - + + + + + + + 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..b926b3a 100644 --- a/.run/Run Qodana.run.xml +++ b/.run/Run Qodana.run.xml @@ -1,29 +1,29 @@ - - - - - - - true - true - false - - + + + + + + + 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..dede294 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { // Kotlin support id("org.jetbrains.kotlin.jvm") version "1.7.10" // Gradle IntelliJ Plugin - id("org.jetbrains.intellij") version "1.7.0" + id("org.jetbrains.intellij") version "1.9.0" // Gradle Changelog Plugin id("org.jetbrains.changelog") version "1.3.1" // Gradle Qodana Plugin diff --git a/gradle.properties b/gradle.properties index 2004369..445e8cd 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 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=11 # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion=7.5 - # 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/gradlew b/gradlew index 1b6c787..f1e4391 100755 --- a/gradlew +++ b/gradlew @@ -40,7 +40,7 @@ # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. +# by Bash, Ksh, and so on; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security @@ -69,18 +69,18 @@ app_path=$0 # Need this for daisy-chained symlinks. while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac + ls=$(ls -ld "$app_path") + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +APP_HOME=$(cd "${APP_HOME:-./}" && pwd -P) || exit APP_NAME="Gradle" APP_BASE_NAME=${0##*/} @@ -91,15 +91,15 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum -warn () { - echo "$*" +warn() { + echo "$*" } >&2 -die () { - echo - echo "$*" - echo - exit 1 +die() { + echo + echo "$*" + echo + exit 1 } >&2 # OS specific support (must be 'true' or 'false'). @@ -107,51 +107,52 @@ cygwin=false msys=false darwin=false nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; +case "$(uname)" in #( +CYGWIN*) cygwin=true ;; #( +Darwin*) darwin=true ;; #( +MSYS* | MINGW*) msys=true ;; #( +NONSTOP*) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - # Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME +if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ]; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi + fi else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac +if ! "$cygwin" && ! "$darwin" && ! "$nonstop"; then + case $MAX_FD in #( + max*) + MAX_FD=$(ulimit -H -n) || + warn "Could not query maximum file descriptor limit" + ;; + esac + case $MAX_FD in #( + '' | soft) : ;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + ;; + esac fi # Collect all arguments for the java command, stacking in reverse order: @@ -163,34 +164,36 @@ fi # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done +if "$cygwin" || "$msys"; then + APP_HOME=$(cygpath --path --mixed "$APP_HOME") + CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") + + JAVACMD=$(cygpath --unix "$JAVACMD") + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg; do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) + t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] + ;; #( + *) false ;; + esac + then + arg=$(cygpath --path --ignore --mixed "$arg") + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done fi # Collect all arguments for the java command; @@ -200,16 +203,16 @@ fi # * put everything else in single quotes, so that it's not re-expanded. set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # -# In Bash we could simply go: +# In Bash, we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" @@ -225,10 +228,10 @@ set -- \ # eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' +)" '"$@"' exec "$JAVACMD" "$@" 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..fb79a2d --- /dev/null +++ b/src/main/kotlin/com/github/serverfrog/bitburnerplugin/bitburner/Bitburner.kt @@ -0,0 +1,116 @@ +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 com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.search.FilenameIndex +import com.intellij.psi.search.GlobalSearchScope +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 { + 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 getListOfProjectVirtualFilesByExt(extName: String = "*"): MutableCollection { + val project: Project = getProject() + val scope = GlobalSearchScope.projectScope(project) + return FilenameIndex.getAllFilesByExt(project, extName, scope) + } + + fun getFileName(filePath: String): String { + val project: Project = getProject() + + return filePath + .replace(project.basePath.toString(), "") + .replace("\\\\", "/") + .replace("\\", "/") + } + + private 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) { + override fun before(events: List) { 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 } - val dataContext = DataManager.getInstance().dataContextFromFocusAsync.blockingGet(100)!! - val project: Project = dataContext.getData(CommonDataKeys.PROJECT)!! for (event in events) { - val file = event.file - if (extensions.contains(file?.canonicalFile?.extension) && file != null) { - PushToBitburner.pushToBitburner(file, project) + if (event.javaClass.simpleName == "VFileDeleteEvent") { + if (event.file?.isDirectory == true) { + for (extension in extensions) { + val allFiles = getListOfProjectVirtualFilesByExt(extension) + for (file in allFiles) { + if (file.path.startsWith(event.path)) { + val filePathToDelete = getFileName(file.path) + Bitburner.delete(filePathToDelete) + } + } + } + } + } + + if (event.javaClass.simpleName == "VFileMoveEvent") { + val eventFileMove: VFileMoveEvent = event as VFileMoveEvent + if (event.file.isDirectory) { + for (extension in extensions) { + val allFiles = getListOfProjectVirtualFilesByExt(extension) + for (file in allFiles) { + if (file.path.startsWith(event.path)) { + val filePathToDelete = getFileName(file.path) + Bitburner.delete(filePathToDelete) + + val newFilePath = eventFileMove.newPath + "/" + file.name + val filePathToPush = getFileName(newFilePath) + Bitburner.push(filePathToPush, file.contentsToByteArray()) + } + } + } + } } + + if (event.javaClass.simpleName == "VFilePropertyChangeEvent") { + val eventFileProperty: VFilePropertyChangeEvent = event as VFilePropertyChangeEvent + + if (event.file.isDirectory) { + if (eventFileProperty.propertyName == "name") { + for (extension in extensions) { + val allFiles = getListOfProjectVirtualFilesByExt(extension) + for (file in allFiles) { + if (file.path.startsWith(event.path)) { + 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()) + } + } + } + } + } + } + } + } + + override fun after(events: List) { + 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 } + for (event in events) { + val filePath = getFileName(event.path) + + if (event.javaClass.simpleName == "VFileCreateEvent" || + event.javaClass.simpleName == "VFileContentChangeEvent" || + event.javaClass.simpleName == "VFileCopyEvent" + ) { + if (event.file?.isDirectory == false) { + if (extensions.contains(event.file?.extension)) { + event.file?.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + } + } + + if (event.javaClass.simpleName == "VFileDeleteEvent") { + if (event.file?.isDirectory == false) { + if (extensions.contains(event.file?.extension)) { + Bitburner.delete(filePath) + } + } + } + + if (event.javaClass.simpleName == "VFileMoveEvent") { + val eventFileMove: VFileMoveEvent = event as VFileMoveEvent + + if (!event.file.isDirectory) { + if (extensions.contains(event.file.extension)) { + val fileOldParent = getFileName(eventFileMove.oldPath) + Bitburner.delete(fileOldParent) + event.file.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + } + } + + if (event.javaClass.simpleName == "VFilePropertyChangeEvent") { + val eventFileProperty: VFilePropertyChangeEvent = event as VFilePropertyChangeEvent + + if (!event.file.isDirectory) { + if (extensions.contains(event.file.extension)) { + if (eventFileProperty.propertyName == "name") { + val fileOldPath = getFileName(eventFileProperty.oldPath) + Bitburner.delete(fileOldPath) + event.file.let { Bitburner.push(filePath, it.contentsToByteArray()) } + } + } + } + } + } } } 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/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