Giter Club home page Giter Club logo

xechat-idea's Introduction

XEChat-Idea

Version 1.6.7-beta0

基于Netty的IDEA即时聊天插件:让你能够在IDEA里实现聊天、下棋、斗地主!(理论上支持JetBrains全系列开发工具🙂)

浏览器端:XEChat-Web

项目介绍

主要功能:

  • 即时聊天
  • 游戏对战
  • 待探索...

目前已实现:

游戏类

  • 五子棋(支持2人联机、人机对战,内置"人工制杖")
  • 斗地主(支持2~3人联机、人机对战)
  • 不贪吃蛇
  • 2048(作者 @浓睡不消残酒 ,感谢PR😊)
  • 数独(作者 @Speciallei ,感谢PR😊)
  • 推箱子(作者 @Speciallei ,感谢PR😊)
  • **象棋(支持2人联机、人机对战,作者 @15738383930 ,感谢PR😊)
  • 俄罗斯方块(作者 @SherlockerSun ,感谢PR😊)
  • 扫雷(作者 @SherlockerSun ,感谢PR😊)

工具类

了解更多...

项目结构

.
├── LICENSE
├── README.md
├── xechat-commons //公共模块
│   ├── pom.xml
│   └── src
├── xechat-plugin //IDEA插件端
│   ├── build.gradle
│   ├── gradle
│   ├── gradle.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── settings.gradle
│   └── src
└── xechat-server //服务端
    ├── pom.xml
    └── src

项目环境

服务端 & 公共模块

  • JDK8
  • Maven 3.6.x

IDEA 插件端

  • JDK11
  • Gradle 6.x

项目开发

运行 & 部署

提醒:公共模块需优先打包

# 进入公共模块根目录
cd xechat-commons
# 打包到本地仓库
mvn install

服务端

创建或调整日志目录 src/main/resources/logback.xml

<property name="ROOT_LOG_PATH" value="/var/log/xechat-server"/>

运行

直接运行主方法 XEChatServer.java

部署

# 进入服务端根目录
cd xechat-server
# 打包
mvn package
# 启动服务端
java -jar target/xechat-server-xxx.jar

启动参数:

  • 设置端口-p {端口号}
  • 设置敏感词文件-swfile {文件路径}
  • 设置和风天气-weather {和风api key}
  • 设置百度翻译-fyAppId {appId} -fyAppKey {appKey}
  • 设置ip2region文件-ipfile {文件路径}
  • 设置管理员令牌-token {令牌}
  • 指定外部配置文件-path {文件路径}
  • 开放WS协议-enableWS {true|false}

具体的外部配置文件信息请看:xechat-server/src/main/resources/config.setting

参考示例:

java -jar target/xechat-server-xxx.jar -p 1024 -swfile /Users/anlingyi/local/test/words.txt -weather {和风天气api key}

敏感词相关配置参考

和风天气相关配置参考

开放WS协议相关配置参考

IDEA插件端

修改IDEA版本

修改 build.gradle 配置文件,将 IDEA 版本号改为你想使用的版本(仅限开发调试阶段)

intellij {
    version '2021.3'
}

本地运行

Tasks > intellij > runIde

image.png

插件部署

提醒:修改服务端地址

进入到 cn.xeblog.plugin.client.XEChatClient ,修改以下变量值

    private static final String HOST = "localhost"; // 服务端IP
    private static final int PORT = 1024; // 服务端端口

打包

Tasks > build > assemble

image.png

打包完成后的文件 build/distributions/xechat-plugin-xxx.zip

安装

IDEA > Preferences > Plugins

image.png

选择打包后的文件安装 build/distributions/xechat-plugin-xxx.zip

安装体验

添加插件库 Plugins > 设置按钮 > Manage Plugin Repositories...

http://plugins.xeblog.cn

image.png

搜索 “xechat” 安装

image.png

如有条件,还请自行部署服务端。

Docker运行

感谢 @猎隼丶止戈 对此部分做的贡献 😊

镜像地址:https://hub.docker.com/r/anlingyi/xechat-server/tags

docker-compose.yml

version: '3'
services:
  xechat:
    image: anlingyi/xechat-server:1.6.7-beta
    container_name: xechat-server
    restart: always
    ports:
      - 1024:1024
      - 1025:1025
    volumes:
      - /home/xechat/logs:/var/log/xechat-server
      - /home/xechat/config/config.setting:/home/xechat/config/config.setting
      - /home/xechat/db:/home/xechat/db

公开你的鱼塘

如果你想公开你的鱼塘,请编辑项目中的 server_list.json 文件,添加上你的鱼塘信息,然后提交PR到这里,待我们审核通过后即可。

    {
        "name": "xxx", //鱼塘名
        "ip": "127.0.0.1", //你的服务器IP或域名
        "port": 1024 //端口号
    }

学习交流

感谢 @鹿儿岛 提供的QQ交流群 😊

如果大家对这个项目感兴趣,欢迎加入我们的交流群🎉

  • QQ群:754126966

