[
  {
    "path": ".github/dependabot.yml",
    "content": "# Dependabot configuration:\n# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  # Maintain dependencies for Gradle dependencies\n  - package-ecosystem: \"gradle\"\n    directory: \"/\"\n    target-branch: \"next\"\n    schedule:\n      interval: \"daily\"\n  # Maintain dependencies for GitHub Actions\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    target-branch: \"next\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "# GitHub Actions Workflow created for testing and preparing the plugin release in following steps:\n# - validate Gradle Wrapper,\n# - run 'test' and 'verifyPlugin' tasks,\n# - run Qodana inspections,\n# - run 'buildPlugin' task and prepare artifact for the further tests,\n# - run 'runPluginVerifier' task,\n# - create a draft release.\n#\n# Workflow is triggered on push and pull_request events.\n#\n# GitHub Actions reference: https://help.github.com/en/actions\n#\n## JBIJPPTPL\n\nname: Build\non:\n  # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g. for dependabot pull requests)\n  push:\n    branches: [main]\n  # Trigger the workflow on any pull request\n  pull_request:\n\njobs:\n\n  # Run Gradle Wrapper Validation Action to verify the wrapper's checksum\n  # Run verifyPlugin, IntelliJ Plugin Verifier, and test Gradle tasks\n  # Build plugin and provide the artifact for the next workflow jobs\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    outputs:\n      version: ${{ steps.properties.outputs.version }}\n      changelog: ${{ steps.properties.outputs.changelog }}\n    steps:\n\n      # Free GitHub Actions Environment Disk Space\n      - name: Maximize Build Space\n        run: |\n          sudo rm -rf /usr/share/dotnet\n          sudo rm -rf /usr/local/lib/android\n          sudo rm -rf /opt/ghc\n\n      # Check out current repository\n      - name: Fetch Sources\n        uses: actions/checkout@v3\n\n      # Validate wrapper\n      - name: Gradle Wrapper Validation\n        uses: gradle/wrapper-validation-action@v1.0.5\n\n      # Setup Java 11 environment for the next steps\n      - name: Setup Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: zulu\n          java-version: 11\n\n      # Set environment variables\n      - name: Export Properties\n        id: properties\n        shell: bash\n        run: |\n          PROPERTIES=\"$(./gradlew properties --console=plain -q)\"\n          VERSION=\"$(echo \"$PROPERTIES\" | grep \"^version:\" | cut -f2- -d ' ')\"\n          NAME=\"$(echo \"$PROPERTIES\" | grep \"^pluginName:\" | cut -f2- -d ' ')\"\n          CHANGELOG=\"$(./gradlew getChangelog --unreleased --no-header --console=plain -q)\"\n          CHANGELOG=\"${CHANGELOG//'%'/'%25'}\"\n          CHANGELOG=\"${CHANGELOG//$'\\n'/'%0A'}\"\n          CHANGELOG=\"${CHANGELOG//$'\\r'/'%0D'}\"\n\n          echo \"::set-output name=version::$VERSION\"\n          echo \"::set-output name=name::$NAME\"\n          echo \"::set-output name=changelog::$CHANGELOG\"\n          echo \"::set-output name=pluginVerifierHomeDir::~/.pluginVerifier\"\n\n          ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier\n\n      # Run tests\n      - name: Run Tests\n        run: ./gradlew check\n\n      # Collect Tests Result of failed tests\n      - name: Collect Tests Result\n        if: ${{ failure() }}\n        uses: actions/upload-artifact@v3\n        with:\n          name: tests-result\n          path: ${{ github.workspace }}/build/reports/tests\n\n      # Upload Kover report to CodeCov\n      - name: Upload Code Coverage Report\n        uses: codecov/codecov-action@v3\n        with:\n          files: ${{ github.workspace }}/build/reports/kover/xml/report.xml\n\n      # Cache Plugin Verifier IDEs\n      - name: Setup Plugin Verifier IDEs Cache\n        uses: actions/cache@v3\n        with:\n          path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides\n          key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }}\n\n      # Run Verify Plugin task and IntelliJ Plugin Verifier tool\n      - name: Run Plugin Verification tasks\n        run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}\n\n      # Collect Plugin Verifier Result\n      - name: Collect Plugin Verifier Result\n        if: ${{ always() }}\n        uses: actions/upload-artifact@v3\n        with:\n          name: pluginVerifier-result\n          path: ${{ github.workspace }}/build/reports/pluginVerifier\n\n      # Run Qodana inspections\n#      - name: Qodana - Code Inspection\n#        uses: JetBrains/qodana-action@v2022.2.3\n\n      # Prepare plugin archive content for creating artifact\n      - name: Prepare Plugin Artifact\n        id: artifact\n        shell: bash\n        run: |\n          cd ${{ github.workspace }}/build/distributions\n          FILENAME=`ls *.zip`\n          unzip \"$FILENAME\" -d content\n\n          echo \"::set-output name=filename::${FILENAME:0:-4}\"\n\n      # Store already-built plugin as an artifact for downloading\n      - name: Upload artifact\n        uses: actions/upload-artifact@v3\n        with:\n          name: ${{ steps.artifact.outputs.filename }}\n          path: ./build/distributions/content/*/*\n\n  # Prepare a draft release for GitHub Releases page for the manual verification\n  # If accepted and published, release workflow would be triggered\n  releaseDraft:\n    name: Release Draft\n    if: github.event_name != 'pull_request'\n    needs: build\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n\n      # Check out current repository\n      - name: Fetch Sources\n        uses: actions/checkout@v3\n\n      # Remove old release drafts by using the curl request for the available releases with draft flag\n      - name: Remove Old Release Drafts\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          gh api repos/{owner}/{repo}/releases \\\n            --jq '.[] | select(.draft == true) | .id' \\\n            | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}\n\n      # Create new release draft - which is not publicly visible and requires manual acceptance\n      - name: Create Release Draft\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          gh release create v${{ needs.build.outputs.version }} \\\n            --draft \\\n            --title \"v${{ needs.build.outputs.version }}\" \\\n            --notes \"$(cat << 'EOM'\n          ${{ needs.build.outputs.changelog }}\n          EOM\n          )\"\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "# GitHub Actions Workflow created for handling the release process based on the draft release prepared\n# with the Build workflow. Running the publishPlugin task requires the PUBLISH_TOKEN secret provided.\n\nname: Release\non:\n  release:\n    types: [prereleased, released]\n\njobs:\n\n  # Prepare and publish the plugin to the Marketplace repository\n  release:\n    name: Publish Plugin\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      pull-requests: write\n    steps:\n\n      # Check out current repository\n      - name: Fetch Sources\n        uses: actions/checkout@v3\n        with:\n          ref: ${{ github.event.release.tag_name }}\n\n      # Setup Java 11 environment for the next steps\n      - name: Setup Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: zulu\n          java-version: 11\n\n      # Set environment variables\n      - name: Export Properties\n        id: properties\n        shell: bash\n        run: |\n          CHANGELOG=\"$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'\n          ${{ github.event.release.body }}\n          EOM\n          )\"\n          \n          CHANGELOG=\"${CHANGELOG//'%'/'%25'}\"\n          CHANGELOG=\"${CHANGELOG//$'\\n'/'%0A'}\"\n          CHANGELOG=\"${CHANGELOG//$'\\r'/'%0D'}\"\n\n          echo \"::set-output name=changelog::$CHANGELOG\"\n\n      # Update Unreleased section with the current release note\n      - name: Patch Changelog\n        if: ${{ steps.properties.outputs.changelog != '' }}\n        env:\n          CHANGELOG: ${{ steps.properties.outputs.changelog }}\n        run: |\n          ./gradlew patchChangelog --release-note=\"$CHANGELOG\"\n\n      # Publish the plugin to the Marketplace\n      - name: Publish Plugin\n        env:\n          PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}\n          CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}\n          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}\n          PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}\n        run: ./gradlew publishPlugin\n\n      # Upload artifact as a release asset\n      - name: Upload Release Asset\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*\n\n      # Create pull request\n      - name: Create Pull Request\n        if: ${{ steps.properties.outputs.changelog != '' }}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          VERSION=\"${{ github.event.release.tag_name }}\"\n          BRANCH=\"changelog-update-$VERSION\"\n          LABEL=\"release changelog\"\n\n          git config user.email \"action@github.com\"\n          git config user.name \"GitHub Action\"\n\n          git checkout -b $BRANCH\n          git commit -am \"Changelog update - $VERSION\"\n          git push --set-upstream origin $BRANCH\n          \n          gh label create \"$LABEL\" \\\n            --description \"Pull requests with release changelog update\" \\\n            || true\n\n          gh pr create \\\n            --title \"Changelog update - \\`$VERSION\\`\" \\\n            --body \"Current pull request contains patched \\`CHANGELOG.md\\` file for the \\`$VERSION\\` version.\" \\\n            --label \"$LABEL\" \\\n            --head $BRANCH\n"
  },
  {
    "path": ".github/workflows/run-ui-tests.yml",
    "content": "# GitHub Actions Workflow for launching UI tests on Linux, Windows, and Mac in the following steps:\n# - prepare and launch IDE with your plugin and robot-server plugin, which is needed to interact with UI\n# - wait for IDE to start\n# - run UI tests with separate Gradle task\n#\n# Please check https://github.com/JetBrains/intellij-ui-test-robot for information about UI tests with IntelliJ Platform\n#\n# Workflow is triggered manually.\n\nname: Run UI Tests\non:\n  workflow_dispatch\n\njobs:\n\n  testUI:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: ubuntu-latest\n            runIde: |\n              export DISPLAY=:99.0\n              Xvfb -ac :99 -screen 0 1920x1080x16 &\n              gradle runIdeForUiTests &\n          - os: windows-latest\n            runIde: start gradlew.bat runIdeForUiTests\n          - os: macos-latest\n            runIde: ./gradlew runIdeForUiTests &\n\n    steps:\n\n      # Check out current repository\n      - name: Fetch Sources\n        uses: actions/checkout@v3\n\n      # Setup Java 11 environment for the next steps\n      - name: Setup Java\n        uses: actions/setup-java@v3\n        with:\n          distribution: zulu\n          java-version: 11\n\n      # Run IDEA prepared for UI testing\n      - name: Run IDE\n        run: ${{ matrix.runIde }}\n\n      # Wait for IDEA to be started\n      - name: Health Check\n        uses: jtalk/url-health-check-action@v3\n        with:\n          url: http://127.0.0.1:8082\n          max-attempts: 15\n          retry-delay: 30s\n\n      # Run tests\n      - name: Tests\n        run: ./gradlew test\n"
  },
  {
    "path": ".gitignore",
    "content": ".gradle\n.idea\n.qodana\nbuild\n"
  },
  {
    "path": ".run/Run IDE for UI Tests.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Run IDE for UI Tests\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <log_file alias=\"idea.log\" path=\"$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log\" />\n    <ExternalSystemSettings>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"runIdeForUiTests\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list />\n      </option>\n      <option name=\"vmOptions\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <method v=\"2\" />\n  </configuration>\n</component>"
  },
  {
    "path": ".run/Run IDE with Plugin.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Run Plugin\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <log_file alias=\"idea.log\" path=\"$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log\" />\n    <ExternalSystemSettings>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list>\n          <option value=\"runIde\" />\n        </list>\n      </option>\n      <option name=\"vmOptions\" value=\"\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <method v=\"2\" />\n  </configuration>\n</component>"
  },
  {
    "path": ".run/Run Plugin Tests.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Run Tests\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <log_file alias=\"idea.log\" path=\"$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log\" />\n    <ExternalSystemSettings>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list>\n          <option value=\"check\" />\n        </list>\n      </option>\n      <option name=\"vmOptions\" value=\"\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <method v=\"2\" />\n  </configuration>\n</component>\n"
  },
  {
    "path": ".run/Run Plugin Verification.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Run Verifications\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <log_file alias=\"idea.log\" path=\"$PROJECT_DIR$/build/idea-sandbox/system/log/idea.log\" />\n    <ExternalSystemSettings>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list>\n          <option value=\"runPluginVerifier\" />\n        </list>\n      </option>\n      <option name=\"vmOptions\" value=\"\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <method v=\"2\">\n      <option name=\"Gradle.BeforeRunTask\" enabled=\"true\" tasks=\"clean\" externalProjectPath=\"$PROJECT_DIR$\" vmOptions=\"\" scriptParameters=\"\" />\n    </method>\n  </configuration>\n</component>"
  },
  {
    "path": ".run/Run Qodana.run.xml",
    "content": "<component name=\"ProjectRunConfigurationManager\">\n  <configuration default=\"false\" name=\"Run Qodana\" type=\"GradleRunConfiguration\" factoryName=\"Gradle\">\n    <ExternalSystemSettings>\n      <option name=\"env\">\n        <map>\n          <entry key=\"QODANA_SHOW_REPORT\" value=\"true\" />\n        </map>\n      </option>\n      <option name=\"executionName\" />\n      <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n      <option name=\"externalSystemIdString\" value=\"GRADLE\" />\n      <option name=\"scriptParameters\" value=\"cleanInspections runInspections\" />\n      <option name=\"taskDescriptions\">\n        <list />\n      </option>\n      <option name=\"taskNames\">\n        <list />\n      </option>\n      <option name=\"vmOptions\" />\n    </ExternalSystemSettings>\n    <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>\n    <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>\n    <DebugAllEnabled>false</DebugAllEnabled>\n    <method v=\"2\" />\n  </configuration>\n</component>"
  },
  {
    "path": "CHANGELOG.md",
    "content": "<!-- Keep a Changelog guide -> https://keepachangelog.com -->\n\n# intellij-chatgpt Changelog\n\n## [Unreleased]\n\n## [1.1.1] - 2023-03-30\n\n### Added\n- Bring session token setting for official website back. [#7 (comment)](https://github.com/LiLittleCat/intellij-chatgpt/issues/7#issuecomment-1487889326)\n\n## [1.1.0] - 2023-03-21\n\n### Added\n- Integration of third-party mirror websites for free usage.\n- Support for all future IDE builds [#12](https://github.com/LiLittleCat/intellij-chatgpt/pull/12)\n\n### Fixed\n- Removed session token storage to resolve cookie setting issues [#16](https://github.com/LiLittleCat/intellij-chatgpt/issues/16)\n- Change the Tool Window name to `ChatGPT Tool` [#10](https://github.com/LiLittleCat/intellij-chatgpt/issues/10)\n\n## [1.0.3] - 2023-02-20\n- Fix bugs\n\n## [1.0.2] - 2022-12-16\n- Remove session token check because of Cloudflare\n- Add refresh button [#2](https://github.com/LiLittleCat/intellij-chatgpt/issues/2)\n- Support version 2020.2-2022.3 [#3](https://github.com/LiLittleCat/intellij-chatgpt/issues/3)\n\n## [1.0.1] - 2022-12-12\n\n### Added\n- Update plugin description\n\n## [1.0.0]\n\n### Added\n- Support all JetBrains IDEs\n\n[Unreleased]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.1.1...HEAD\n[1.1.1]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.1.0...v1.1.1\n[1.1.0]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.0.3...v1.1.0\n[1.0.3]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.0.2...v1.0.3\n[1.0.2]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.0.1...v1.0.2\n[1.0.1]: https://github.com/LiLittleCat/intellij-chatgpt/compare/v1.0.0...v1.0.1\n[1.0.0]: https://github.com/LiLittleCat/intellij-chatgpt/commits/v1.0.0\n"
  },
  {
    "path": "DESCRIPTION.md",
    "content": "\n<!-- Plugin description -->\n\nThis Jetbrains IDEs plugin integrates [ChatGPT](https://chat.openai.com/) and [other third-party mirror websites](https://github.com/LiLittleCat/awesome-free-chatgpt) of ChatGPT into JetBrains IDEs,\nproviding a seamless experience for developers to interact with the ChatGPT AI model directly within their development environment.\n\n### Feature\n\n- 🚀 Easy to use, interact with ChatGPT without leaving the IDE.\n- 🆓 Integrates free third-party mirror websites and easily update.\n- ✅ Add and manage multiple ChatGPT URLs.\n- 🔄 Easily switch between different ChatGPT URLs.\n\n### How it works\n\nThis plugin uses JCEF(Java Chromium Embedded Framework) to render the content. It is a lightweight and cross-platform web browser engine that is built on top of Chromium and is used by IntelliJ IDEA to render the HTML content of the IDE.\nJCEF is supported in IntelliJ IDEA 2020.2 and later. See [JCEF](https://plugins.jetbrains.com/docs/intellij/jcef.html) for more information.\n\n### 💡 Solution for `Cannot log in to the official ChatGPT by Google account or Microsoft account`\n\nSee [Notice from README](https://github.com/LiLittleCat/intellij-chatgpt/blob/bring-back-session-token/README.md#-notice).\n\n### Support\n\nFeel free to submit [issue](https://github.com/LiLittleCat/awesome-free-chatgpt/issues) and [PRs](https://github.com/LiLittleCat/awesome-free-chatgpt/pulls). If you find it useful, welcome to star ⭐, your support is my motivation to move forward.\n\n---\n\n一个将 [ChatGPT](https://chat.openai.com/) 和 [其他第三方镜像网站](https://github.com/LiLittleCat/awesome-free-chatgpt) 整合到 JetBrains IDEs 的插件。\n\n### 功能\n\n- 🚀 易于使用，无需离开 IDE 即可与 ChatGPT 交互。\n- 🆓 集成免费的第三方镜像网站，并且更新方便。\n- ✅ 添加和管理多个 ChatGPT URL。\n- 🔄 轻松在不同的 ChatGPT URL 之间切换。\n\n### 如何工作的\n\n此插件使用 JCEF（Java Chromium Embedded Framework）来渲染内容。它是一个轻量级且跨平台的基于 Chromium 的网络浏览器引擎，被 IntelliJ IDEA 用于渲染 IDE 的 HTML 内容。\nJCEF 支持 IntelliJ IDEA 2020.2 及更高版本。有关更多信息，请参阅 [JCEF](https://plugins.jetbrains.com/docs/intellij/jcef.html)。\n\n### 💡 `无法用谷歌账户或微软账户登录官方 ChatGPT` 的解决方案\n\n见 [README 中的注意](https://github.com/LiLittleCat/intellij-chatgpt/blob/bring-back-session-token/README_CN.md#-%E6%B3%A8%E6%84%8F)。\n\n### 支持\n\n欢迎随时提交 [issue](https://github.com/LiLittleCat/awesome-free-chatgpt/issues) 和 [PRs](https://github.com/LiLittleCat/awesome-free-chatgpt/pulls)，如果您觉得有用，欢迎 star ⭐，您的支持是我前进的动力。\n\n<!-- Plugin description end -->"
  },
  {
    "path": "README.md",
    "content": "<img src=\"src/main/resources/META-INF/pluginIcon.svg\" align=\"right\" width=\"128\" height=\"128\" alt=\"icon\"/>\n\n# ChatGPT Tool\n\n![Build](https://github.com/LiLittleCat/intellij-chatgpt/workflows/Build/badge.svg)\n[![Version](https://img.shields.io/jetbrains/plugin/v/20629-chatgpt-tool.svg)](https://plugins.jetbrains.com/plugin/20629-chatgpt-tool)\n[![Downloads](https://img.shields.io/jetbrains/plugin/d/20629-chatgpt-tool.svg)](https://plugins.jetbrains.com/plugin/20629-chatgpt-tool)\n\n[中文说明](README_CN.md)\n\nThis Jetbrains IDEs plugin integrates [ChatGPT](https://chat.openai.com/) and [other third-party mirror websites](https://github.com/LiLittleCat/awesome-free-chatgpt) of ChatGPT into JetBrains IDEs,\nproviding a seamless experience for developers to interact with the ChatGPT AI model directly within their development environment.\n\n> ### 💡 Notice\n> Cannot log in to the official ChatGPT by Google account or Microsoft account is not caused by this plugin, but by the\n> official ChatGPT itself.\n>\n> See https://github.com/LiLittleCat/intellij-chatgpt/issues/7 and https://github.com/JetBrains/jcef/issues/14 for more\n> information.\n>\n> <details>\n> <summary>💡 Click to expand the Solution for this</summary>\n>\n> 1. Go to [https://chat.openai.com/chat](https://chat.openai.com/chat) and log in or sign up.\n> 2. Open dev tools.\n> 3. Open `Application` > `Cookies`.\n      [![pSSKdmR.png](https://s1.ax1x.com/2022/12/28/pSSKdmR.png)](https://imgse.com/i/pSSKdmR)\n> 4. Copy the value for `__Secure-next-auth.session-token` as settings value.\n      [![pSSK6pD.png](https://s1.ax1x.com/2022/12/28/pSSK6pD.png)](https://imgse.com/i/pSSK6pD)\n> 5. After you enter the session token, you need to restart the IDE because ChatGPT Tool Windows needs a restart, and\n     you won't need to log in until the session token is expired.\n> </details>\n\n## Feature\n\n- 🚀 Easy to use, and interact with ChatGPT without leaving the IDE.\n- 🆓 Integrates free third-party mirror websites and easily update.\n- ✅ Add and manage multiple ChatGPT URLs.\n- 🔄 Easily switch between different ChatGPT URLs.\n\n## How it works\n\nThis plugin uses JCEF(Java Chromium Embedded Framework) to render the content. It is a lightweight and cross-platform web browser engine that is built on top of Chromium and is used by IntelliJ IDEA to render the HTML content of the IDE.\nJCEF is supported in IntelliJ IDEA 2020.2 and later. See [JCEF](https://plugins.jetbrains.com/docs/intellij/jcef.html) for more information.\n\n## Installation\n\n- Using IDE built-in plugin system:\n\n  <kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd>Search for \"ChatGPT Tool\"</kbd> >\n  <kbd>Install Plugin</kbd>\n\n- Manually:\n\n  Download the [latest release](https://github.com/LiLittleCat/intellij-chatgpt/releases/latest) and install it manually using\n  <kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>\n\n\n## Usage\n\n1. Open the \"ChatGPT Tool\" tool window, which will load the default ChatGPT URL.\n   ![](/image/login.png)\n2. If you have set the [official ChatGPT](https://chat.openai.com/) as the default, you can register for an [OpenAI](https://beta.openai.com/signup) account and log in.\n   ![](/image/use.png)\n3. Access the settings to modify the default ChatGPT URL or add additional URLs\n   ![](/image/settings-info.png)\n\n   Explanation:\n    1. Quickly open the settings.\n    2. Refresh the currently opened page.\n    3. Add a new URL to the tool window.\n    4. Open the author's GitHub page in browser.\n    5. Open other plugins from the author in browser.\n    6. Select the default URL. The default URL will be opened when you first launch the tool window and when all opened pages are closed.\n    7. URL list: add, edit, and delete URLs.\n    8. Add a new URL.\n       ![](/image/add-tab.png)\n    9. Delete the selected URL.\n    10. Fetch the URL list from [the author's other GitHub repository](https://github.com/LiLittleCat/awesome-free-chatgpt).\n4. Utilize third-party mirror websites.\n   ![](/image/another.png)"
  },
  {
    "path": "README_CN.md",
    "content": "<img src=\"src/main/resources/META-INF/pluginIcon.svg\" align=\"right\" width=\"128\" height=\"128\" alt=\"icon\"/>\n\n# ChatGPT Tool\n\n![Build](https://github.com/LiLittleCat/intellij-chatgpt/workflows/Build/badge.svg)\n[![Version](https://img.shields.io/jetbrains/plugin/v/20629-chatgpt-tool.svg)](https://plugins.jetbrains.com/plugin/20629-chatgpt-tool)\n[![Downloads](https://img.shields.io/jetbrains/plugin/d/20629-chatgpt-tool.svg)](https://plugins.jetbrains.com/plugin/20629-chatgpt-tool)\n\n[English](README.md)\n\n一个将 [ChatGPT](https://chat.openai.com/) 和 [其他第三方镜像网站](https://github.com/LiLittleCat/awesome-free-chatgpt) 整合到 JetBrains IDEs 的插件。\n\n> ### 💡 注意\n> 无法使用 Google 账户或 Microsoft 账户登录官方 ChatGPT 不是由于此插件造成的，而是由官方 ChatGPT 本身造成的。\n>\n> 有关更多信息，请参阅 https://github.com/LiLittleCat/intellij-chatgpt/issues/7 和 https://github.com/JetBrains/jcef/issues/14 。\n>\n> <details>\n> <summary>💡 点击展开解决方案</summary>\n>\n> 1. 进入 [https://chat.openai.com/chat](https://chat.openai.com/chat)，登录或注册。\n> 2. 打开开发工具。\n> 3. 打开 `Application` > `Cookies`。\n     [![pSSKdmR.png](https://s1.ax1x.com/2022/12/28/pSSKdmR.png)](https://imgse.com/i/pSSKdmR)\n> 4. 复制 `__Secure-next-auth.session-token` 的值作为设置值。\n     [![pSSK6pD.png](https://s1.ax1x.com/2022/12/28/pSSK6pD.png)](https://imgse.com/i/pSSK6pD)\n> 5. 输入会话令牌后，你需要重启 IDE，因为 ChatGPT 工具 Windows 需要重启，在会话令牌过期之前，你不需要登录。\n> </details>\n\n## 功能\n\n- 🚀 易于使用，无需离开 IDE 即可与 ChatGPT 交互。\n- 🆓 集成免费的第三方镜像网站，并且更新方便。\n- ✅ 添加和管理多个 ChatGPT URL。\n- 🔄 轻松在不同的 ChatGPT URL 之间切换。\n\n## 如何工作的\n\n此插件使用 JCEF（Java Chromium Embedded Framework）来渲染内容。它是一个轻量级且跨平台的基于 Chromium 的网络浏览器引擎，被 IntelliJ IDEA 用于渲染 IDE 的 HTML 内容。\nJCEF 支持 IntelliJ IDEA 2020.2 及更高版本。有关更多信息，请参阅 [JCEF](https://plugins.jetbrains.com/docs/intellij/jcef.html)。\n\n## 安装\n\n- 使用 IDE 内部插件系统：\n\n  <kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>Marketplace</kbd> > <kbd> 搜索 \"ChatGPT Tool\"</kbd> >\n  <kbd>Install Plugin</kbd>\n\n- 手动安装：\n\n  下载 [最新版本](https://github.com/LiLittleCat/intellij-chatgpt/releases/latest) 找到\n  <kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>\n  手动安装。\n\n## 使用方法\n\n1. 打开 \"ChatGPT Tool\" 工具窗口，它将打开默认的 ChatGPT URL。\n   ![](/image/login.png)\n2. 如果您将 [官方 ChatGPT](https://chat.openai.com/) 设置为默认，您可以注册一个 [OpenAI](https://beta.openai.com/signup) 账户并登录。\n   ![](/image/use.png)\n3. 打开设置以更改默认的 ChatGPT URL 或添加更多 URL。\n   ![](/image/settings-info.png)\n   说明:\n    1. 快速打开设置。\n    2. 刷新已打开的页面。\n    3. 向工具窗口添加新的 URL。\n    4. 在浏览器中打开作者的 GitHub 页面。\n    5. 在浏览器中打开作者的其他插件。\n    6. 选择默认 URL，当您首次打开工具窗口和关闭所有已打开的页面时，将打开默认 URL。\n    7. URL 列表，您可以添加、编辑和删除 URL 列表。\n    8. 添加新的 URL。\n       ![](/image/add-tab.png)\n    9. 删除选定的 URL。\n    10. 从 [作者的另一个 GitHub 仓库](https://github.com/LiLittleCat/awesome-free-chatgpt) 获取 URL 列表。\n4. 使用第三方镜像网站。\n   ![](/image/another.png)"
  },
  {
    "path": "build.gradle.kts",
    "content": "import org.jetbrains.changelog.Changelog\nimport org.jetbrains.changelog.markdownToHTML\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nfun properties(key: String) = project.findProperty(key).toString()\n\nplugins {\n    // Java support\n    id(\"java\")\n    // Kotlin support\n    id(\"org.jetbrains.kotlin.jvm\") version \"1.8.10\"\n    // Gradle IntelliJ Plugin\n    id(\"org.jetbrains.intellij\") version \"1.13.2\"\n    // Gradle Changelog Plugin\n    id(\"org.jetbrains.changelog\") version \"2.0.0\"\n    // Gradle Qodana Plugin\n    id(\"org.jetbrains.qodana\") version \"0.1.13\"\n    // Gradle Kover Plugin\n    id(\"org.jetbrains.kotlinx.kover\") version \"0.6.1\"\n}\n\ngroup = properties(\"pluginGroup\")\nversion = properties(\"pluginVersion\")\n\n// Configure project's dependencies\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n//    implementation(\"com.google.guava:guava:31.1-jre\")\n    implementation(\"com.squareup.okhttp3:okhttp:4.9.3\")\n    implementation(\"org.json:json:20230227\")\n}\n\n// Set the JVM language level used to build project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+.\nkotlin {\n    jvmToolchain(11)\n}\n\n// Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html\nintellij {\n    pluginName.set(properties(\"pluginName\"))\n    version.set(properties(\"platformVersion\"))\n    type.set(properties(\"platformType\"))\n\n    // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file.\n    plugins.set(properties(\"platformPlugins\").split(',').map(String::trim).filter(String::isNotEmpty))\n}\n\n// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin\nchangelog {\n    groups.set(emptyList())\n    repositoryUrl.set(properties(\"pluginRepositoryUrl\"))\n}\n\n// Configure Gradle Qodana Plugin - read more: https://github.com/JetBrains/gradle-qodana-plugin\nqodana {\n    cachePath.set(file(\".qodana\").canonicalPath)\n    reportPath.set(file(\"build/reports/inspections\").canonicalPath)\n    saveReport.set(true)\n    showReport.set(System.getenv(\"QODANA_SHOW_REPORT\")?.toBoolean() ?: false)\n}\n\n// Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration\nkover.xmlReport {\n    onCheck.set(true)\n}\n\ntasks {\n    wrapper {\n        gradleVersion = properties(\"gradleVersion\")\n    }\n\n    patchPluginXml {\n        version.set(properties(\"pluginVersion\"))\n        sinceBuild.set(properties(\"pluginSinceBuild\"))\n        untilBuild.set(properties(\"pluginUntilBuild\"))\n\n        // Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest\n        pluginDescription.set(\n            file(\"DESCRIPTION.md\").readText().lines().run {\n                val start = \"<!-- Plugin description -->\"\n                val end = \"<!-- Plugin description end -->\"\n\n                if (!containsAll(listOf(start, end))) {\n                    throw GradleException(\"Plugin description section not found in README.md:\\n$start ... $end\")\n                }\n                subList(indexOf(start) + 1, indexOf(end))\n            }.joinToString(\"\\n\").let { markdownToHTML(it) }\n        )\n\n        // Get the latest available change notes from the changelog file\n        changeNotes.set(provider {\n            with(changelog) {\n                renderItem(\n                    getOrNull(properties(\"pluginVersion\")) ?: getLatest(),\n                    Changelog.OutputType.HTML,\n                )\n            }\n        })\n    }\n\n    // Configure UI tests plugin\n    // Read more: https://github.com/JetBrains/intellij-ui-test-robot\n    runIdeForUiTests {\n        systemProperty(\"robot-server.port\", \"8082\")\n        systemProperty(\"ide.mac.message.dialogs.as.sheets\", \"false\")\n        systemProperty(\"jb.privacy.policy.text\", \"<!--999.999-->\")\n        systemProperty(\"jb.consents.confirmation.enabled\", \"false\")\n    }\n\n    signPlugin {\n        certificateChain.set(System.getenv(\"CERTIFICATE_CHAIN\"))\n        privateKey.set(System.getenv(\"PRIVATE_KEY\"))\n        password.set(System.getenv(\"PRIVATE_KEY_PASSWORD\"))\n    }\n\n    publishPlugin {\n        dependsOn(\"patchChangelog\")\n        token.set(System.getenv(\"PUBLISH_TOKEN\"))\n        // pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3\n        // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:\n        // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel\n        channels.set(listOf(properties(\"pluginVersion\").split('-').getOrElse(1) { \"default\" }.split('.').first()))\n    }\n}\ndependencies {\n    implementation(kotlin(\"stdlib-jdk8\"))\n}\nval compileKotlin: KotlinCompile by tasks\ncompileKotlin.kotlinOptions {\n    jvmTarget = \"1.8\"\n}\nval compileTestKotlin: KotlinCompile by tasks\ncompileTestKotlin.kotlinOptions {\n    jvmTarget = \"1.8\"\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.0.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html\n\npluginGroup = com.lilittlecat.intellij-chatgpt\npluginName = ChatGPT Tool\npluginRepositoryUrl = https://github.com/LiLittleCat/intellij-chatgpt\n# SemVer format -> https://semver.org\npluginVersion = 1.1.1\n\n# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html\npluginSinceBuild = 202\npluginUntilBuild =\n\n# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension\nplatformType = IC\nplatformVersion = 2020.2\n\n# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html\n# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22\nplatformPlugins =\n\n# Gradle Releases -> https://github.com/gradle/gradle/releases\ngradleVersion = 8.0.2\n\n# Opt-out flag for bundling Kotlin standard library -> https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library\n# suppress inspection \"UnusedProperty\"\nkotlin.stdlib.default.dependency = false\n\n# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html\norg.gradle.unsafe.configuration-cache = true\n\n#systemProp.https.proxyHost=127.0.0.1\n#systemProp.https.proxyPort=7890\n#systemProp.http.proxyHost=127.0.0.1\n#systemProp.http.proxyPort=7890"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\n@rem you may not use this file except in compliance with the License.\n@rem You may obtain a copy of the License at\n@rem\n@rem      https://www.apache.org/licenses/LICENSE-2.0\n@rem\n@rem Unless required by applicable law or agreed to in writing, software\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n@rem See the License for the specific language governing permissions and\n@rem limitations under the License.\n@rem\n\n@if \"%DEBUG%\"==\"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif %ERRORLEVEL% equ 0 goto execute\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto execute\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\n\n:end\n@rem End local scope for the variables with windows NT shell\nif %ERRORLEVEL% equ 0 goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nset EXIT_CODE=%ERRORLEVEL%\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\nexit /b %EXIT_CODE%\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "qodana.yml",
    "content": "# Qodana configuration:\n# https://www.jetbrains.com/help/qodana/qodana-yaml.html\n\nversion: 1.0\nprofile:\n  name: qodana.recommended\nexclude:\n  - name: All\n    paths:\n      - .qodana\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "rootProject.name = \"intellij-chatgpt\"\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/AddTabAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.intellij.openapi.ui.Messages;\nimport com.intellij.openapi.wm.ToolWindow;\nimport com.intellij.openapi.wm.ToolWindowManager;\nimport com.intellij.ui.content.Content;\nimport com.intellij.ui.content.ContentManager;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport com.lilittlecat.chatgpt.setting.ChatGPTSettingsState;\nimport com.lilittlecat.chatgpt.window.ChatGPTToolWindow;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * add new tab action\n *\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2023/3/9\n */\npublic class AddTabAction extends DumbAwareAction {\n    public AddTabAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.General.Add);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent e) {\n        List<String> urlList = ChatGPTSettingsState.getInstance().urlList;\n        String[] options = urlList.toArray(new String[0]);\n//        String selected = Messages.showChooseDialog(\"Select Content\", \"Choose Content to Add\", options, options[0], null);\n        String selected = Messages.showEditableChooseDialog(\"Select URL\", \"Choose a URL to Add\", AllIcons.General.Add, options, options[0], null);\n        if (selected == null) {\n            return;\n        }\n        ToolWindowManager instance = ToolWindowManager.getInstance(Objects.requireNonNull(e.getProject()));\n        ToolWindow toolWindow = instance.getToolWindow(ChatGPTBundle.message(\"name\"));\n        assert toolWindow != null;\n        ContentManager contentManager = toolWindow.getContentManager();\n        Content content = contentManager.getFactory().createContent(new ChatGPTToolWindow(selected).getContent(), selected, false);\n        contentManager.addContent(content);\n        contentManager.setSelectedContent(content);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/FetchURLAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.application.ApplicationManager;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.intellij.util.messages.MessageBus;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport com.lilittlecat.chatgpt.setting.ChatGPTSettingsState;\nimport com.lilittlecat.chatgpt.setting.UpdateChatGPTSettingStateTopic;\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.Response;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\nimport org.json.JSONArray;\n\nimport javax.swing.*;\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2023/3/20\n */\npublic class FetchURLAction extends DumbAwareAction {\n    public FetchURLAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.Actions.CheckOut);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent event) {\n        OkHttpClient client = new OkHttpClient.Builder()\n                .connectTimeout(3, TimeUnit.SECONDS)\n                .readTimeout(3, TimeUnit.SECONDS)\n                .build();\n        String primaryUrl = ChatGPTBundle.message(\"free.chatgpt.file.url.original\");\n        String fallbackUrl = ChatGPTBundle.message(\"free.chatgpt.file.url.fallback\");\n        try {\n            JSONArray jsonArray = fetchJsonArray(client, primaryUrl);\n            processJsonArray(jsonArray);\n            JOptionPane.showMessageDialog(null, ChatGPTBundle.message(\"success.fetch.message\"), \"Success\", JOptionPane.INFORMATION_MESSAGE);\n        } catch (IOException e) {\n            try {\n                JSONArray jsonArray = fetchJsonArray(client, fallbackUrl);\n                processJsonArray(jsonArray);\n                JOptionPane.showMessageDialog(null, ChatGPTBundle.message(\"success.fetch.message\"), \"Success\", JOptionPane.INFORMATION_MESSAGE);\n            } catch (IOException e2) {\n                JOptionPane.showMessageDialog(null, ChatGPTBundle.message(\"cannot.fetch.message\"), \"Error\", JOptionPane.ERROR_MESSAGE);\n            }\n        }\n\n    }\n\n    private JSONArray fetchJsonArray(OkHttpClient client, String url) throws IOException {\n        Request request = new Request.Builder()\n                .url(url)\n                .build();\n        try (Response response = client.newCall(request).execute()) {\n            if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n            assert response.body() != null;\n            String jsonData = response.body().string();\n            return new JSONArray(jsonData);\n        }\n    }\n\n    private void processJsonArray(JSONArray jsonArray) {\n//        String defaultUrl = ChatGPTSettingsState.getInstance().defaultUrl;\n        List<String> oldUrlList = ChatGPTSettingsState.getInstance().urlList;\n//        oldUrlList.clear();\n//        String originalUrl = ChatGPTBundle.message(\"original.url\");\n//        if (originalUrl.equals(defaultUrl)) {\n//            oldUrlList.add(defaultUrl);\n//        } else {\n//            oldUrlList.add(originalUrl);\n//            oldUrlList.add(defaultUrl);\n//        }\n        for (int i = 0; i < jsonArray.length(); i++) {\n            String url = jsonArray.getString(i);\n            if (!oldUrlList.contains(url)) {\n                oldUrlList.add(url);\n            }\n        }\n        // Notify subscribers about the change\n        MessageBus messageBus = ApplicationManager.getApplication().getMessageBus();\n        messageBus.syncPublisher(UpdateChatGPTSettingStateTopic.TOPIC).stateChanged();\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/GitHubAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.ide.BrowserUtil;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\n\n/**\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2023/3/21\n */\npublic class GitHubAction extends DumbAwareAction {\n\n    public GitHubAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.Vcs.Vendors.Github);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent e) {\n        BrowserUtil.browse(ChatGPTBundle.message(\"github.url\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/MorePluginAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.ide.BrowserUtil;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\n\n/**\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2023/3/21\n */\npublic class MorePluginAction extends DumbAwareAction {\n    public MorePluginAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.Nodes.Plugin);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent e) {\n        BrowserUtil.browse(ChatGPTBundle.message(\"more.plugins.url\"));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/RefreshAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.intellij.openapi.wm.ToolWindow;\nimport com.intellij.openapi.wm.ToolWindowManager;\nimport com.intellij.ui.content.Content;\nimport com.intellij.ui.content.ContentFactory;\nimport com.intellij.ui.content.ContentManager;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport com.lilittlecat.chatgpt.window.ChatGPTToolWindow;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.Objects;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/15\n */\npublic class RefreshAction extends DumbAwareAction {\n    public RefreshAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.Actions.Refresh);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent e) {\n        // Get the ToolWindowManager instance for the current project\n        ToolWindowManager instance = ToolWindowManager.getInstance(Objects.requireNonNull(e.getProject()));\n        // Get the tool window with the specified name\n        ToolWindow toolWindow = instance.getToolWindow(ChatGPTBundle.message(\"name\"));\n        if (toolWindow != null) {\n            // Get the content manager for the tool window\n            ContentManager contentManager = toolWindow.getContentManager();\n            // Get the currently selected content\n            Content selectedContent = contentManager.getSelectedContent();\n            assert selectedContent != null;\n            // Get the tab name of the selected content\n            String selectedContentTabName = selectedContent.getTabName();\n            // Store the index of the selected content\n            int selectedIndex = contentManager.getIndexOfContent(selectedContent);\n            // Remove the selected content\n            contentManager.removeContent(selectedContent, true);\n            // Iterate through all contents in the content manager\n            for (int i = 0; i < contentManager.getContentCount(); i++) {\n                // Get the current content\n                Content content = contentManager.getContent(i);\n                assert content != null;\n                // Get the tab name of the current content\n                String tabName = content.getTabName();\n                // Remove the current content\n                contentManager.removeContent(content, true);\n                // Create a new content with the same tab name\n                Content browser = ContentFactory.SERVICE.getInstance().createContent(\n                        new ChatGPTToolWindow(tabName).getContent(), tabName, false);\n                // Add the new content to the content manager\n                contentManager.addContent(browser);\n            }\n            // Set the new content as the selected content using the updated selectedIndex\n            Content selectedBrowser = ContentFactory.SERVICE.getInstance().createContent(\n                    new ChatGPTToolWindow(selectedContentTabName).getContent(), selectedContentTabName,false);\n            contentManager.addContent(selectedBrowser, selectedIndex);\n            contentManager.setSelectedContent(selectedBrowser);\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/action/SettingsAction.java",
    "content": "package com.lilittlecat.chatgpt.action;\n\nimport com.intellij.icons.AllIcons;\nimport com.intellij.openapi.actionSystem.AnActionEvent;\nimport com.intellij.openapi.options.ShowSettingsUtil;\nimport com.intellij.openapi.project.DumbAwareAction;\nimport com.lilittlecat.chatgpt.setting.ChatGPTSettingsConfigurable;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class SettingsAction extends DumbAwareAction {\n\n    public SettingsAction(@NotNull @Nls String text) {\n        super(() -> text, AllIcons.General.Settings);\n    }\n\n    @Override\n    public void actionPerformed(@NotNull AnActionEvent e) {\n        ShowSettingsUtil.getInstance().showSettingsDialog(e.getProject(), ChatGPTSettingsConfigurable.class);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/message/ChatGPTBundle.java",
    "content": "package com.lilittlecat.chatgpt.message;\n\nimport com.intellij.DynamicBundle;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NonNls;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.PropertyKey;\n\nimport java.util.function.Supplier;\n\n/**\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class ChatGPTBundle extends DynamicBundle {\n    @NonNls\n    public static final String BUNDLE = \"messages.ChatGPTBundle\";\n    private static final ChatGPTBundle INSTANCE = new ChatGPTBundle();\n\n    private ChatGPTBundle() {\n        super(BUNDLE);\n    }\n\n    @NotNull\n    public static @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {\n        return INSTANCE.getMessage(key, params);\n    }\n\n    @NotNull\n    public static Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) {\n        return INSTANCE.getLazyMessage(key, params);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/AddOrEditUrl.form",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class=\"com.lilittlecat.chatgpt.setting.AddOrEditUrl\">\n  <grid id=\"cbd77\" binding=\"contentPane\" layout-manager=\"GridLayoutManager\" row-count=\"2\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n    <margin top=\"10\" left=\"10\" bottom=\"10\" right=\"10\"/>\n    <constraints>\n      <xy x=\"48\" y=\"54\" width=\"436\" height=\"297\"/>\n    </constraints>\n    <properties/>\n    <border type=\"none\"/>\n    <children>\n      <grid id=\"94766\" layout-manager=\"GridLayoutManager\" row-count=\"1\" column-count=\"2\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n        <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n        <constraints>\n          <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"1\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties/>\n        <border type=\"none\"/>\n        <children>\n          <hspacer id=\"98af6\">\n            <constraints>\n              <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"1\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n          </hspacer>\n          <grid id=\"9538f\" layout-manager=\"GridLayoutManager\" row-count=\"1\" column-count=\"2\" same-size-horizontally=\"true\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n            <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n            <constraints>\n              <grid row=\"0\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties/>\n            <border type=\"none\"/>\n            <children>\n              <component id=\"e7465\" class=\"javax.swing.JButton\" binding=\"buttonOK\">\n                <constraints>\n                  <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"0\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                </constraints>\n                <properties>\n                  <text value=\"OK\"/>\n                </properties>\n              </component>\n              <component id=\"5723f\" class=\"javax.swing.JButton\" binding=\"buttonCancel\">\n                <constraints>\n                  <grid row=\"0\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"0\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                </constraints>\n                <properties>\n                  <text value=\"Cancel\"/>\n                </properties>\n              </component>\n            </children>\n          </grid>\n        </children>\n      </grid>\n      <grid id=\"e3588\" layout-manager=\"GridLayoutManager\" row-count=\"2\" column-count=\"2\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n        <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n        <constraints>\n          <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties/>\n        <border type=\"none\"/>\n        <children>\n          <component id=\"45ebb\" class=\"javax.swing.JTextField\" binding=\"textField1\" default-binding=\"true\">\n            <constraints>\n              <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"2\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n                <preferred-size width=\"150\" height=\"-1\"/>\n              </grid>\n            </constraints>\n            <properties/>\n          </component>\n          <vspacer id=\"22b09\">\n            <constraints>\n              <grid row=\"0\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n          </vspacer>\n          <component id=\"f9ce4\" class=\"javax.swing.JLabel\">\n            <constraints>\n              <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties>\n              <text value=\"Url\"/>\n            </properties>\n          </component>\n        </children>\n      </grid>\n    </children>\n  </grid>\n</form>\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/AddOrEditUrl.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport javax.swing.*;\nimport java.awt.event.*;\n\npublic class AddOrEditUrl extends JDialog {\n    private JPanel contentPane;\n    private JButton buttonOK;\n    private JButton buttonCancel;\n    private JTextField textField1;\n\n    public AddOrEditUrl() {\n        setContentPane(contentPane);\n        setModal(true);\n        getRootPane().setDefaultButton(buttonOK);\n\n        buttonOK.addActionListener(new ActionListener() {\n            public void actionPerformed(ActionEvent e) {\n                onOK();\n            }\n        });\n\n        buttonCancel.addActionListener(new ActionListener() {\n            public void actionPerformed(ActionEvent e) {\n                onCancel();\n            }\n        });\n\n        // call onCancel() when cross is clicked\n        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);\n        addWindowListener(new WindowAdapter() {\n            public void windowClosing(WindowEvent e) {\n                onCancel();\n            }\n        });\n\n        // call onCancel() on ESCAPE\n        contentPane.registerKeyboardAction(new ActionListener() {\n            public void actionPerformed(ActionEvent e) {\n                onCancel();\n            }\n        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);\n    }\n\n    private void onOK() {\n        // add your code here\n        dispose();\n    }\n\n    private void onCancel() {\n        // add your code here if necessary\n        dispose();\n    }\n\n    public static void main(String[] args) {\n        AddOrEditUrl dialog = new AddOrEditUrl();\n        dialog.pack();\n        dialog.setVisible(true);\n        System.exit(0);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/ChatGPTSettingsComponent.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport com.intellij.ui.components.JBLabel;\nimport com.intellij.ui.components.JBList;\nimport com.intellij.ui.components.JBScrollPane;\nimport com.intellij.ui.components.JBTextArea;\nimport com.intellij.ui.table.JBTable;\nimport com.intellij.util.ui.FormBuilder;\nimport com.intellij.util.ui.ListTableModel;\nimport com.intellij.util.ui.UIUtil;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\n\nimport javax.swing.*;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class ChatGPTSettingsComponent {\n    private final JPanel myMainPanel;\n    private final JBTextArea sessionToken = new JBTextArea();\n    private final JBTextArea defaultUrl = new JBTextArea();\n    private final JBTable urlTable = new JBTable();\n\n    public ChatGPTSettingsComponent() {\n        sessionToken.setFont(UIUtil.getLabelFont());\n        sessionToken.setLineWrap(true);\n        JBScrollPane scrollPane = new JBScrollPane(sessionToken,\n                ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,\n                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);\n        myMainPanel = FormBuilder.createFormBuilder()\n//                .addLabeledComponent(new JBLabel(ChatGPTBundle.message(\"setting.session.token.label\")), scrollPane, 1, false)\n                .addLabeledComponent(new JBLabel(ChatGPTBundle.message(\"setting.session.token.label\")), sessionToken, 1, false)\n                .addLabeledComponent(new JBLabel(\"Table\"), urlTable)\n                .addComponentFillVertically(new JPanel(), 0)\n                .getPanel();\n    }\n\n    public JPanel getPanel() {\n        return myMainPanel;\n    }\n\n    public JComponent getPreferredFocusedComponent() {\n        return sessionToken;\n    }\n\n    public String getSessionToken() {\n        return sessionToken.getText();\n    }\n\n    public void setSessionToken(String token) {\n        sessionToken.setText(token);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/ChatGPTSettingsConfigurable.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport com.intellij.openapi.Disposable;\nimport com.intellij.openapi.application.ApplicationManager;\nimport com.intellij.openapi.options.SearchableConfigurable;\nimport com.intellij.openapi.ui.ComboBox;\nimport com.intellij.openapi.ui.cellvalidators.StatefulValidatingCellEditor;\nimport com.intellij.openapi.ui.cellvalidators.ValidatingTableCellRendererWrapper;\nimport com.intellij.openapi.ui.cellvalidators.ValidationUtils;\nimport com.intellij.openapi.util.Disposer;\nimport com.intellij.openapi.util.text.StringUtil;\nimport com.intellij.ui.*;\nimport com.intellij.ui.components.JBLabel;\nimport com.intellij.ui.components.JBScrollPane;\nimport com.intellij.ui.components.JBTextArea;\nimport com.intellij.ui.components.fields.ExtendableTextField;\nimport com.intellij.ui.table.JBTable;\nimport com.intellij.util.messages.MessageBusConnection;\nimport com.intellij.util.ui.*;\nimport com.lilittlecat.chatgpt.action.FetchURLAction;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport org.jetbrains.annotations.Nls;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport javax.swing.*;\nimport javax.swing.event.ChangeEvent;\nimport javax.swing.event.TableModelEvent;\nimport java.awt.*;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class ChatGPTSettingsConfigurable implements SearchableConfigurable {\n\n    private MessageBusConnection connection;\n\n    // A default constructor with no arguments is required because this implementation\n    // is registered as an applicationConfigurable EP\n    public ChatGPTSettingsConfigurable() {\n        connection = ApplicationManager.getApplication().getMessageBus().connect();\n        connection.subscribe(UpdateChatGPTSettingStateTopic.TOPIC, this::refreshUI);\n        init();\n    }\n\n    private void refreshUI() {\n        // Update the defaultUrlComboBox\n        defaultUrlComboBox.removeAllItems();\n        List<String> items = ChatGPTSettingsState.getInstance().urlList;\n        for (String item : items) {\n            defaultUrlComboBox.addItem(item);\n        }\n        defaultUrlComboBox.setSelectedItem(ChatGPTSettingsState.getInstance().defaultUrl);\n\n        // Update the myModel\n        myModel.setItems(ChatGPTSettingsState.getInstance().urlList);\n    }\n\n    @Override\n    public void disposeUIResources() {\n        // Disconnect the message bus connection when the UI is disposed\n        connection.disconnect();\n        Disposer.dispose(myDisposable);\n    }\n\n    @Override\n    public @NotNull String getId() {\n        return \"com.lilittlecat.chatgpt.setting.ChatGPTSettingConfigurable\";\n    }\n\n    public void addUrl(@NotNull String url) {\n        if (StringUtil.isNotEmpty(url)) {\n            defaultUrlComboBox.addItem(url);\n            myModel.addRow(url);\n        }\n    }\n\n    private Disposable myDisposable = Disposer.newDisposable();\n\n    private JPanel myMainPanel;\n    private JBTextArea sessionToken = new JBTextArea();\n    private JComboBox<String> defaultUrlComboBox;\n\n    private ListTableModel<String> myModel;\n\n    private JBTable myTable;\n\n    private JComponent init() {\n        myModel = new ListTableModel<>() {\n            @Override\n            public void addRow() {\n                // add item to table\n                addRow(\"\");\n            }\n\n            @Override\n            public void removeRow(int idx) {\n                String item = getItem(idx);\n                if (item.equals(ChatGPTSettingsState.getInstance().defaultUrl)) {\n                    // popup a dialog to tell user that the default url can't be removed\n                    JOptionPane.showMessageDialog(null, ChatGPTBundle.message(\"chatgpt.settings.defaultUrlCanNotBeRemoved\"));\n                } else if (item.equals(ChatGPTBundle.message(\"original.url\"))) {\n                    // popup a dialog to tell user that the original url can't be removed\n                    JOptionPane.showMessageDialog(null, ChatGPTBundle.message(\"chatgpt.settings.originalUrlCanNotBeRemoved\"));\n                } else {\n                    // remove item from table\n                    super.removeRow(idx);\n                    // remove item from comboBox\n                    defaultUrlComboBox.removeItemAt(idx);\n                }\n            }\n\n            @NotNull\n            @Override\n            public List<String> getItems() {\n                List<String> items = super.getItems();\n                // change Collections.unmodifiableList to ArrayList\n                return new ArrayList<>(items);\n            }\n\n        };\n\n        // init table\n        myModel.addRows(ChatGPTSettingsState.getInstance().urlList);\n        myTable = new JBTable(myModel) {\n            @Override\n            public void editingCanceled(ChangeEvent e) {\n                int row = getEditingRow();\n                super.editingCanceled(e);\n                if (row >= 0 && row < myModel.getRowCount() && StringUtil.isEmpty(myModel.getRowValue(row))) {\n                    myModel.removeRow(row);\n                }\n            }\n        };\n        JComponent table = createTable();\n        table.setPreferredSize(new Dimension(500, 200));\n        createComboBox();\n\n        sessionToken.setFont(UIUtil.getLabelFont());\n        sessionToken.setLineWrap(true);\n        JBScrollPane scrollPane = new JBScrollPane(sessionToken,\n                ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,\n                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);\n        myMainPanel = FormBuilder.createFormBuilder()\n                .addLabeledComponent(new JBLabel(ChatGPTBundle.message(\"setting.session.token.label\")), scrollPane, 1, true)\n                .addLabeledComponent(new JBLabel(ChatGPTBundle.message(\"default.url.message\")), defaultUrlComboBox, 1, false)\n                .addLabeledComponent(new SeparatorComponent(), new JPanel(), 1, false)\n                .addLabeledComponent(new JBLabel(ChatGPTBundle.message(\"url.list.message\")), table, 3, true)\n                .addComponentFillVertically(new JPanel(), 0)\n                .getPanel();\n        return myMainPanel;\n    }\n\n    private void createComboBox() {\n        // get value from myTable dynamically and set first value in myTable as default value of comboBox\n        defaultUrlComboBox = new ComboBox<>();\n        Dimension preferredSize = defaultUrlComboBox.getPreferredSize();\n        preferredSize.width = 200; // Set the desired width here\n        defaultUrlComboBox.setPreferredSize(preferredSize);\n        List<String> items = myModel.getItems();\n        for (String item : items) {\n            defaultUrlComboBox.addItem(item);\n        }\n        defaultUrlComboBox.setSelectedItem(ChatGPTSettingsState.getInstance().defaultUrl);\n    }\n\n    private JComponent createTable() {\n\n        myModel.setColumnInfos(new ColumnInfo[]{new ColumnInfo<String, String>(\"\") {\n\n            @Override\n            public @Nullable String valueOf(String s) {\n                return s;\n            }\n\n            @Override\n            public boolean isCellEditable(String s) {\n                return true;\n            }\n\n            @Override\n            public void setValue(String s, String value) {\n                int row = myTable.getSelectedRow();\n                if (StringUtil.isEmpty(value) && row >= 0 && row < myModel.getRowCount()) {\n                    myModel.removeRow(row);\n                    defaultUrlComboBox.removeItemAt(row);\n                }\n                List<String> items = new ArrayList<>(myModel.getItems());\n                items.set(row, value);\n                myModel.setItems(items);\n                myModel.fireTableCellUpdated(row, TableModelEvent.ALL_COLUMNS);\n                myTable.repaint();\n                // add to comboBox\n                defaultUrlComboBox.addItem(value);\n            }\n        }});\n        myTable.getColumnModel().setColumnMargin(0);\n        myTable.setShowColumns(false);\n        myTable.setShowGrid(false);\n        myTable.getEmptyText().setText(\"No websites added.\");\n        myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\n        myTable.setToolTipText(\"Double click to edit it\");\n\n        ExtendableTextField cellEditor = new ExtendableTextField();\n        DefaultCellEditor editor = new StatefulValidatingCellEditor(cellEditor, myDisposable).\n                withStateUpdater(vi -> ValidationUtils.setExtension(cellEditor, vi));\n        editor.setClickCountToStart(2);\n        myTable.setDefaultEditor(Object.class, editor);\n\n        myTable.setDefaultRenderer(Object.class, new ValidatingTableCellRendererWrapper(new ColoredTableCellRenderer() {\n            {\n                setIpad(new JBInsets(0, 0, 0, 0));\n            }\n\n            @Override\n            protected void customizeCellRenderer(@NotNull JTable table, @Nullable Object value, boolean selected, boolean hasFocus, int row, int column) {\n                if (row >= 0 && row < myModel.getRowCount()) {\n                    String prefix = myModel.getRowValue(row);\n                    setForeground(selected ? table.getSelectionForeground() : table.getForeground());\n                    setBackground(selected ? table.getSelectionBackground() : table.getBackground());\n                    append(prefix, SimpleTextAttributes.REGULAR_ATTRIBUTES);\n                    setToolTipText(\"Double click to edit it.\");\n                }\n            }\n\n            @Override\n            protected SimpleTextAttributes modifyAttributes(SimpleTextAttributes attributes) {\n                return attributes;\n            }\n        }).bindToEditorSize(cellEditor::getPreferredSize));\n\n        AnActionButton fetchUrlListFromGithub = AnActionButton.fromAction(new FetchURLAction(ChatGPTBundle.message(\"chatgpt.settings.fetch.url.list.from.github\")));\n        return ToolbarDecorator.createDecorator(myTable)\n                .addExtraAction(fetchUrlListFromGithub)\n                .disableUpDownActions()\n                .createPanel();\n    }\n\n\n    @Nls(capitalization = Nls.Capitalization.Title)\n    @Override\n    public String getDisplayName() {\n        return ChatGPTBundle.message(\"setting.menu.text\");\n    }\n\n    @Override\n    public JComponent getPreferredFocusedComponent() {\n        return defaultUrlComboBox;\n    }\n\n    @Nullable\n    @Override\n    public JComponent createComponent() {\n        return myMainPanel;\n    }\n\n    @Override\n    public boolean isModified() {\n        ChatGPTSettingsState instance = ChatGPTSettingsState.getInstance();\n        boolean modified = false;\n        modified = !instance.defaultUrl.equals(defaultUrlComboBox.getSelectedItem());\n        List<String> urlList = instance.urlList;\n        List<String> items = myModel.getItems();\n        modified |= urlList.size() != items.size();\n        modified |= !urlList.equals(items);\n        modified |= !instance.sessionToken.equals(sessionToken.getText());\n        return modified;\n    }\n\n    @Override\n    public void apply() {\n        myTable.editingStopped(null);\n        ChatGPTSettingsState instance = ChatGPTSettingsState.getInstance();\n        instance.defaultUrl = Objects.requireNonNull(defaultUrlComboBox.getSelectedItem()).toString();\n        instance.urlList = myModel.getItems();\n        instance.sessionToken = sessionToken.getText();\n        // Refresh the UI after updating the settings\n        refreshUI();\n//        instance.urlList.addAll(myModel.getItems());\n    }\n\n    @Override\n    public void reset() {\n        ChatGPTSettingsState instance = ChatGPTSettingsState.getInstance();\n        myModel.setItems(instance.urlList);\n        defaultUrlComboBox.removeAllItems();\n        for (String s : instance.urlList) {\n            defaultUrlComboBox.addItem(s);\n        }\n        defaultUrlComboBox.setSelectedItem(instance.defaultUrl);\n        sessionToken.setText(instance.sessionToken);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/ChatGPTSettingsState.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport com.intellij.openapi.application.ApplicationManager;\nimport com.intellij.openapi.components.PersistentStateComponent;\nimport com.intellij.openapi.components.State;\nimport com.intellij.openapi.components.Storage;\nimport com.intellij.util.xmlb.XmlSerializerUtil;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.List;\nimport java.util.ResourceBundle;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\n@State(\n        name = \"com.lilittlecat.chatgpt.setting.ChatGPTSettingsState\",\n        storages = @Storage(\"ChatGPTSettingsState.xml\")\n)\npublic class ChatGPTSettingsState implements PersistentStateComponent<ChatGPTSettingsState> {\n\n    public String sessionToken = \"\";\n\n    public String defaultUrl = ChatGPTBundle.message(\"default.url\");\n\n    public List<String> urlList;\n\n    public ChatGPTSettingsState() {\n        urlList = new ArrayList<>();\n        urlList.add(ChatGPTBundle.message(\"default.url\"));\n//        ResourceBundle bundle = ResourceBundle.getBundle(ChatGPTBundle.BUNDLE);\n//        Enumeration<String> keys = bundle.getKeys();\n//        while (keys.hasMoreElements()) {\n//            String key = keys.nextElement();\n//            if (key.startsWith(\"url\")) {\n//                String url = bundle.getString(key);\n//                System.out.println(key + \": \" + url);\n//                urlList.add(url);\n//            }\n//        }\n    }\n\n    @Nullable\n    @Override\n    public ChatGPTSettingsState getState() {\n        return this;\n    }\n\n    @Override\n    public void loadState(@NotNull ChatGPTSettingsState state) {\n        XmlSerializerUtil.copyBean(state, this);\n    }\n\n//    public void setSessionToken(String sessionToken) {\n//        this.sessionToken = sessionToken;\n//    }\n\n    public void setDefaultUrl(String defaultUrl) {\n        this.defaultUrl = defaultUrl;\n    }\n\n    public void setUrlList(List<String> urlList) {\n        this.urlList = urlList;\n    }\n\n    public String getSessionToken() {\n        return sessionToken;\n    }\n\n    public void setSessionToken(String sessionToken) {\n        this.sessionToken = sessionToken;\n    }\n\n    public static ChatGPTSettingsState getInstance() {\n        return ApplicationManager.getApplication().getService(ChatGPTSettingsState.class);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/Test.form",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class=\"com.lilittlecat.chatgpt.setting.Test\">\n  <grid id=\"27dc6\" binding=\"myMainPanel\" layout-manager=\"GridLayoutManager\" row-count=\"1\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n    <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n    <constraints>\n      <xy x=\"20\" y=\"20\" width=\"408\" height=\"400\"/>\n    </constraints>\n    <properties/>\n    <border type=\"none\"/>\n    <children>\n      <grid id=\"e7f17\" layout-manager=\"GridLayoutManager\" row-count=\"3\" column-count=\"2\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n        <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n        <constraints>\n          <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n        </constraints>\n        <properties/>\n        <border type=\"none\"/>\n        <children>\n          <component id=\"87bc6\" class=\"javax.swing.JLabel\">\n            <constraints>\n              <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties>\n              <text value=\"Default Website\"/>\n            </properties>\n          </component>\n          <component id=\"89d5d\" class=\"javax.swing.JComboBox\" binding=\"defaultWebsite\">\n            <constraints>\n              <grid row=\"0\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"2\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties/>\n          </component>\n          <component id=\"7af06\" class=\"javax.swing.JLabel\">\n            <constraints>\n              <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties>\n              <text value=\"Third Party Websites\"/>\n            </properties>\n          </component>\n          <grid id=\"9f58\" layout-manager=\"BorderLayout\" hgap=\"0\" vgap=\"0\">\n            <constraints>\n              <grid row=\"2\" column=\"0\" row-span=\"1\" col-span=\"2\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n            </constraints>\n            <properties/>\n            <border type=\"none\"/>\n            <children/>\n          </grid>\n        </children>\n      </grid>\n    </children>\n  </grid>\n</form>\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/Test.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport com.intellij.ui.components.JBComboBoxLabel;\n\nimport javax.swing.*;\n\n/**\n * @author <a href=\"https://github.com/LiLittleCat\">LiLittleCat</a>\n * @since 2023/3/9\n */\npublic class Test {\n    private JPanel myMainPanel;\n    private JComboBox defaultWebsite;\n    private JSpinner spinner1;\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/setting/UpdateChatGPTSettingStateTopic.java",
    "content": "package com.lilittlecat.chatgpt.setting;\n\nimport com.intellij.util.messages.Topic;\n\n/**\n * A topic for changing the state of the settings.\n *\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2023/3/21\n */\npublic interface UpdateChatGPTSettingStateTopic {\n    Topic<UpdateChatGPTSettingStateTopic> TOPIC = Topic.create(\"Update Field Topic\", UpdateChatGPTSettingStateTopic.class);\n\n    void stateChanged();\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/window/ChatGPTToolWindow.java",
    "content": "package com.lilittlecat.chatgpt.window;\n\n\nimport com.intellij.openapi.ui.SimpleToolWindowPanel;\nimport com.intellij.ui.jcef.JBCefApp;\nimport com.intellij.ui.jcef.JBCefBrowser;\nimport com.intellij.ui.jcef.JBCefCookie;\nimport com.intellij.ui.jcef.JBCefCookieManager;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport com.lilittlecat.chatgpt.setting.ChatGPTSettingsState;\nimport org.apache.commons.lang3.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.swing.*;\nimport javax.swing.event.HyperlinkEvent;\nimport java.awt.*;\nimport java.io.IOException;\nimport java.net.URISyntaxException;\nimport java.util.List;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class ChatGPTToolWindow extends SimpleToolWindowPanel {\n    private static final Logger LOG = LoggerFactory.getLogger(ChatGPTToolWindow.class);\n\n    private final JPanel content;\n\n    private final String sessionTokenName = \"__Secure-next-auth.session-token\";\n\n    ThreadPoolExecutor executor = new ThreadPoolExecutor(\n            1, 10, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));\n\n    public ChatGPTToolWindow(String url) {\n        super(true, false);\n        this.content = new JPanel(new BorderLayout());\n        if (!JBCefApp.isSupported()) {\n            JEditorPane editorPane = new JEditorPane(\"text/html\", ChatGPTBundle.message(\"jBCefApp.not.supported\"));\n            editorPane.setEditable(false);\n            editorPane.setOpaque(false);\n            editorPane.addHyperlinkListener(e -> {\n                if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {\n                    try {\n                        java.awt.Desktop.getDesktop().browse(e.getURL().toURI());\n                    } catch (IOException | URISyntaxException ex) {\n                        ex.printStackTrace();\n                    }\n                }\n            });\n            JOptionPane.showMessageDialog(null, editorPane);\n//            this.content.add(new JLabel(ChatGPTBundle.message(\"jBCefApp.not.supported\"), SwingConstants.CENTER));\n            this.content.add(editorPane, SwingConstants.CENTER);\n            return;\n        }\n        JBCefBrowser jbCefBrowser = new JBCefBrowser();\n        this.content.add(jbCefBrowser.getComponent(), BorderLayout.CENTER);\n        if (url.equals(ChatGPTBundle.message(\"default.url\"))) {\n            setCookieForOfficalWebsite(url);\n        }\n        jbCefBrowser.loadURL(url);\n    }\n\n    private void setCookieForOfficalWebsite(String url) {\n        JBCefCookieManager jbCefCookieManager = new JBCefCookieManager();\n        // find if there is session token in settings\n        ChatGPTSettingsState state = ChatGPTSettingsState.getInstance().getState();\n        if (state != null) {\n            String sessionToken = state.sessionToken;\n            if (StringUtils.isNotBlank(sessionToken)) {\n                // check the token is right or not\n\n                // 2022.12.16 with Cloudflare, can not check token by http get\n\n//                String cookie = sessionTokenName + \"=\" + sessionToken;\n//                HttpGet httpGet = new HttpGet(\"https://chat.openai.com/chat\");\n//                httpGet.setHeader(\"Connection\", \"keep-alive\");\n//                httpGet.setHeader(\"User-Agent\", \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15\");\n//                httpGet.setHeader(\"Cookie\", cookie);\n//                httpGet.setHeader(\"Origin\", \"https://auth0.openai.com\");\n//                httpGet.setHeader(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\");\n//                httpGet.setHeader(\"Accept-Language\", \"en-US,en;q=0.9\");\n//                try (CloseableHttpClient httpClient = HttpClients.createDefault();\n//                     CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {\n//                    HttpEntity httpEntity = httpResponse.getEntity();\n//                    String bodyString = EntityUtils.toString(httpEntity);\n//                    if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK && !bodyString.contains(\"Welcome to ChatGPT\")) {\n                JBCefCookie jbCefCookie = new JBCefCookie(sessionTokenName, sessionToken, \"chat.openai.com\", \"/\", true, true);\n                // use async set\n                jbCefCookieManager.setCookie(ChatGPTBundle.message(\"default.url\"), jbCefCookie, false);\n//                    }\n//                } catch (IOException e) {\n//                    LOG.error(\"Error when check session token: \", e);\n//                }\n            }\n        }\n        // get session token after login, fill it in settings\n        // fill it every login, in case invalid session token cause can't login problem\n        executor.execute(() -> {\n            String currentSessionToken = null;\n            while (currentSessionToken == null) {\n                List<JBCefCookie> cookies = jbCefCookieManager.getCookies();\n                if (!cookies.isEmpty()) {\n                    for (JBCefCookie cookie : cookies) {\n                        if (cookie.getName().equals(sessionTokenName)) {\n                            currentSessionToken = cookie.getValue();\n                            ChatGPTSettingsState.getInstance().setSessionToken(currentSessionToken);\n                        }\n                    }\n                }\n                try {\n                    Thread.sleep(1000L);\n                } catch (InterruptedException e) {\n                    throw new RuntimeException(e);\n                }\n            }\n        });\n    }\n\n    public JPanel getContent() {\n        return content;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/lilittlecat/chatgpt/window/ChatGPTToolWindowFactory.java",
    "content": "package com.lilittlecat.chatgpt.window;\n\nimport com.intellij.openapi.actionSystem.AnAction;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.wm.ToolWindow;\nimport com.intellij.openapi.wm.ToolWindowFactory;\nimport com.intellij.ui.content.Content;\nimport com.intellij.ui.content.ContentManager;\nimport com.intellij.ui.content.ContentManagerEvent;\nimport com.intellij.ui.content.ContentManagerListener;\nimport com.lilittlecat.chatgpt.action.*;\nimport com.lilittlecat.chatgpt.message.ChatGPTBundle;\nimport com.lilittlecat.chatgpt.setting.ChatGPTSettingsState;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author LiLittleCat\n * @link <a href=\"https://github.com/LiLittleCat\">https://github.com/LiLittleCat</a>\n * @since 2022/12/10\n */\npublic class ChatGPTToolWindowFactory implements ToolWindowFactory {\n    @Override\n    public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {\n        ContentManager contentManager = toolWindow.getContentManager();\n        Content labelContent = contentManager.getFactory().createContent(\n                new ChatGPTToolWindow(ChatGPTSettingsState.getInstance().defaultUrl).getContent(),\n                ChatGPTSettingsState.getInstance().defaultUrl, false);\n        contentManager.addContent(labelContent);\n        contentManager.addContentManagerListener(\n                new ContentManagerListener() {\n                    @Override\n                    public void contentRemoved(@NotNull ContentManagerEvent event) {\n                        // when all tabs are closed, add a new tab\n                        if (contentManager.getContentCount() == 0) {\n                            Content labelContent = contentManager.getFactory().createContent(\n                                    new ChatGPTToolWindow(ChatGPTSettingsState.getInstance().defaultUrl).getContent(),\n                                    ChatGPTSettingsState.getInstance().defaultUrl, false);\n                            contentManager.addContent(labelContent);\n                        }\n                    }\n                }\n        );\n        // add actions to tool window\n        List<AnAction> anActionList = new ArrayList<>();\n        anActionList.add(new SettingsAction(ChatGPTBundle.message(\"settings.action\")));\n        anActionList.add(new RefreshAction(ChatGPTBundle.message(\"refresh.action\")));\n        anActionList.add(new AddTabAction(ChatGPTBundle.message(\"add.tab.action\")));\n        anActionList.add(new GitHubAction(ChatGPTBundle.message(\"github.action\")));\n        anActionList.add(new MorePluginAction(ChatGPTBundle.message(\"more.plugins.action\")));\n        toolWindow.setTitleActions(anActionList);\n    }\n}\n"
  },
  {
    "path": "src/main/resources/META-INF/plugin.xml",
    "content": "<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->\n<idea-plugin>\n    <id>com.lilittlecat.intellij-chatgpt</id>\n    <name>ChatGPT Tool</name>\n    <vendor email=\"lilittlecat@qq.com\" url=\"https://github.com/LiLittleCat\">\n        LiLittleCat\n    </vendor>\n\n    <depends>com.intellij.modules.platform</depends>\n\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <toolWindow factoryClass=\"com.lilittlecat.chatgpt.window.ChatGPTToolWindowFactory\" icon=\"/icons/openai.svg\" id=\"ChatGPT Tool\" anchor=\"right\" canCloseContents=\"true\"/>\n        <applicationConfigurable\n                parentId=\"tools\"\n                instance=\"com.lilittlecat.chatgpt.setting.ChatGPTSettingsConfigurable\"\n                id=\"com.lilittlecat.chatgpt.setting.ChatGPTSettingsConfigurable\"\n                displayName=\"ChatGPT Tool\"/>\n        <applicationService serviceImplementation=\"com.lilittlecat.chatgpt.setting.ChatGPTSettingsState\"/>\n    </extensions>\n</idea-plugin>\n"
  },
  {
    "path": "src/main/resources/messages/ChatGPTBundle.properties",
    "content": "name=ChatGPT Tool\nsetting.session.token.label=Session token(only for https://chat.openai.com):\nsetting.menu.text=ChatGPT Tool\ndefault.url.message=Default URL:\nurl.list.message=URL list:\noriginal.url=https://chat.openai.com\ndefault.url=https://chat.openai.com\nurl1=https://baidu.com\nurl2=https://jd.com\nurl3=https://bilibili.com\nurl4=https://douyu.com\n\njBCefApp.not.supported=<html><body style='text-align: center; display: flex; justify-content: center; align-items: center; height: 100%;'> \\\n  Sorry, your IDE does not support JCEF, please use IDEA 2020.2 or later.<br>\\\n  \\ See <a href=https://plugins.jetbrains.com/docs/intellij/jcef.html?from=jetbrains.org>jcef</a> and <a href=https://github.com/LiLittleCat/intellij-chatgpt/issues/3>issue 3</a> for more details.\\\n  </body></html>\nchatgpt.settings.defaultUrlCanNotBeRemoved=Default URL can not be removed.\nchatgpt.settings.originalUrlCanNotBeRemoved=Original URL can not be removed.\nchatgpt.settings.fetch.url.list.from.github=Fetch URL list from GitHub\n\nfree.chatgpt.file.url.original=https://raw.githubusercontent.com/LiLittleCat/awesome-free-chatgpt/main/urls.json\nfree.chatgpt.file.url.fallback=https://cdn.jsdelivr.net/gh/LiLittleCat/awesome-free-chatgpt/urls.json\ncannot.fetch.message=Can not fetch from remote, please check your network\nsuccess.fetch.message=Successfully fetched from remote\n\n\nsettings.action=Settings\nrefresh.action=Refresh\nadd.tab.action=Add Tab\ngithub.action=Author's GitHub\ngithub.url=https://github.com/LiLittleCat\nmore.plugins.action=More plugins from Author\nmore.plugins.url=https://plugins.jetbrains.com/organizations/LiLittleCat\n\n"
  },
  {
    "path": "src/test/testData/rename/foo.xml",
    "content": "<root>\n    <a<caret>1>Foo</a1>\n</root>\n"
  },
  {
    "path": "src/test/testData/rename/foo_after.xml",
    "content": "<root>\n    <a2>Foo</a2>\n</root>\n"
  }
]