xechat-idea's People

Contributors

15738383930 avatar anlingyi avatar codenooblh avatar easy-do avatar iamqiz avatar jiangtao69039 avatar minipuffer avatar nn200433 avatar sherlockersun avatar specialleiliei avatar zzz823968094 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xechat-idea's Issues

bug

AdminReactHandler.java #92行

ChannelAction.send(ResponseBuilder.build(execUser, null, MessageType.STATUS_UPDATE));
null 应该使用msg
ChannelAction.send(ResponseBuilder.build(execUser, msg, MessageType.STATUS_UPDATE));

image
image

关于MainWindow类中无用的属性contentPanel

public class MainWindow {
    private JPanel mainPanel;
    private JTextPane console;
    private JTextArea contentArea;
    private JPanel leftPanel;
    private JPanel rightPanel;
    private JPanel contentPanel;
    private JScrollPane consoleScroll;
    private JPanel leftTopPanel;

在这个类中,属性contentPanel在整个项目中都没用被使用。属性contentPanel在MainWindow.form中40行出现过。

 <grid id="eece8" binding="contentPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">

在整个项目中,属性contentPanel只在MainWindow.form中40行出现过,而且只是用于与MainWindow 类中的属性contentPanel绑定,绑定后实际没有使用,经过测试:
1.删除MainWindow 类中的属性contentPanel.
2.删除MainWindow.form中40行binding="contentPanel"
删除后项目与原先没有区别。

当通讯发生异常时,如果发生的用户是玩家,此时用户所在游戏房房主仍为游戏中状态,实际应该是鱼

XEChatServerHandler#

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    ChannelAction.cleanUser(ctx);
    ctx.close();
    log.error("error:", cause);
  }

ChannelAction#

/**
   * 清理指定用户
   * @param ctx 会话处理器上下文
   */
  public static void cleanUser(ChannelHandlerContext ctx) {
    cleanUser(getId(ctx));
  }

  /**
   * 通过id清理指定用户
   * @param id  用户id
   * @return 清理的用户信息
   */
  public static User cleanUser(String id) {
    log.debug("清理用户, id -> {}", id);

    User user = getUser(id);
    if (user == null) {
      return null;
    }

    log.debug("清理用户, username -> {}", user.getUsername());

    // 获取游戏房间号
    GameRoom gameRoom = GameRoomCache.getGameRoomByUserId(user.getId());
    if (gameRoom != null) {
      gameRoom.getUsers().forEach((k, v) -> {
        if (v.getId().equals(user.getId())) {
          return;
        }

        // 通知客户端玩家离开房间
        User player = UserCache.get(v.getId());
        if (player != null) {
          player.send(ResponseBuilder.build(user, new GameRoomMsgDTO(GameRoomMsgDTO.MsgType.PLAYER_LEFT, null), MessageType.GAME_ROOM));
        }
      });
      // 玩家离开房间
      GameRoomCache.leftRoom(gameRoom.getId(), user);
    }

    // 设置用户离线并移除相关缓存
    UserCache.remove(id);
    sendUserState(user, UserStateMsgDTO.State.OFFLINE);

    return user;
  }

GameRoomCache

  /**
     * 玩家离开房间
     *
     * @param roomId 房间ID
     * @param user   玩家
     * @return
     */
    public static boolean leftRoom(String roomId, User user) {
        // 查询游戏房间
        GameRoom gameRoom = GAME_ROOM_MAP.get(roomId);
        if (gameRoom == null) {
            return false;
        }

        // 从游戏房间移除玩家
        if (gameRoom.removeUser(user)) {
            // 从用户与房间的缓存中移除,即移除玩家与游戏房间的关联
            USER_ROOM_MAP.remove(user.getId());
            // 如果房间没人或者当前用户是房主
            if (gameRoom.getCurrentNums() == 0 || gameRoom.isHomeowner(user.getUsername())) {
                // 移除房间
                removeRoom(gameRoom.getId());
            }
            return true;
        }

        return false;
    }

    /**
     * 移除房间
     *
     * @param roomId 房间ID
     */
    public static void removeRoom(String roomId) {
        GameRoom gameRoom = getGameRoom(roomId);
        if (gameRoom == null) {
            return;
        }

        log.debug("游戏房间关闭 -> {}", gameRoom);

        // 先移除房间与房号的关联,再移除房间与玩家的关联
        GAME_ROOM_MAP.remove(roomId);
        if (gameRoom.getUsers().size() > 0) {
            gameRoom.getUsers().forEach((k, v) -> {
                USER_ROOM_MAP.remove(v.getId());
            });
        }

        //
        // 邀请的用户列表
        Set<User> userSet = new HashSet<>(gameRoom.getInviteUsers());
        // 房间内有玩家
        gameRoom.getUsers().forEach((k, v) -> {
            User user = UserCache.get(v.getId());
            if (user != null) {
                userSet.add(user);
            }
        });

        // 将非房主的玩家设置为“鱼”的状态
        if (userSet.size() > 0) {
            userSet.forEach(player -> {
                if (gameRoom.isHomeowner(player.getUsername())) {
                    return;
                }

                player.setStatus(UserStatus.FISHING);
                ChannelAction.updateUserStatus(player);
            });
        }
    }

removeRoom在这个方法中:

 if (gameRoom.isHomeowner(player.getUsername())) {
                    return;
 }

这里直接把房主过滤了

右键菜单颜色问题

当我从黑色主题切换到白色主题时就这样了,要重启才能还原
image
重启之后就正常了
image
当我从白色主题切换到黑色主题,就这样了,也要重启才能还原
image
重启之后就好了
image

关于版本校验bug

LoginActionHandler#handle

    String currentPluginVersion = CommonConstants.PLUGIN_VERSION;

    String userPluginVersion = body.getPluginVersion();

    // 这里是对用户版本和服务端版本补全,让两端版本长度一致
    if (StrUtil.isNotBlank(userPluginVersion)) {
        int len = currentPluginVersion.length();
        int len2 = userPluginVersion.length();
        int k = len - len2;
        String padding = "";
        for (int i = Math.abs(k); i > 0; i--) {
            padding += "0";
        }
        if (k > 0) {
            userPluginVersion += padding;
        } else if (k < 0) {
            currentPluginVersion += padding;
        }
    }

    // 比较版本,这里会用"."对用户版本和服务端版本进行切割,用于比较两端版本是否一致
    int versionState = VersionComparator.INSTANCE.compare(currentPluginVersion, userPluginVersion);
    // 客户端版本与服务端是否一致
    if (versionState > 0) {
        ctx.writeAndFlush(ResponseBuilder.system("温馨提醒~ 请尽快更新插件版本至v" + CommonConstants.PLUGIN_VERSION + "!"));
        ctx.close();
        return;
    }
    // 判断服务端版本是否有问题
    if (versionState < 0) {
        ctx.writeAndFlush(ResponseBuilder.system("当前服务端版本过低!你的版本:v" + body.getPluginVersion()
                + ",服务端版本:v" + CommonConstants.PLUGIN_VERSION));
        ctx.close();
        return;
    }

这里是不需要判断服务端的版本是否有问题,因为客户端本身就应该与服务端的版本一致,客户端不应该超过服务端的版本

报错了,就想摸个鱼,这么难的么?

A problem occurred configuring root project 'xechat-plugin'.

Could not resolve all artifacts for configuration ':classpath'.
Could not resolve org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.7.2.
Required by:
project : > org.jetbrains.intellij:org.jetbrains.intellij.gradle.plugin:0.7.2
> Could not resolve org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.7.2.
> Could not get resource 'https://plugins.gradle.org/m2/org/jetbrains/intellij/plugins/gradle-intellij-plugin/0.7.2/gradle-intellij-plugin-0.7.2.module'.
> Could not GET 'https://jcenter.bintray.com/org/jetbrains/intellij/plugins/gradle-intellij-plugin/0.7.2/gradle-intellij-plugin-0.7.2.module'.
> sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

  • Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Exception is:
    org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'xechat-plugin'.
    at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:80)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:73)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.access$600(LifecycleProjectEvaluator.java:53)
    at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject$1.run(LifecycleProjectEvaluator.java:109)
    at org.gradle.internal.Factories$1.create(Factories.java:26)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
    at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withProjectLock(DefaultProjectStateRegistry.java:238)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:232)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:193)
    at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:96)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68)
    at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:699)
    at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:142)
    at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:36)
    at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
    at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:61)
    at org.gradle.configuration.BuildOperatingFiringProjectsPreparer$ConfigureBuild.run(BuildOperatingFiringProjectsPreparer.java:52)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.BuildOperatingFiringProjectsPreparer.prepareProjects(BuildOperatingFiringProjectsPreparer.java:40)
    at org.gradle.initialization.DefaultGradleLauncher.prepareProjects(DefaultGradleLauncher.java:207)
    at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:145)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:130)
    at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:110)
    at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:60)
    at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:57)
    at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:85)
    at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:78)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
    at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
    at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:78)
    at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:57)
    at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:60)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
    at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
    at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
    at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:80)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
    at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
    at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
    at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
    at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
    at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:60)
    at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:38)
    at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
    at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
    at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
    at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
    at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
    at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
    at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
    at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
    at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
    at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
    at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
    at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:27)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all artifacts for configuration ':classpath'.
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:1293)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$2300(DefaultConfiguration.java:140)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationArtifactCollection.ensureResolved(DefaultConfiguration.java:1780)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationArtifactCollection.getArtifacts(DefaultConfiguration.java:1752)
    at org.gradle.composite.internal.CompositeBuildClassPathInitializer.execute(CompositeBuildClassPathInitializer.java:45)
    at org.gradle.composite.internal.CompositeBuildClassPathInitializer.execute(CompositeBuildClassPathInitializer.java:32)
    at org.gradle.api.internal.initialization.DefaultScriptClassPathResolver.resolveClassPath(DefaultScriptClassPathResolver.java:37)
    at org.gradle.api.internal.initialization.DefaultScriptHandler.getScriptClassPath(DefaultScriptHandler.java:87)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.defineScriptHandlerClassScope(DefaultPluginRequestApplicator.java:210)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:143)
    at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:216)
    at org.gradle.configuration.BuildOperationScriptPlugin$1$1.run(BuildOperationScriptPlugin.java:69)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:66)
    at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:63)
    at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:49)
    at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:63)
    at org.gradle.configuration.project.BuildScriptProcessor$1.run(BuildScriptProcessor.java:45)
    at org.gradle.internal.Factories$1.create(Factories.java:26)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:212)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:193)
    at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:42)
    at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
    at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)
    at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject$1.run(LifecycleProjectEvaluator.java:107)
    ... 107 more
    Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.7.2.
    Required by:
    project : > org.jetbrains.intellij:org.jetbrains.intellij.gradle.plugin:0.7.2
    Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could not resolve org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.7.2.
    Caused by: org.gradle.api.resources.ResourceException: Could not get resource 'https://plugins.gradle.org/m2/org/jetbrains/intellij/plugins/gradle-intellij-plugin/0.7.2/gradle-intellij-plugin-0.7.2.module'.
    at org.gradle.internal.resource.ResourceExceptions.failure(ResourceExceptions.java:74)
    at org.gradle.internal.resource.ResourceExceptions.getFailed(ResourceExceptions.java:57)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor.copyToCache(DefaultCacheAwareExternalResourceAccessor.java:211)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor.access$300(DefaultCacheAwareExternalResourceAccessor.java:56)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor$1.get(DefaultCacheAwareExternalResourceAccessor.java:93)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor$1.get(DefaultCacheAwareExternalResourceAccessor.java:85)
    at org.gradle.cache.internal.ProducerGuard$AdaptiveProducerGuard.guardByKey(ProducerGuard.java:97)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor.getResource(DefaultCacheAwareExternalResourceAccessor.java:85)
    at org.gradle.api.internal.artifacts.repositories.resolver.DefaultExternalResourceArtifactResolver.downloadByCoords(DefaultExternalResourceArtifactResolver.java:139)
    at org.gradle.api.internal.artifacts.repositories.resolver.DefaultExternalResourceArtifactResolver.downloadStaticResource(DefaultExternalResourceArtifactResolver.java:94)
    at org.gradle.api.internal.artifacts.repositories.resolver.DefaultExternalResourceArtifactResolver.resolveArtifact(DefaultExternalResourceArtifactResolver.java:62)
    at org.gradle.api.internal.artifacts.repositories.metadata.DefaultGradleModuleMetadataSource.create(DefaultGradleModuleMetadataSource.java:70)
    at org.gradle.api.internal.artifacts.repositories.DefaultMavenArtifactRepository$MavenSnapshotDecoratingSource.create(DefaultMavenArtifactRepository.java:439)
    at org.gradle.api.internal.artifacts.repositories.metadata.RedirectingGradleMetadataModuleMetadataSource.create(RedirectingGradleMetadataModuleMetadataSource.java:53)
    at org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver.resolveStaticDependency(ExternalResourceResolver.java:252)
    at org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver.doResolveComponentMetaData(MavenResolver.java:130)
    at org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver$RemoteRepositoryAccess.resolveComponentMetaData(ExternalResourceResolver.java:479)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.CachingModuleComponentRepository$ResolveAndCacheRepositoryAccess.resolveComponentMetaData(CachingModuleComponentRepository.java:379)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.lambda$resolveComponentMetaData$5(ErrorHandlingModuleComponentRepository.java:154)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.lambda$tryResolveAndMaybeBlacklist$18(ErrorHandlingModuleComponentRepository.java:223)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.tryResolveAndMaybeBlacklist(ErrorHandlingModuleComponentRepository.java:237)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.tryResolveAndMaybeBlacklist(ErrorHandlingModuleComponentRepository.java:222)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.performOperationWithRetries(ErrorHandlingModuleComponentRepository.java:215)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ErrorHandlingModuleComponentRepository$ErrorHandlingModuleComponentRepositoryAccess.resolveComponentMetaData(ErrorHandlingModuleComponentRepository.java:153)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ComponentMetaDataResolveState.process(ComponentMetaDataResolveState.java:69)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.ComponentMetaDataResolveState.resolve(ComponentMetaDataResolveState.java:61)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.findBestMatch(RepositoryChainComponentMetaDataResolver.java:139)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.findBestMatch(RepositoryChainComponentMetaDataResolver.java:120)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.resolveModule(RepositoryChainComponentMetaDataResolver.java:93)
    at org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainComponentMetaDataResolver.resolve(RepositoryChainComponentMetaDataResolver.java:64)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.ComponentResolversChain$ComponentMetaDataResolverChain.resolve(ComponentResolversChain.java:95)
    at org.gradle.api.internal.artifacts.ivyservice.clientmodule.ClientModuleResolver.resolve(ClientModuleResolver.java:65)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.ComponentState.resolve(ComponentState.java:195)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.ComponentState.getMetadata(ComponentState.java:142)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.calculateTargetConfigurations(EdgeState.java:209)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.attachToTargetConfigurations(EdgeState.java:153)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.attachToTargetRevisionsSerially(DependencyGraphBuilder.java:368)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolveEdges(DependencyGraphBuilder.java:250)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.traverseGraph(DependencyGraphBuilder.java:187)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder.resolve(DependencyGraphBuilder.java:146)
    at org.gradle.api.internal.artifacts.ivyservice.resolveengine.DefaultArtifactDependencyResolver.resolve(DefaultArtifactDependencyResolver.java:127)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultConfigurationResolver.resolveGraph(DefaultConfigurationResolver.java:179)
    at org.gradle.api.internal.artifacts.ivyservice.ShortCircuitEmptyConfigurationResolver.resolveGraph(ShortCircuitEmptyConfigurationResolver.java:86)
    at org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingConfigurationResolver.resolveGraph(ErrorHandlingConfigurationResolver.java:74)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$6.run(DefaultConfiguration.java:632)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveGraphIfRequired(DefaultConfiguration.java:623)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$500(DefaultConfiguration.java:140)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$5.run(DefaultConfiguration.java:603)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$SafeExclusiveLockImpl.withLock(DefaultProjectStateRegistry.java:256)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveExclusively(DefaultConfiguration.java:599)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.resolveToStateOrLater(DefaultConfiguration.java:588)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$2400(DefaultConfiguration.java:140)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getSelectedArtifacts(DefaultConfiguration.java:1276)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.access$3700(DefaultConfiguration.java:1193)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationArtifactCollection.ensureResolved(DefaultConfiguration.java:1774)
    at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationArtifactCollection.getArtifacts(DefaultConfiguration.java:1752)
    at org.gradle.composite.internal.CompositeBuildClassPathInitializer.execute(CompositeBuildClassPathInitializer.java:45)
    at org.gradle.composite.internal.CompositeBuildClassPathInitializer.execute(CompositeBuildClassPathInitializer.java:32)
    at org.gradle.api.internal.initialization.DefaultScriptClassPathResolver.resolveClassPath(DefaultScriptClassPathResolver.java:37)
    at org.gradle.api.internal.initialization.DefaultScriptHandler.getScriptClassPath(DefaultScriptHandler.java:87)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.defineScriptHandlerClassScope(DefaultPluginRequestApplicator.java:210)
    at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:143)
    at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:216)
    at org.gradle.configuration.BuildOperationScriptPlugin$1$1.run(BuildOperationScriptPlugin.java:69)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:66)
    at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:63)
    at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:49)
    at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:63)
    at org.gradle.configuration.project.BuildScriptProcessor$1.run(BuildScriptProcessor.java:45)
    at org.gradle.internal.Factories$1.create(Factories.java:26)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:212)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:193)
    at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:42)
    at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
    at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)
    at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject$1.run(LifecycleProjectEvaluator.java:107)
    at org.gradle.internal.Factories$1.create(Factories.java:26)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
    at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withProjectLock(DefaultProjectStateRegistry.java:238)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:232)
    at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:193)
    at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:96)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68)
    at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:699)
    at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:142)
    at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:36)
    at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
    at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:61)
    at org.gradle.configuration.BuildOperatingFiringProjectsPreparer$ConfigureBuild.run(BuildOperatingFiringProjectsPreparer.java:52)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
    at org.gradle.configuration.BuildOperatingFiringProjectsPreparer.prepareProjects(BuildOperatingFiringProjectsPreparer.java:40)
    at org.gradle.initialization.DefaultGradleLauncher.prepareProjects(DefaultGradleLauncher.java:207)
    at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:145)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:130)
    at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:110)
    at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:60)
    at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:57)
    at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:85)
    at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:78)
    at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
    at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
    at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:78)
    at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:57)
    at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:60)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
    at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
    at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
    at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
    at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:80)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
    at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
    at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
    at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
    at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
    at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:60)
    at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:38)
    at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
    at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
    at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
    at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
    at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
    at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
    at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
    at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
    at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
    at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
    at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
    at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:27)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: org.gradle.internal.resource.transport.http.HttpRequestException: Could not GET 'https://jcenter.bintray.com/org/jetbrains/intellij/plugins/gradle-intellij-plugin/0.7.2/gradle-intellij-plugin-0.7.2.module'.
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performRequest(HttpClientHelper.java:99)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performRawGet(HttpClientHelper.java:84)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performGet(HttpClientHelper.java:88)
    at org.gradle.internal.resource.transport.http.HttpResourceAccessor.openResource(HttpResourceAccessor.java:43)
    at org.gradle.internal.resource.transport.http.HttpResourceAccessor.openResource(HttpResourceAccessor.java:28)
    at org.gradle.internal.resource.transfer.DefaultExternalResourceConnector.openResource(DefaultExternalResourceConnector.java:56)
    at org.gradle.internal.resource.transfer.ProgressLoggingExternalResourceAccessor.openResource(ProgressLoggingExternalResourceAccessor.java:38)
    at org.gradle.internal.resource.transfer.AccessorBackedExternalResource.withContentIfPresent(AccessorBackedExternalResource.java:130)
    at org.gradle.internal.resource.BuildOperationFiringExternalResourceDecorator$11.call(BuildOperationFiringExternalResourceDecorator.java:237)
    at org.gradle.internal.resource.BuildOperationFiringExternalResourceDecorator$11.call(BuildOperationFiringExternalResourceDecorator.java:229)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
    at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
    at org.gradle.internal.resource.BuildOperationFiringExternalResourceDecorator.withContentIfPresent(BuildOperationFiringExternalResourceDecorator.java:229)
    at org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor.copyToCache(DefaultCacheAwareExternalResourceAccessor.java:209)
    ... 194 more
    Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:374)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performHttpRequest(HttpClientHelper.java:141)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performHttpRequest(HttpClientHelper.java:117)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.executeGetOrHead(HttpClientHelper.java:106)
    at org.gradle.internal.resource.transport.http.HttpClientHelper.performRequest(HttpClientHelper.java:97)
    ... 212 more
    Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    ... 227 more
    Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    ... 227 more

关于客户端提示代码bug和无效的代码片段

private static void atUserAndCommandTips(KeyEvent e) {
       
        boolean isAt = false;
        // 数据列表
        java.util.List<String> dataList = null;
        // 文本内容
        String content = contentArea.getText();
        // 光标位置
        int caretPosition = contentArea.getCaretPosition();
        int atIndex = -1;
        // 命令前缀
        String commandPrefix = Command.COMMAND_PREFIX;
        // 以命令前缀开头
        if (content.startsWith(commandPrefix)) {
            // 渲染命令map
            Map<String, String> commandMap = new LinkedHashMap<>();
            for (Command command : Command.values()) {
                commandMap.put(command.getCommand(), command.getCommand() + " (" + command.getDesc() + ")");
            }

            String command = content;
            if (StrUtil.isBlank(command)) {
                dataList = new ArrayList<>(commandMap.values());
            } else {
                // 匹配列表并转给赋值给dataList
                final java.util.List<String> matchList = new ArrayList<>();
                commandMap.forEach((k, v) -> {
                    if (k.toLowerCase().contains(command.toLowerCase()) || command.startsWith(k)) {
                        matchList.add(v);
                    }
                });
                dataList = matchList;
            }
        } else {
            // 当用户在线时,且不以命令前缀开头时
            if (DataCache.isOnline) {
                // 是否为@
                isAt = true;
                // 获取内容
                String atContent = content.substring(0, caretPosition);
                // 最后出现@的下标,防止可能有多个@
                atIndex = atContent.lastIndexOf("@");

                // 当存在@时
                if (atIndex > -1) {

                    // 获取在线用户列表
                    java.util.List<User> onlineUserList = new ArrayList<>(DataCache.userMap.values());

                    // 以角色来对用户排序
                    onlineUserList.sort((u1, u2) -> {
                        // o1,o2枚举中的顺序数
                        int o1 = u1.getRole().ordinal();
                        int o2 = u2.getRole().ordinal();
                        if (o1 < o2) {
                            return -1;
                        }
                        if (o1 == o2) {
                            return 0;
                        }
                        return 1;
                    });

                    // 所有在线用户列表
                    List<String> allUserList = new ArrayList<>();
                    onlineUserList.forEach(user -> allUserList.add(user.getUsername()));

                    if (atIndex + 1 == caretPosition) {
                        dataList = allUserList;
                    }

                    //
                    String name = content.substring(atIndex + 1, caretPosition);
                    if (StrUtil.isNotBlank(name)) {
                        dataList = new ArrayList<>();
                        for (String user : allUserList) {
                            if (user.toLowerCase().contains(name.toLowerCase())) {
                                dataList.add(user);
                            }
                        }
                    }
                }
            }
        }

        leftTopPanel.setVisible(false);
        leftTopPanel.removeAll();

        // 匹配的数据列表不为空
        if (CollectionUtil.isNotEmpty(dataList)) {
            boolean copyIsAt = isAt;
            int copyAtIndex = atIndex;

            Runnable runnable = () -> {
                if (jbList == null) {
                    return;
                }

                Object selectedValue = jbList.getSelectedValue();
                if (selectedValue == null) {
                    return;
                }

                String value = selectedValue.toString();
                if (copyIsAt) {
                    contentArea.replaceRange(value + " ", copyAtIndex + 1, caretPosition);
                } else {
                    contentArea.setText(value.substring(0, value.indexOf(" ")));
                }

                requestFocus();
                leftTopPanel.setVisible(false);
                leftTopPanel.removeAll();
            };

            jbList = new JBList();
            jbList.setListData(dataList.toArray());
            jbList.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if (KeyEvent.VK_ENTER == e.getKeyCode()) {
                        runnable.run();
                    }
                }
            });

            jbList.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        runnable.run();
                    }
                }
            });

            JBScrollPane scrollPane = new JBScrollPane(jbList);
            scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

            leftTopPanel.setMinimumSize(new Dimension(0, 100));
            leftTopPanel.add(scrollPane);
            leftTopPanel.setVisible(true);

            if (e.getKeyCode() == KeyEvent.VK_TAB) {
                String value = dataList.get(0);
                if (copyIsAt) {
                    contentArea.replaceRange(value + " ", copyAtIndex + 1, caretPosition);
                } else {
                    contentArea.replaceRange(value.substring(0, value.indexOf(" ")), 0, caretPosition);
                }
            }
        }

        leftTopPanel.updateUI();
    }

无效的代码

关于这段代码,在以下部分存在问题:

  ...
   if (content.startsWith(commandPrefix)) {
            // 渲染命令map
            Map<String, String> commandMap = new LinkedHashMap<>();
            for (Command command : Command.values()) {
                commandMap.put(command.getCommand(), command.getCommand() + " (" + command.getDesc() + ")");
            }

            String command = content;
            if (StrUtil.isBlank(command)) {
                dataList = new ArrayList<>(commandMap.values());
            } else {
                // 匹配列表并转给赋值给dataList
                final java.util.List<String> matchList = new ArrayList<>();
                commandMap.forEach((k, v) -> {
                    if (k.toLowerCase().contains(command.toLowerCase()) || command.startsWith(k)) {
                        matchList.add(v);
                    }
                });
                dataList = matchList;
            }
  ... 

在这里,先判断命令是以#开头,下面又判断他为空时,显示全部命令,很显然,下面这样代码永远不可能触发,即

 if (StrUtil.isBlank(command)) {
                dataList = new ArrayList<>(commandMap.values());
            }

错误的提示

atIndex = atContent.lastIndexOf("@");

从这段代码可以看出, atIndex是最后的@下标

if (atIndex + 1 == caretPosition) {
                        dataList = allUserList;
                    }

在这段代码中,主要的作用是当用户输入@时,会弹出所有用户的列表提示框,这里有一个致命的问题,即当用户的用户名存在多个@,假设现在存在用户pi@piro、pipi@ro、pipiro...时,当用户输入“@pipi@”,这里atIndex等于5,光标下标为6

atIndex + 1 == caretPosition

等式成立,提示会显示全部用户,正确应该显示pipi@ro

当用户输入@pipi@r时,

 String name = content.substring(atIndex + 1, caretPosition);
                    if (StrUtil.isNotBlank(name)) {
                        dataList = new ArrayList<>();
                        for (String user : allUserList) {
                            if (user.toLowerCase().contains(name.toLowerCase())) {
                                dataList.add(user);
                            }
                        }
                    }

这里又会出现类似的问题,匹配包含r的用户名,实际应该是包含“pipi@r”的用户名

消息解析优化

当前版本的消息结构为: 消息大小+消息内容。
在极端环境下粘包/丢包的话,消息解析有bug.
建议优化结构为: 起始标记+消息大小+消息内容 +结束标记

加个改字体颜色的功能吧,太亮了,惹眼

建议加个修改字体颜色的功能,在settings里,如果做起来不方便,加个 #setFontColor [Hex RGB value] 类似的命令也行啊。 字体颜色太亮, 看一眼就发现了,需要给字体穿个吉利服。可以的话,背景颜色也弄个调节的。谢谢!

安全问题

毕竟需要部署在外网服务器上。而且聊天这个东西容易有法律风险。
建议增加一个简单的管理员对用户的控制功能。
如:账号密码由管理员生成然后给到朋友用。

查询天气时获取城市时关于匹配规则的若干疑问?

WeatherActionHandler#

@Override
    public void handle(ChannelHandlerContext ctx, WeatherDTO body) {
        User user = ChannelAction.getUser(ctx);
        if (user == null) {
            return;
        }

        // 构建天气服务,单例
        WeatherService weatherService = Singleton.get(HeFengWeatherServiceImpl.class);
        // 构建城市服务,单例
        CityService cityService = Singleton.get(HeFengCityServiceImpl.class);

        // 地区ID 或 经度纬度坐标
        final String location = body.getLocation();
        // 天气类型
        final WeatherType type = body.getType();

        // 获取相关城市
        CityInfo cityInfo = cityService.getOne(location);
        List<FutureWeather> futureWeatherList = null;
        CurrentWeather weatherNow = null;

        try {
            if (WeatherType.WEATHER_3D == type) {
                // 未来3天
                futureWeatherList = weatherService.getWeather3d(cityInfo.getLocationId());
            } else if (WeatherType.WEATHER_7D == type) {
                // 未来7天
                futureWeatherList = weatherService.getWeather7d(cityInfo.getLocationId());
            } else {
                // 当前
                weatherNow = weatherService.getWeatherNow(cityInfo.getLocationId());
            }
        } catch (Exception e) {
            log.error("出现异常:", e);
            user.send(ResponseBuilder.build(null, "天气查询异常,请联系管理员!", MessageType.SYSTEM));
            return;
        }

        ConsoleTable consoleTable = new ConsoleTable();
        consoleTable.setSBCMode(Boolean.FALSE);
        if (null != weatherNow) {
            consoleTable.addHeader("日期", "天气", "当前温度", "体感温度");
            consoleTable.addBody(DateUtil.today(), weatherNow.getText(), weatherNow.getTemp() + "℃", weatherNow.getFeelsLike() + "℃");
        }

        if (CollUtil.isNotEmpty(futureWeatherList)) {
            consoleTable.addHeader("日期", "天气", "温度");
            futureWeatherList.forEach(weather -> {
                String textWeather = weather.getTextDay() + "转" + weather.getTextNight();
                if (StrUtil.equals(weather.getTextDay(), weather.getTextNight())) {
                    textWeather = weather.getTextDay();
                }
                consoleTable.addBody(weather.getFxDate(), textWeather,
                        weather.getTempMin() + "℃ ~ " + weather.getTempMax() + "℃");
            });
        }

        final String msg = StrUtil.CRLF + cityInfo.getLocationName() + " 天气预报" + StrUtil.CRLF + consoleTable;
        user.send(ResponseBuilder.build(null, msg, MessageType.SYSTEM));
    }

HeFengCityServiceImpl#

    @Override
    public List<CityInfo> getList(String keyword) {
        // 从市/区县、省、市/自治州匹配关键字
        return CITY_INFO_LIST.parallelStream().filter(
                cityInfo -> StrUtil.contains(cityInfo.getLocationName(), keyword) ||
                        StrUtil.contains(cityInfo.getAdmName1(), keyword) ||
                        StrUtil.contains(cityInfo.getAdmName2(), keyword)
        ).collect(Collectors.toList());
    }

    @Override
    public CityInfo getOne(String keyword) {
        // 从市/区县、省、市/自治州匹配关键字,取列表第一个
        List<CityInfo> list = getList(keyword);
        if (CollUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

在HeFengCityServiceImpl#getOne方法中,获取单个城市信息时,查询是模糊匹配的。
1.匹配查询条件的结果是否是随机的?
2.是否需要按照相关性来排序,然后最相关性最高的城市?
3.如果不按照相关性,是否需要按照直辖,地级,省,市,镇,村等级别来排序?

现在问题是,当我输入"#weather 西"时,居然返回是是北京市西城区,陕西省省会城市-西安市居然还没一个区的权重大.
看源码出现这个结果是China-City-List-latest.json文件中,西城在文档最前面,但我感觉这个结果应该是有问题的,有点困惑。望采纳

获取mac

cn.xeblog.plugin.action.handler.command.LoginCommandHandler#getMac

建议把 if 换成while
if (networkInterfaces.hasMoreElements()) {...} => while(networkInterfaces.hasMoreElements()) {...}

多个网卡第一个为本地的时候,用if获取不到
image

换成while 获取到第一个mac就返回了,刚刚好
image

idea2023.1阅读-困难 报错

idea2023.1阅读-困难 报错
java.lang.NoSuchMethodError: 'void com.intellij.openapi.wm.impl.status.IdeStatusBarImpl.addWidgetToLeft(com.intellij.openapi.wm.StatusBarWidget, com.intellij.openapi.Disposable)' at cn.xeblog.plugin.tools.read.ui.HardReadWidget.register(HardReadWidget.java:43) at cn.xeblog.plugin.tools.read.page.ReadPage.setText(ReadPage.java:348) at cn.xeblog.plugin.tools.read.page.ReadPage.setText(ReadPage.java:342) at cn.xeblog.plugin.tools.read.page.ReadPage.lambda$getModelButton$5(ReadPage.java:231) at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972) at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313) at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405) at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262) at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279) at java.desktop/java.awt.Component.processMouseEvent(Component.java:6656) at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3385) at java.desktop/java.awt.Component.processEvent(Component.java:6421) at java.desktop/java.awt.Container.processEvent(Container.java:2266) at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5026) at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854) at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948) at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575) at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516) at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310) at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2804) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4854) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:790) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:731) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:763) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:761) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:760) at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:666) at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.kt:614) at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:569) at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:68) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:349) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:348) at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:348) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:343) at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:994) at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113) at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:994) at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$4(IdeEventQueue.kt:343) at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:831) at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:385) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)

关于用户id唯一性bug

服务端生成用户id是通过ChannelAction.getId(ctx),而此方法使用的是channel.id().asShortText()。
netty的官方文档表明asShortText()是简短但全局非唯一的字符串。这与用户id唯一性冲突
可能会在缓存用户信息时key值冲突,将会替换旧的用户缓存信息

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.