Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f672f4550e | ||
|
|
04c89d1fc1 | ||
|
|
97540bdd1b | ||
|
|
8514d808b3 | ||
|
|
e8e3d91dbc | ||
|
|
b64316c67d | ||
|
|
650ffa14e2 | ||
|
|
9fa33159c8 | ||
|
|
35794a777b | ||
|
|
bf60ed2d7d | ||
|
|
0d09aad24f | ||
|
|
8d31e031bc | ||
|
|
9af2bbf3d0 | ||
|
|
d391ba386c | ||
|
|
b2ef3152db | ||
|
|
05fe5bd766 | ||
|
|
48c9b10365 |
@@ -19,6 +19,7 @@
|
||||
* 拥有应用开放平台,可以开发和创建自建应用,扩展您的工作台。
|
||||
* API丰富,方便与其它服务系统的对接。
|
||||
* 拥有机器人和频道功能。
|
||||
* 代码开源率高,二次开发简单。可以先试用3到6个月,二开搞定后再购买。
|
||||
|
||||
## 野火开源项目
|
||||
主要包括以下项目:
|
||||
|
||||
@@ -304,6 +304,10 @@ push.ios.server.address http://localhost:8085/ios/push
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3
|
||||
|
||||
##敏感消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.sensitive.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.mentionmsg.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
+6
-1
@@ -5,7 +5,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.92</version>
|
||||
<version>0.94</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>moquette-broker</artifactId>
|
||||
@@ -234,6 +234,11 @@
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
<version>2.4.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ package cn.wildfirechat.push;
|
||||
import cn.wildfirechat.common.IMExceptionEvent;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.moquette.persistence.MemorySessionStore;
|
||||
import io.moquette.server.config.IConfig;
|
||||
import io.moquette.spi.ISessionsStore;
|
||||
@@ -29,7 +30,7 @@ import static win.liyufan.im.HttpUtils.HttpPostType.POST_TYPE_Push;
|
||||
|
||||
public class PushServer {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PushServer.class);
|
||||
|
||||
protected static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
public interface PushMessageType {
|
||||
int PUSH_MESSAGE_TYPE_NORMAL = 0;
|
||||
int PUSH_MESSAGE_TYPE_VOIP_INVITE = 1;
|
||||
@@ -100,7 +101,7 @@ public class PushServer {
|
||||
url = iOSPushServerUrl;
|
||||
pushMessage.voipDeviceToken = session.getVoipDeviceToken();
|
||||
}
|
||||
HttpUtils.httpJsonPost(url, new Gson().toJson(pushMessage, pushMessage.getClass()), POST_TYPE_Push);
|
||||
HttpUtils.httpJsonPost(url, gson.toJson(pushMessage, pushMessage.getClass()), POST_TYPE_Push);
|
||||
} else {
|
||||
LOG.info("Not mobile platform {}", session.getPlatform());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.xiaoleilu.loServer.action;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.annotation.RequireAuthentication;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
@@ -39,7 +40,7 @@ import static io.moquette.BrokerConstants.*;
|
||||
abstract public class Action {
|
||||
public static IMessagesStore messagesStore = null;
|
||||
public static ISessionsStore sessionsStore = null;
|
||||
|
||||
protected static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
public ChannelHandlerContext ctx;
|
||||
|
||||
protected static RateLimiter adminLimiter = null;
|
||||
@@ -129,7 +130,7 @@ abstract public class Action {
|
||||
}
|
||||
|
||||
RestResult result = RestResult.resultOf(errorCode, errorCode.getMsg(), RestResult.resultOf(errorCode));
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
response.send();
|
||||
}
|
||||
|
||||
@@ -145,7 +146,7 @@ abstract public class Action {
|
||||
FullHttpRequest fullHttpRequest = (FullHttpRequest) request;
|
||||
byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content());
|
||||
String content = new String(bytes, StandardCharsets.UTF_8);//contribute by JiaRG from github
|
||||
Gson gson = new Gson();
|
||||
|
||||
T t = gson.fromJson(content, cls);
|
||||
return t;
|
||||
}
|
||||
@@ -154,6 +155,6 @@ abstract public class Action {
|
||||
|
||||
protected void setResponseContent(RestResult result, Response response) {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class VersionAction extends Action {
|
||||
|
||||
try {
|
||||
|
||||
response.setContent(Utility.formatJson(new Gson().toJson(GitRepositoryState.getGitRepositoryState())));
|
||||
response.setContent(Utility.formatJson(gson.toJson(GitRepositoryState.getGitRepositoryState())));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
response.setContent("{\"version\":\"unknown\"}");
|
||||
|
||||
@@ -99,7 +99,7 @@ abstract public class AdminAction extends Action {
|
||||
}
|
||||
|
||||
RestResult result = RestResult.resultOf(errorCode, errorCode.getMsg(), data);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
response.send();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class ApplicationGetUserInfoAction extends AdminAction {
|
||||
}
|
||||
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class BlockUserAction extends AdminAction {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
RestResult result;
|
||||
result = RestResult.resultOf(errorCode);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
|
||||
if (inputUserBlock.getStatus() == 2) {
|
||||
sendApiMessage(null, null, ServerAPIHelper.KICKOFF_USER_REQUEST, inputUserBlock.getUserId().getBytes(), null);
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package com.xiaoleilu.loServer.action.admin;
|
||||
|
||||
import cn.wildfirechat.common.APIPath;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.pojos.InputChannelSubscribe;
|
||||
import cn.wildfirechat.pojos.InputCreateChannel;
|
||||
import cn.wildfirechat.pojos.InputSubscribeChannel;
|
||||
import cn.wildfirechat.pojos.OutputCreateChannel;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.google.gson.Gson;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.action.channel.ChannelAction;
|
||||
import com.xiaoleilu.loServer.annotation.HttpMethod;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
@Route(APIPath.Subscribe_Channel)
|
||||
@HttpMethod("POST")
|
||||
public class ChannelSubscriberAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
InputSubscribeChannel inputSubscribeChannel = getRequestBody(request.getNettyRequest(), InputSubscribeChannel.class);
|
||||
if (inputSubscribeChannel != null
|
||||
&& !io.netty.util.internal.StringUtil.isNullOrEmpty(inputSubscribeChannel.getChannelId())
|
||||
&& !io.netty.util.internal.StringUtil.isNullOrEmpty(inputSubscribeChannel.getUserId())) {
|
||||
|
||||
WFCMessage.ListenChannel.Builder builder = WFCMessage.ListenChannel.newBuilder().setChannelId(inputSubscribeChannel.getChannelId()).setListen(inputSubscribeChannel.getSubscribe());
|
||||
sendApiMessage(response, inputSubscribeChannel.getUserId(), IMTopic.ChannelListenTopic, builder.build().toByteArray(), result -> {
|
||||
ErrorCode errorCode = ErrorCode.fromCode(result[0]);
|
||||
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
return new Result(ErrorCode.ERROR_CODE_SUCCESS);
|
||||
} else {
|
||||
return new Result(errorCode);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public class CheckUserOnlineAction extends AdminAction {
|
||||
InputGetUserInfo inputUserId = getRequestBody(request.getNettyRequest(), InputGetUserInfo.class);
|
||||
if (inputUserId == null || !StringUtil.isNullOrEmpty(inputUserId.getUserId())) {
|
||||
sendApiMessage(response, inputUserId.getUserId(), ServerAPIHelper.CHECK_USER_ONLINE_REQUEST, inputUserId.getUserId().getBytes(), res -> {
|
||||
OutputCheckUserOnline out = new Gson().fromJson(new String(res), OutputCheckUserOnline.class);
|
||||
OutputCheckUserOnline out = gson.fromJson(new String(res), OutputCheckUserOnline.class);
|
||||
return new Result(ErrorCode.ERROR_CODE_SUCCESS, out);
|
||||
});
|
||||
return false;
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package com.xiaoleilu.loServer.action.admin;
|
||||
|
||||
import cn.wildfirechat.common.APIPath;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import cn.wildfirechat.pojos.InputChannelId;
|
||||
import cn.wildfirechat.pojos.InputSubscribeChannel;
|
||||
import cn.wildfirechat.pojos.OutputBooleanValue;
|
||||
import cn.wildfirechat.pojos.OutputGetChannelInfo;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.xiaoleilu.loServer.RestResult;
|
||||
import com.xiaoleilu.loServer.annotation.HttpMethod;
|
||||
import com.xiaoleilu.loServer.annotation.Route;
|
||||
import com.xiaoleilu.loServer.handler.Request;
|
||||
import com.xiaoleilu.loServer.handler.Response;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
@Route(APIPath.Check_User_Subscribe_Channel)
|
||||
@HttpMethod("POST")
|
||||
public class CheckUserSubscribeChannelAction extends AdminAction {
|
||||
|
||||
@Override
|
||||
public boolean isTransactionAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean action(Request request, Response response) {
|
||||
if (request.getNettyRequest() instanceof FullHttpRequest) {
|
||||
InputSubscribeChannel inputSubscribeChannel = getRequestBody(request.getNettyRequest(), InputSubscribeChannel.class);
|
||||
if (inputSubscribeChannel != null
|
||||
&& !StringUtil.isNullOrEmpty(inputSubscribeChannel.getChannelId())
|
||||
&& !StringUtil.isNullOrEmpty(inputSubscribeChannel.getUserId())) {
|
||||
boolean isInChannel = messagesStore.checkUserInChannel(inputSubscribeChannel.getUserId(), inputSubscribeChannel.getChannelId());
|
||||
OutputBooleanValue outputBooleanValue = new OutputBooleanValue();
|
||||
outputBooleanValue.value = isInChannel;
|
||||
setResponseContent(RestResult.ok(outputBooleanValue), response);
|
||||
} else {
|
||||
setResponseContent(RestResult.resultOf(ErrorCode.INVALID_PARAMETER), response);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class CreateChatroomAction extends AdminAction {
|
||||
FullHttpRequest fullHttpRequest = (FullHttpRequest)request.getNettyRequest();
|
||||
byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content());
|
||||
String content = new String(bytes);
|
||||
Gson gson = new Gson();
|
||||
|
||||
InputCreateChatroom inputCreateChatroom = gson.fromJson(content, InputCreateChatroom.class);
|
||||
if (inputCreateChatroom != null
|
||||
&& !StringUtil.isNullOrEmpty(inputCreateChatroom.getTitle())) {
|
||||
|
||||
@@ -67,7 +67,7 @@ public class CreateRobotAction extends AdminAction {
|
||||
Utility.printExecption(LOG, e, IMExceptionEvent.EventType.ADMIN_API_Exception);
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
RestResult result = RestResult.resultOf(ErrorCode.ERROR_CODE_SERVER_ERROR, e.getMessage());
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class DestoryChatroomAction extends AdminAction {
|
||||
FullHttpRequest fullHttpRequest = (FullHttpRequest)request.getNettyRequest();
|
||||
byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content());
|
||||
String content = new String(bytes);
|
||||
Gson gson = new Gson();
|
||||
|
||||
InputDestoryChatroom inputDestoryChatroom = gson.fromJson(content, InputDestoryChatroom.class);
|
||||
if (inputDestoryChatroom != null
|
||||
&& !StringUtil.isNullOrEmpty(inputDestoryChatroom.getChatroomId())) {
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class ModifyGroupMemberExtraAction extends AdminAction {
|
||||
} else {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class ApplicationGetUserInfoAction extends ChannelAction {
|
||||
}
|
||||
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ abstract public class ChannelAction extends Action {
|
||||
}
|
||||
|
||||
RestResult result = RestResult.resultOf(errorCode, errorCode.getMsg(), data);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
response.send();
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ abstract public class ChannelAction extends Action {
|
||||
FullHttpRequest fullHttpRequest = (FullHttpRequest) request;
|
||||
byte[] bytes = Utils.readBytesAndRewind(fullHttpRequest.content());
|
||||
String content = new String(bytes, StandardCharsets.UTF_8);
|
||||
Gson gson = new Gson();
|
||||
|
||||
T t = gson.fromJson(content, cls);
|
||||
return t;
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class SubscriberChannelAction extends ChannelAction {
|
||||
if(input.getSubscribe() > 0 && (channelInfo.getStatus() & ProtoConstants.ChannelState.Channel_State_Mask_Active_Subscribe) == 0) {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
RestResult result = RestResult.resultOf(ErrorCode.ERROR_CODE_NOT_RIGHT);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
return true;
|
||||
}
|
||||
WFCMessage.ListenChannel listenChannel = WFCMessage.ListenChannel.newBuilder().setChannelId(channelInfo.getTargetId()).setListen(input.getSubscribe()).build();
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class ApplicationGetUserInfoAction extends RobotAction {
|
||||
}
|
||||
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class ModifyGroupMemberExtraAction extends RobotAction {
|
||||
} else {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
RestResult result = RestResult.resultOf(ErrorCode.INVALID_PARAMETER);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -102,7 +102,7 @@ abstract public class RobotAction extends Action {
|
||||
}
|
||||
|
||||
RestResult result = RestResult.resultOf(errorCode, errorCode.getMsg(), data);
|
||||
response.setContent(new Gson().toJson(result));
|
||||
response.setContent(gson.toJson(result));
|
||||
response.send();
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ abstract public class RobotAction extends Action {
|
||||
String content = null;
|
||||
try {
|
||||
content = new String(bytes, "UTF-8");
|
||||
Gson gson = new Gson();
|
||||
|
||||
T t = gson.fromJson(content, cls);
|
||||
return t;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
||||
@@ -114,6 +114,13 @@ abstract public class ActionHandler extends SimpleChannelInboundHandler<FullHttp
|
||||
handleOptions(ctx, request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("HEAD".equalsIgnoreCase(request.getMethod())) {
|
||||
response.setStatus(HttpResponseStatus.OK);
|
||||
response.send();
|
||||
return;
|
||||
}
|
||||
|
||||
Action action;
|
||||
if (isValidePath(request.getPath())) {
|
||||
action = ServerSetting.getAction(request.getPath(), request.getMethod().toUpperCase());
|
||||
|
||||
@@ -41,6 +41,7 @@ import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.codec.http.cookie.Cookie;
|
||||
import io.netty.handler.codec.http.cookie.DefaultCookie;
|
||||
import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
|
||||
import org.apache.tika.Tika;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
@@ -469,7 +470,9 @@ public class Response {
|
||||
this.setContentLength(fileLength);
|
||||
|
||||
//文件类型
|
||||
String contentType = HttpUtil.getMimeType(file.getName());
|
||||
Tika tika = new Tika();
|
||||
String contentType = tika.detect(file);
|
||||
// String contentType = HttpUtil.getMimeType(file.getName());
|
||||
if(StrUtil.isBlank(contentType)){
|
||||
//无法识别默认使用数据流
|
||||
contentType = "application/octet-stream";
|
||||
|
||||
@@ -120,6 +120,7 @@ public final class BrokerConstants {
|
||||
public static final String SENSITIVE_Remote_Fail_When_Matched = "sensitive.remote_fail_when_matched";
|
||||
|
||||
public static final String MESSAGE_Forward_Url = "message.forward.url";
|
||||
public static final String MESSAGE_Sensitive_Forward_Url = "message.sensitive.forward.url";
|
||||
public static final String MESSAGE_Forward_Types = "message.forward.types";
|
||||
public static final String MESSAGE_MentionMsg_Forward_Url = "message.mentionmsg.forward.url";
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ public class GetQiniuUploadTokenHandler extends IMHandler<Byte> {
|
||||
String token;
|
||||
|
||||
WFCMessage.GetUploadTokenResult.Builder resultBuilder = WFCMessage.GetUploadTokenResult.newBuilder();
|
||||
|
||||
if (MediaServerConfig.USER_QINIU) {
|
||||
Auth auth = Auth.create(MediaServerConfig.QINIU_ACCESS_KEY, MediaServerConfig.QINIU_SECRET_KEY);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import io.netty.util.internal.StringUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import win.liyufan.im.GsonUtil;
|
||||
import win.liyufan.im.RateLimiter;
|
||||
import win.liyufan.im.Utility;
|
||||
|
||||
@@ -39,6 +40,8 @@ import java.util.*;
|
||||
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_OVER_FREQUENCY;
|
||||
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
|
||||
import static io.moquette.BrokerConstants.CLIENT_REQUEST_RATE_LIMIT;
|
||||
import static win.liyufan.im.IMTopic.GetUserSettingTopic;
|
||||
import static win.liyufan.im.IMTopic.PullMessageTopic;
|
||||
|
||||
/**
|
||||
* 请求处理接口<br>
|
||||
@@ -139,7 +142,7 @@ abstract public class IMHandler<T> {
|
||||
// }
|
||||
|
||||
//json ?
|
||||
return (T)(new Gson().fromJson(new String(bytes), dataCls));
|
||||
return (T)(GsonUtil.gson.fromJson(new String(bytes), dataCls));
|
||||
}
|
||||
|
||||
public static void init(IMessagesStore ms, ISessionsStore ss, MessagesPublisher p, ThreadPoolExecutorWrapper businessExecutor, Server server) {
|
||||
@@ -162,10 +165,17 @@ abstract public class IMHandler<T> {
|
||||
mLimitCounter = new RateLimiter(5, clientRateLimit);
|
||||
}
|
||||
|
||||
boolean isNotLimitTopic(String topic) {
|
||||
if (PullMessageTopic.equals(topic)
|
||||
|| GetUserSettingTopic.equals(topic)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ErrorCode preAction(String clientID, String fromUser, String topic, Qos1PublishHandler.IMCallback callback, ProtoConstants.RequestSourceType requestSourceType) {
|
||||
LOG.info("imHandler fromUser={}, clientId={}, topic={}", fromUser, clientID, topic);
|
||||
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User && !mLimitCounter.isGranted(clientID + fromUser + topic)) {
|
||||
if(requestSourceType == ProtoConstants.RequestSourceType.Request_From_User && !isNotLimitTopic(topic) && !mLimitCounter.isGranted(clientID + fromUser + topic)) {
|
||||
return ErrorCode.ERROR_CODE_OVER_FREQUENCY;
|
||||
}
|
||||
return ErrorCode.ERROR_CODE_SUCCESS;
|
||||
|
||||
@@ -20,10 +20,7 @@ import io.moquette.spi.impl.Qos1PublishHandler;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import win.liyufan.im.HttpUtils;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.MessageShardingUtil;
|
||||
import win.liyufan.im.Utility;
|
||||
import win.liyufan.im.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -34,6 +31,7 @@ import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
|
||||
public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
private int mSensitiveType = 0; //命中敏感词时,0 失败,1 吞掉, 2 敏感词替换成*。
|
||||
private String mForwardUrl = null;
|
||||
private String mSensitiveMessageForwardUrl = null;
|
||||
private Set<Integer> mForwardMessageTypes = new HashSet<>();
|
||||
private String mMentionForwardUrl = null;
|
||||
private int mBlacklistStrategy = 0; //黑名单中时,0失败,1吞掉。
|
||||
@@ -56,7 +54,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mSensitiveMessageForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Sensitive_Forward_Url);
|
||||
mMentionForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_MentionMsg_Forward_Url);
|
||||
|
||||
try {
|
||||
@@ -194,6 +192,9 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
Set<String> matched = m_messagesStore.handleSensitiveWord(message.getContent().getSearchableContent());
|
||||
if (matched != null && !matched.isEmpty()) {
|
||||
m_messagesStore.storeSensitiveMessage(message);
|
||||
if (!StringUtil.isNullOrEmpty(mSensitiveMessageForwardUrl)) {
|
||||
publisher.forwardMessage(message, mSensitiveMessageForwardUrl, outputClient);
|
||||
}
|
||||
if (mSensitiveType == 0) {
|
||||
errorCode = ErrorCode.ERROR_CODE_SENSITIVE_MATCHED;
|
||||
} else if (mSensitiveType == 1) {
|
||||
@@ -215,7 +216,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
|
||||
if(StringUtil.isNullOrEmpty(content)) {
|
||||
saveAndPublish(fromUser, clientID, finalMsg, requestSourceType);
|
||||
} else {
|
||||
MessagePayload payload = new Gson().fromJson(content, MessagePayload.class);
|
||||
MessagePayload payload = GsonUtil.gson.fromJson(content, MessagePayload.class);
|
||||
if (payload != null && payload.getType() > 0) {
|
||||
WFCMessage.Message newMsg = finalMsg.toBuilder().setContent(payload.toProtoMessageContent()).build();
|
||||
saveAndPublish(fromUser, clientID, newMsg, requestSourceType);
|
||||
|
||||
@@ -1143,7 +1143,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.type = type;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mGroupInfoUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_Grout_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mGroupInfoUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Grout_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1162,7 +1162,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.value = value;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mGroupMemberUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_Grout_Member_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mGroupMemberUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Grout_Member_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1180,7 +1180,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.value = value;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mRelationUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_User_Relation_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mRelationUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_User_Relation_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1193,7 +1193,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
if (!StringUtil.isNullOrEmpty(mUserInfoUpdateCallback)) {
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mUserInfoUpdateCallback, new Gson().toJson(InputOutputUserInfo.fromPbUser(user)), HttpUtils.HttpPostType.POST_TYPE_User_Info_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mUserInfoUpdateCallback, GsonUtil.gson.toJson(InputOutputUserInfo.fromPbUser(user)), HttpUtils.HttpPostType.POST_TYPE_User_Info_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1210,7 +1210,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.type = type;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mChannelInfoUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_Channel_Info_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mChannelInfoUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Channel_Info_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1226,7 +1226,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.type = type;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mChatroomInfoUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_Chatroom_Info_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mChatroomInfoUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Chatroom_Info_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -1244,7 +1244,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
event.type = type;
|
||||
m_Server.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mChatroomMemberUpdateCallback, new Gson().toJson(event), HttpUtils.HttpPostType.POST_TYPE_Chatroom_Member_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mChatroomMemberUpdateCallback, GsonUtil.gson.toJson(event), HttpUtils.HttpPostType.POST_TYPE_Chatroom_Member_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -3889,7 +3889,7 @@ public class MemoryMessagesStore implements IMessagesStore {
|
||||
Utility.printExecption(LOG, e);
|
||||
}
|
||||
} else if(modifyType == Modify_Channel_Menu) {
|
||||
OutputGetChannelInfo.OutputMenuList outputMenuButtons = new Gson().fromJson(value, OutputGetChannelInfo.OutputMenuList.class);
|
||||
OutputGetChannelInfo.OutputMenuList outputMenuButtons = GsonUtil.gson.fromJson(value, OutputGetChannelInfo.OutputMenuList.class);
|
||||
if (!outputMenuButtons.isEmpty()) {
|
||||
for (OutputGetChannelInfo.OutputMenu outputMenuButton : outputMenuButtons) {
|
||||
newInfoBuilder.addMenu(outputMenuButton.toPbInfo());
|
||||
|
||||
@@ -35,6 +35,7 @@ import io.moquette.spi.ISessionsStore;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.mqtt.*;
|
||||
import win.liyufan.im.GsonUtil;
|
||||
import win.liyufan.im.HttpUtils;
|
||||
import win.liyufan.im.IMTopic;
|
||||
|
||||
@@ -188,7 +189,7 @@ public class MessagesPublisher {
|
||||
OutputClient finalOutputClient = outputClient;
|
||||
Server.getServer().getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(robot.getCallback(), new Gson().toJson(OutputMessageData.fromProtoMessage(finalMsg, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Robot_Message_Callback);
|
||||
HttpUtils.httpJsonPost(robot.getCallback(), GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(finalMsg, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Robot_Message_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -616,7 +617,7 @@ public class MessagesPublisher {
|
||||
OutputClient finalOutputClient = outputClient;
|
||||
Server.getServer().getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(channelInfo.getCallback() + "/message", new Gson().toJson(OutputMessageData.fromProtoMessage(message, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Channel_Message_Callback);
|
||||
HttpUtils.httpJsonPost(channelInfo.getCallback() + "/message", GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(message, finalOutputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Channel_Message_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -669,7 +670,7 @@ public class MessagesPublisher {
|
||||
public void forwardMessage(final WFCMessage.Message message, String forwardUrl, OutputClient outputClient) {
|
||||
Server.getServer().getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(forwardUrl, new Gson().toJson(OutputMessageData.fromProtoMessage(message, outputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Forward_Message_Callback);
|
||||
HttpUtils.httpJsonPost(forwardUrl, GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(message, outputClient), OutputMessageData.class), HttpUtils.HttpPostType.POST_TYPE_Forward_Message_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
@@ -679,7 +680,7 @@ public class MessagesPublisher {
|
||||
|
||||
public void forwardMessageWithCallback(final WFCMessage.Message message, String forwardUrl, HttpUtils.HttpCallback callback) {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(forwardUrl, new Gson().toJson(OutputMessageData.fromProtoMessage(message), OutputMessageData.class), new HttpUtils.HttpCallback() {
|
||||
HttpUtils.httpJsonPost(forwardUrl, GsonUtil.gson.toJson(OutputMessageData.fromProtoMessage(message), OutputMessageData.class), new HttpUtils.HttpCallback() {
|
||||
@Override
|
||||
public void onSuccess(String content) {
|
||||
Server.getServer().getImBusinessScheduler().execute(()->{
|
||||
@@ -707,7 +708,7 @@ public class MessagesPublisher {
|
||||
|
||||
Server.getServer().getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(channelInfo.getCallback() + "/subscribe", new Gson().toJson(new OutputNotifyChannelSubscribeStatus(user, channelInfo.getTargetId(), listen), OutputNotifyChannelSubscribeStatus.class), HttpUtils.HttpPostType.POST_TYPE_Channel_Subscriber_Event_Callback);
|
||||
HttpUtils.httpJsonPost(channelInfo.getCallback() + "/subscribe", GsonUtil.gson.toJson(new OutputNotifyChannelSubscribeStatus(user, channelInfo.getTargetId(), listen), OutputNotifyChannelSubscribeStatus.class), HttpUtils.HttpPostType.POST_TYPE_Channel_Subscriber_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
|
||||
@@ -43,6 +43,7 @@ import io.netty.handler.codec.mqtt.*;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import win.liyufan.im.GsonUtil;
|
||||
import win.liyufan.im.HttpUtils;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.Utility;
|
||||
@@ -264,7 +265,7 @@ public class ProtocolProcessor {
|
||||
if (!StringUtil.isNullOrEmpty(mUserOnlineStatusCallback)) {
|
||||
mServer.getCallbackScheduler().execute(() -> {
|
||||
try {
|
||||
HttpUtils.httpJsonPost(mUserOnlineStatusCallback, new Gson().toJson(new UserOnlineStatus(userId, clientId, platform, status, packageName)), HttpUtils.HttpPostType.POST_TYPE_User_Online_Event_Callback);
|
||||
HttpUtils.httpJsonPost(mUserOnlineStatusCallback, GsonUtil.gson.toJson(new UserOnlineStatus(userId, clientId, platform, status, packageName)), HttpUtils.HttpPostType.POST_TYPE_User_Online_Event_Callback);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utility.printExecption(LOG, e, EVENT_CALLBACK_Exception);
|
||||
|
||||
@@ -57,6 +57,7 @@ import io.netty.handler.codec.mqtt.MqttFixedHeader;
|
||||
import io.netty.handler.codec.mqtt.MqttMessageType;
|
||||
import io.netty.handler.codec.mqtt.MqttPublishMessage;
|
||||
import cn.wildfirechat.common.ErrorCode;
|
||||
import win.liyufan.im.GsonUtil;
|
||||
import win.liyufan.im.IMTopic;
|
||||
import win.liyufan.im.RateLimiter;
|
||||
import win.liyufan.im.Utility;
|
||||
@@ -142,7 +143,7 @@ public class Qos1PublishHandler extends QosPublishHandler {
|
||||
out.addSession(userId, session.getClientID(), session.getPlatform(), status, session.getLastActiveTime());
|
||||
}
|
||||
|
||||
callback.onRouteHandled(new Gson().toJson(out).getBytes());
|
||||
callback.onRouteHandled(GsonUtil.gson.toJson(out).getBytes());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package win.liyufan.im;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
public class GsonUtil {
|
||||
public static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class Utility {
|
||||
if(now - t >= SendExceptionDuration) {
|
||||
for (Map.Entry<String, IMExceptionEvent> entry : exceptionEventHashMap.entrySet()) {
|
||||
if(entry.getValue().count > 0) {
|
||||
String jsonStr = new Gson().toJson(entry.getValue());
|
||||
String jsonStr = GsonUtil.gson.toJson(entry.getValue());
|
||||
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(gMonitorEventAddress, jsonStr, HttpUtils.HttpPostType.POST_TYPE_Server_Exception_Callback));
|
||||
entry.getValue().count = 0;
|
||||
lastSendTime = now;
|
||||
@@ -111,7 +111,7 @@ public class Utility {
|
||||
event.msg = "监控心跳通知";
|
||||
event.call_stack = "别担心!这个是心跳消息,已经有24小时没有出现异常消息了!";
|
||||
event.count = IMExceptionEvent.EventType.HEART_BEAT;
|
||||
String jsonStr = new Gson().toJson(event);
|
||||
String jsonStr = GsonUtil.gson.toJson(event);
|
||||
Server.getServer().getCallbackScheduler().execute(() -> HttpUtils.httpJsonPost(gMonitorEventAddress, jsonStr, HttpUtils.HttpPostType.POST_TYPE_Server_Exception_Callback));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.92</version>
|
||||
<version>0.94</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public interface APIPath {
|
||||
String Msg_RecallMultiCast = "/admin/message/recall_multicast";
|
||||
String Msg_ConvRead = "/admin/message/conv_read";
|
||||
String Msg_Delivery = "/admin/message/delivery";
|
||||
String Conversation_Delete = "/admin/conversation/delete";
|
||||
|
||||
String Create_Group = "/admin/group/create";
|
||||
String Group_Dismiss = "/admin/group/del";
|
||||
@@ -79,6 +80,8 @@ public interface APIPath {
|
||||
String Create_Channel = "/admin/channel/create";
|
||||
String Destroy_Channel = "/admin/channel/destroy";
|
||||
String Get_Channel_Info = "/admin/channel/get";
|
||||
String Subscribe_Channel = "/admin/channel/subscribe";
|
||||
String Check_User_Subscribe_Channel = "/admin/channel/is_subscribed";
|
||||
String Get_System_Setting = "/admin/system/get_setting";
|
||||
String Put_System_Setting = "/admin/system/put_setting";
|
||||
|
||||
|
||||
@@ -19,4 +19,5 @@ public class IMExceptionEvent {
|
||||
public String msg;
|
||||
public String call_stack;
|
||||
public int count;
|
||||
public int node_id;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.wildfirechat.pojos;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
@@ -47,7 +48,7 @@ public class ArticleContent {
|
||||
MessagePayload payload = new MessagePayload();
|
||||
payload.setType(13);
|
||||
payload.setSearchableContent(top.title);
|
||||
payload.setBase64edData(Base64.getEncoder().encodeToString(new Gson().toJson(this).getBytes(StandardCharsets.UTF_8)));
|
||||
payload.setBase64edData(Base64.getEncoder().encodeToString(new GsonBuilder().disableHtmlEscaping().create().toJson(this).getBytes(StandardCharsets.UTF_8)));
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package cn.wildfirechat.pojos;
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import java.util.List;
|
||||
@@ -89,7 +90,7 @@ public class GroupNotificationBinaryContent {
|
||||
}
|
||||
|
||||
public WFCMessage.MessageContent getGroupNotifyContent(int groupContentType) {
|
||||
return WFCMessage.MessageContent.newBuilder().setType(groupContentType).setData(ByteString.copyFromUtf8(new Gson().toJson(this))).build();
|
||||
return WFCMessage.MessageContent.newBuilder().setType(groupContentType).setData(ByteString.copyFromUtf8(new GsonBuilder().disableHtmlEscaping().create().toJson(this))).build();
|
||||
}
|
||||
|
||||
public WFCMessage.MessageContent getAddGroupNotifyContent() {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package cn.wildfirechat.pojos;
|
||||
|
||||
public class InputSubscribeChannel {
|
||||
private String channelId;
|
||||
private String userId;
|
||||
private int subscribe; //1,订阅;0,取消订阅
|
||||
|
||||
public InputSubscribeChannel() {
|
||||
}
|
||||
|
||||
public InputSubscribeChannel(String channelId, String userId, int subscribe) {
|
||||
this.channelId = channelId;
|
||||
this.userId = userId;
|
||||
this.subscribe = subscribe;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public int getSubscribe() {
|
||||
return subscribe;
|
||||
}
|
||||
|
||||
public void setSubscribe(int subscribe) {
|
||||
this.subscribe = subscribe;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cn.wildfirechat.pojos;
|
||||
|
||||
public class InputUserConversation {
|
||||
public String userId;
|
||||
public Conversation conversation;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of the Wildfire Chat package.
|
||||
* (c) Heavyrain2012 <[email protected]>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
package cn.wildfirechat.pojos;
|
||||
|
||||
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class OutputBooleanValue {
|
||||
public boolean value;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!--<relativePath>../pom.xml</relativePath>-->
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.92</version>
|
||||
<version>0.94</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>distribution</artifactId>
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
<source>src/main/files/README.txt</source>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>src/main/files/release_note.md</source>
|
||||
</file>
|
||||
|
||||
<file>
|
||||
<source>../broker/target/moquette-broker-${project.version}.jar</source>
|
||||
<outputDirectory>lib/</outputDirectory>
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
# 升级注意事项
|
||||
1. *** 0.42 版本增加了群成员数限制,默认为2000。如果您想修改默认值,可以在升级版本之后,修改t_setting表,把默认的大小改为您期望的。另外修改t_group表,把已经存在的群组max_member_count改成您期望的,然后重启。***
|
||||
2. *** 0.46和0.47版本升级到0.48及以后版本时,可能会提示flyway migrate 38错误,请执行 [修复脚本](https://github.com/wildfirechat/server/blob/wildfirechat/flyway_repaire_migrate_38.sql) 进行修复。0.46和0.47版本之外的版本不会出现此问题。***
|
||||
3. *** 0.50版本添加了是否允许客户端发送群操作通知的配置。如果您在客户端自定义群通知,需要在服务器端配置允许,没有使用自定义群操作通知的不受影响。***
|
||||
4. *** 从0.54之前版本升级到0.54及以后版本时,会提示flyway migrate错误。因为0.54版本删除了sql脚本中默认敏感词的内容,flyway checksum失败。请执行```update flyway_schema_history set checksum = 0 where script = 'V17__add_default_sensitive_word.sql';```来修复。***
|
||||
5. *** 从0.59之前的版本升级到之后的版本执行数据库升级时间比较长,请耐心等待提示运行成功,避免中途中断。 ***
|
||||
6. *** 0.62/0.63 版本有严重的问题,请使用0.64及以后版本,或者0.61版。 ***
|
||||
7. *** 从0.68 版本起添加了pc在线是否默认手机接收推送的开关,默认为开,与以前版本作用相反,请注意兼容(可以关掉与之前保持一致或者升级客户端) ***
|
||||
8. *** 从0.78 版本起把MySQL数据库中关键字都改为大小写敏感,另外生成id的方法也做了改变,只生成小写的id,避免出现id重复的问题,建议所有客户都升级 ***
|
||||
9 *** 从0.79 版本起把log4j升级到log4j2,因为log4j已经不再维护而且还有已知的漏洞,建议所有客户都升级,升级时注意更新log4j2的配置文件 ***
|
||||
|
||||
# 更新记录
|
||||
|
||||
--------------
|
||||
Release note 0.94:
|
||||
1. Server SDK添加删除会话接口
|
||||
2. 解决内置对象存储某些类型文件返回content-type错误问题
|
||||
3. 添加server api检查是否订阅频道接口
|
||||
4. 添加超频检查忽略信令
|
||||
5. gson单例化,且关掉html转义。
|
||||
|
||||
--------------
|
||||
Release note 0.93:
|
||||
1. Server API添加订阅频道功能
|
||||
2. 短链接端口添加HEAD方法处理
|
||||
3. Server SDK的HTTP Client调整部分参数,解决出现连接错误问题
|
||||
4. 添加敏感词回调功能
|
||||
|
||||
--------------
|
||||
Release note 0.92:
|
||||
1. SDK部分POJO对象添加无参数构造函数解决某些反序列化工具失败问题。
|
||||
2. 频道只有在auto属性为1时,才会回调函数及订阅事件。
|
||||
3. 添加配置,在关闭消息漫游时,客户端首次登录同步多久时间之内的消息。
|
||||
4. 频道添加菜单属性。
|
||||
|
||||
---------------
|
||||
Release note 0.91:
|
||||
1. 创建群组时检查群组类型的有效性。
|
||||
2. 添加配置消息回调时是否带上客户端信息。
|
||||
3. 添加群组成员时,检查是否已经在群组中。
|
||||
|
||||
---------------
|
||||
Release note 0.90:
|
||||
1. mysql-connector-java版本升级到8.0.28
|
||||
2. 配置文件中去掉绑定IP的配置,防止误操作
|
||||
3. 解决客户端触发限频多调用一次callback的错误。
|
||||
|
||||
---------------
|
||||
Release note 0.89:
|
||||
1. gson依赖库升级到2.8.9
|
||||
2. log4j升级到2.17.2
|
||||
3. 解决SDK部分响应反序列化失败的问题
|
||||
4. 添加配置允许PC多端
|
||||
|
||||
---------------
|
||||
Release note 0.88:
|
||||
1. 添加部分数据库表的索引。
|
||||
2. 优化频道订阅关系的缓存处理。
|
||||
3. 添加支持开放平台的接口。
|
||||
4. 机器人和频道回调消息中添加缺失信息。
|
||||
5. 频道automic状态为1时,都不发送消息给owner。
|
||||
6. 机器人api添加获取机器人信息的接口。
|
||||
7. 解决server api撤回单聊消息时发送方无法撤回的问题
|
||||
|
||||
---------------
|
||||
Release note 0.87:
|
||||
1. 优化pc在线状态逻辑。
|
||||
2. 添加配置当删除用户时使用的用户昵称。
|
||||
3. 添加获取单条消息接口。
|
||||
|
||||
---------------
|
||||
Release note 0.86:
|
||||
1. Server SDK获取在线用户结果的变量改成公开
|
||||
|
||||
---------------
|
||||
Release note 0.85:
|
||||
1. 消息只能撤回一次,不能重复撤回。
|
||||
3. gzip压缩避免内存泄漏
|
||||
|
||||
---------------
|
||||
Release note 0.84:
|
||||
1. 定向消息,如果有多于一个收件人,只保存第一个收件人,避免定向消息被远程消息拉取下来。
|
||||
3. 内置文件存储,是否内存避免内存泄漏。
|
||||
|
||||
---------------
|
||||
Release note 0.83:
|
||||
1. 解决多端登陆时,处理好友请求状态同步问题
|
||||
2. SDK会议接口中添加permanent参数,可以创建永久保存会议。
|
||||
|
||||
---------------
|
||||
Release note 0.82:
|
||||
1. 修正PC在线状态逻辑错误问题
|
||||
2. 销毁用户时,清理所有信息
|
||||
4. SDK中添加更新消息的接口(仅专业版支持)
|
||||
5. SDK中添加获取在线用户数据(仅专业版支持)
|
||||
|
||||
---------------
|
||||
Release note 0.81:
|
||||
1. 修正PC在线状态某些特殊情况下错误问题
|
||||
2. 写入用户信息关系表时带上会话信息
|
||||
|
||||
---------------
|
||||
Release note 0.80:
|
||||
1. 全局频道或者可以给非订阅用户发送消息的频道允许非订阅用户回复消息
|
||||
2. Server API获取群组成员带上群组成员加入时间
|
||||
4. 支持平板端接入
|
||||
5. 解决有时PC在线状态错误问题
|
||||
6. log4j2升级到2.17.1
|
||||
|
||||
---------------
|
||||
Release note 0.79:
|
||||
1. 频道API发送消息时,如果automic则不发送给频道主
|
||||
2. 修改UserSetting表的key字段长度
|
||||
3. 敏感词过滤跳过链接,链接内的词语不过滤敏感词
|
||||
4. 销毁聊天室时,清理相关数据
|
||||
6. 加入聊天室时判断是否聊天室已经清理
|
||||
7. 升级log4j到log4j2
|
||||
|
||||
---------------
|
||||
Release note 0.78:
|
||||
1. 添加是否允许机器人自定义群通知的配置
|
||||
2. 修正禁止存储searchablecontent时的错误问题
|
||||
3. 解决API修改群组或用户为空时的异常问题
|
||||
4. 当用户修改自己信息时,通知其他的更新自己的信息
|
||||
5. MySQL数据字段中的关键字改为大小写敏感
|
||||
7. 使用新的id生成方法,生成9为数字小写字母组成的id。
|
||||
|
||||
---------------
|
||||
Release note 0.77:
|
||||
1. Server API添加获取频道信息,销毁频道,销毁机器人功能。
|
||||
2. 解决频道API发送中文乱码问题。
|
||||
3. 解决频道拉取远程消息错乱问题。
|
||||
4. 添加频道无密钥的错误码。
|
||||
5. 解决频道和机器人API高压力下错乱问题。
|
||||
|
||||
---------------
|
||||
Release note 0.76:
|
||||
1. 为聊天室单独添加拉取远程消息开关。
|
||||
2. 获取远程消息支持过滤消息类型。
|
||||
3. 推送、消息、回调等事件HTTP请求失败打印提示信息。
|
||||
|
||||
---------------
|
||||
Release note 0.75:
|
||||
1. 修正有时欢迎语排序乱序问题。
|
||||
2. 机器人禁止获取IM token。
|
||||
|
||||
---------------
|
||||
Release note 0.74:
|
||||
1. 发送好友请求时,如果已经是好友了,返回已经是好友的错误码
|
||||
2. 修正通过server api修改用户昵称没有通知客户端的问题
|
||||
3. 添加限频配置项
|
||||
|
||||
---------------
|
||||
Release note 0.73:
|
||||
1. 优化客户端断开连接功。
|
||||
2. 解决双方同时添加好友,后接受的失败的问题。
|
||||
|
||||
---------------
|
||||
Release note 0.72:
|
||||
1. 添加提醒消息回调
|
||||
2. 优化客户端断开连接功能
|
||||
3. 支持客户端lite模式
|
||||
|
||||
---------------
|
||||
Release note 0.71:
|
||||
1. 添加多端登录被踢下线的错误码
|
||||
2. 添加VOIP免打扰功能
|
||||
3. 消息撤回推送功能
|
||||
4. 推送只有pushData,没有pushContent也要推送
|
||||
|
||||
---------------
|
||||
Release note 0.70:
|
||||
1. 修改敏感词过滤问题
|
||||
2. 添加修改好友附加信息的server api
|
||||
|
||||
---------------
|
||||
Release note 0.69:
|
||||
1. 完善会议API
|
||||
2. 解决配置文件中特殊字符的问题
|
||||
3. 添加简单的健康检查API
|
||||
|
||||
---------------
|
||||
Release note 0.68:
|
||||
1. 去掉脚本中GC日志输出,减少无效日志。
|
||||
2. 添加配置是否加密存储消息。
|
||||
3. 当接受好友请求时,如果请求原因为空,不发送消息。
|
||||
4. 添加开关,当pc/web在线时移动端默认是否接收通知。
|
||||
5. 解决文件不存在时的异常日志。
|
||||
|
||||
---------------
|
||||
Release note 0.67:
|
||||
1. Server API发送好友强制参数错误问题
|
||||
2. 添加群组成员附加信息字段
|
||||
3. 添加配置,允许加入聊天室不存在时自动创建
|
||||
4. 解决Server API创建群组,部分参数无效问题
|
||||
5. Server SDK链接复用问题修正
|
||||
|
||||
---------------
|
||||
Release note 0.66:
|
||||
1. Server SDK支持多个机器人账户
|
||||
|
||||
---------------
|
||||
Release note 0.65:
|
||||
1. 添加分段更新好友/好友请求/用户设置功能,防止相关数据太大无法更新下来
|
||||
2. 同步Server SDK中关于会议的接口
|
||||
3. 修正Server API设置好友请求被限制的问题
|
||||
|
||||
---------------
|
||||
Release note 0.64:
|
||||
1. 修正0.62版本重构引入的短链接错乱问题
|
||||
2. 添加server api获取群组信息缺失字段
|
||||
3. 添加配置项,可以为内置存储配置远程服务地址
|
||||
|
||||
---------------
|
||||
Release note 0.63:
|
||||
1. 实现频道权限功能
|
||||
2. 配置文件中打开默认开启新好友欢迎语模式
|
||||
3. 客户端更新用户设置时,不用再通知当前端
|
||||
4. 群成员和好友请求中添加Extra字段
|
||||
|
||||
---------------
|
||||
Release note 0.62:
|
||||
1. 修改限频逻辑,server API,机器人api,频道api和客户端的限频要分开,避免server api超频导致客户端无法使用。
|
||||
2. 添加关闭群主/群管理撤回用户权限的开关。
|
||||
3. 对部分代码进行了重构。
|
||||
|
||||
---------------
|
||||
Release note 0.61:
|
||||
1. 升级缓存Hazelcast版本
|
||||
|
||||
---------------
|
||||
Release note 0.60:
|
||||
1. 解决server api修改群组信息失败问题
|
||||
|
||||
---------------
|
||||
Release note 0.59:
|
||||
1. 当server api未签名时,返回未签名的错误码
|
||||
2. 当群成员离开群后再次加入群时,修改群成员createTime为最后一次加入时间
|
||||
3. 解决自定义群组操作通知无效的问题
|
||||
4. 群组修改extra时,发送通知给客户端
|
||||
5. server api修改用户信息时添加修改name属性能力
|
||||
6. 为user messages表添加会话信息及索引等
|
||||
8. 内置测试存储文件上限提升到200MB
|
||||
|
||||
---------------
|
||||
Release note 0.58:
|
||||
1. 多人音视频添加成员也需要推送消息
|
||||
2. 添加禁言时允许发送的消息类型配置
|
||||
3. 添加频道相关api
|
||||
|
||||
---------------
|
||||
Release note 0.57:
|
||||
1. 修正某些情况下群组成员变更无法同步到客户端的问题
|
||||
|
||||
---------------
|
||||
Release note 0.56:
|
||||
1. 修正同一个设备登录多个用户的问题
|
||||
2. 优化启动脚本,可以在bin目录下执行
|
||||
|
||||
---------------
|
||||
Release note 0.55
|
||||
1. 添加更新用户api接口
|
||||
|
||||
---------------
|
||||
Release note 0.54:
|
||||
1. 添加对接第三方敏感词处理接口
|
||||
2. 添加消息转发类型过滤参数
|
||||
3. 去掉对客户端最大版本号的限制,可以兼容未来版本客户端
|
||||
4. 去掉默认敏感词
|
||||
|
||||
---------------
|
||||
Release note 0.53:
|
||||
1. 修正当敏感词策略为忽略时敏感词消息会从历史消息功能中拉取的问题
|
||||
2. 修正创建群组时,如果没有把owner加入到群成员列表中,服务器自动加入群成员列表,但count计数时没有加入的问题
|
||||
3. 添加获取两个用户之间用户关系的接口
|
||||
4. 解决某些情况下群组成员计数不准确的问题
|
||||
|
||||
---------------
|
||||
Release note 0.52:
|
||||
1. 添加配置是否同步用户信息中敏感信息到客户端
|
||||
2. SDK添加会话置顶功能
|
||||
3. 屏蔽掉日志中消息内容的打印,防止日志泄漏聊天内容
|
||||
4. 添加机器人进行群操作的功能
|
||||
5. 添加机器人更改机器人回调地址的接口
|
||||
6. 创建群组时,如果群主不在成员列表中自动加入群主
|
||||
8. 禁止客户端直接修改自己的电话号码,只能通过server api修改自己的电话号码
|
||||
9. 推送接听信息到客户端
|
||||
10. 优化客户端被踢下线的逻辑
|
||||
11. 内置存储下载时带上content-type字段
|
||||
12. 添加历史消息自动清除功能,3年以上的历史消息自动删除
|
||||
|
||||
---------------
|
||||
Release note 0.51:
|
||||
1. 修改群成员昵称时,发送通知消息
|
||||
2. 添加异常报警功能
|
||||
3. 修正清除客户端清除掉数据库,无法获取自己发送消息的问题
|
||||
4. 解决某些特殊情况下,用户session错误问题
|
||||
5. 优化多端客户端被踢下线或者pc被手机踢下线的功能
|
||||
|
||||
---------------
|
||||
Release note 0.50:
|
||||
1. 解决分页查找用户或者频道,查找翻页错误问题
|
||||
2. 添加是否允许客户端发送群操作通知的开关
|
||||
3. 添加禁止客户端发送消息类型的配置,可以配置禁止客户端发送特定类型消息
|
||||
4. 添加设置群成员昵称接口
|
||||
5. 添加配置,当退群或者踢人时是否发送显式通知消息
|
||||
|
||||
---------------
|
||||
Release note 0.48
|
||||
1. 推送数据中加上用户id
|
||||
2. server sdk发送消息接口添加定向用户参数
|
||||
3. 状态消息改为可以同步到发送者其它端
|
||||
4. 支持jdk15
|
||||
5. 添加撤回组播和广播消息接口
|
||||
6. 解决用户关系不存在时无法备注的问题
|
||||
|
||||
---------------
|
||||
Release note 0.48
|
||||
1. 同步专业版数据库
|
||||
|
||||
---------------
|
||||
Release note 0.47:
|
||||
1. 添加按照时间段免打扰功能
|
||||
2. 解决服务器压力过大时消息id可能重复问题
|
||||
3. 解决当拉取历史消息时,如果中间几个月没有发过消息无法拉取消息问题
|
||||
4. 移除掉无用的fastjson库,避免系统安全警告
|
||||
5. 添加群组/用户信息/频道信息变更通知
|
||||
|
||||
---------------
|
||||
Release note 0.46:
|
||||
1. Server api获取用户好友以好友状态时间排序
|
||||
2. 增加Server api发送好友请求的功能
|
||||
3. 解决server api删除好友时没有发送通知的问题
|
||||
4. 添加PC在线时是否移动端推送的开关
|
||||
5. 在频道或机器人没有密钥的情况下禁止使用api
|
||||
6. 添加默认文件助手用户
|
||||
7. 支持群主或群管理修改群成员昵称的功能
|
||||
|
||||
---------------
|
||||
Release note 0.45:
|
||||
1. 修正golang server api请求兼容问题。
|
||||
2. 修改两个用户互相发送好友请求时,丢失其中一条的问题。
|
||||
3. 解决server api删除好友失败的问题。
|
||||
|
||||
---------------
|
||||
Release note 0.44:
|
||||
1. 解决server api修改群成员昵称不生效的问题
|
||||
2. 添加服务器端允许撤回时间最长限制,仅对普通用户有效,系统管理员/server api/群管理员可以任何时候撤回消息
|
||||
3. 获取群成员接口检查权限,不在群组中成员无法获取群成员。
|
||||
4. 撤回消息的extra中添加更多原始消息内容
|
||||
5. 用户在线状态回调接口添加包名
|
||||
6. 创建群组时,按照请求列表顺序对成员排序
|
||||
7. 修正server SDK中的错误测试例
|
||||
9. Server SDK中添加对专业版白名单的支持
|
||||
10. 修正server api中设置好友状态不能实时同步到客户端的问题
|
||||
11. 修正客户端创建群组时,群主的群成员状态错误问题
|
||||
|
||||
---------------
|
||||
Release note 0.43:
|
||||
1. 修改撤回消息,extra信息填写错误问题
|
||||
2. 修正黑名单设置后无法取消问题
|
||||
3. 推送信息添加push_data字段
|
||||
4. 消息过期时间问题修正
|
||||
5. server api创建群组时,添加更多的可选参数
|
||||
6. 修正推送数据中计数不准确问题
|
||||
|
||||
> *** 0.42 版本增加了群成员数限制,默认为2000。如果您想修改默认值,可以在升级版本之后,修改t_setting表,把默认的大小改为您期望的。另外修改t_group表,把已经存在的群组max_member_count改成您期望的,然后重启。***
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.42:
|
||||
1. 当接受好友请求时,如果已经时好友,返回已经是好友的错误码
|
||||
2. 解决SDK中修改群信息缺少自定义通知内容的问题
|
||||
3. Server api获取群成员过滤掉已经删除成员信息
|
||||
4. SDK增加群内禁言功能(仅专业版支持)
|
||||
5. 转发消息带上消息id和时间戳
|
||||
6. 对拉黑server api添加参数校验
|
||||
7. 群成员添加加入时间属性
|
||||
8. 音视频电脑挂掉消息不增加未读消息计数
|
||||
9. 添加对群成员最大限制控制,默认为2000
|
||||
10. 普通成员可以修改群extra属性。
|
||||
12. 修改使用server api操作群时通知错误
|
||||
> *** 0.42 版本增加了群成员数限制,默认为2000。如果您想修改默认值,可以在升级版本之后,修改t_setting表,把默认的大小改为您期望的。另外修改t_group表,把已经存在的群组max_member_count改成您期望的,然后重启。***
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.41:
|
||||
1. 添加手机控制PC下线功能
|
||||
2. 添加是否保存searchable_content字段的配置
|
||||
3. 增加移动端退出不清除session且不推送消息操作(现在移动端退出有3个可选参数,断开连接有消息就推送/断开连接清掉服务器session/断开连接不推送且保留session)
|
||||
4. SDK添加对物联网设备的支持(物联网接入功能仅专业版有效)
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.40:
|
||||
1. 修正拒绝好友错误问题。
|
||||
2. 添加聊天室API。
|
||||
3. 添加禁止用户搜索和禁止添加好友的配置。
|
||||
4. 升级mysql connector到8.0.19版本。
|
||||
5. 添加PC在线状态通知。
|
||||
6. 在撤回消息中加上被撤回的内容。
|
||||
7. 修改设置黑名单失败的问题。
|
||||
8. 添加sticker bucket的支持。
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.39:
|
||||
1. 修正群内定向消息发送错误问题
|
||||
2. 添加好友成功多语言处理
|
||||
3. 修正拒绝好友请求的错误问题
|
||||
4. 修正内置测试文件服务器部分错误问题
|
||||
5. 添加机器人根据电话号码或用户名查询用户接口
|
||||
6. 修正Server SDK中的用户关系错误问题
|
||||
7. 修改获取用户在线状态错误问题
|
||||
8. 修正用户信息中社交字段无法更新问题
|
||||
9. 在好友关系中添加extra字段
|
||||
10. 给token添加过期时间配置
|
||||
11. 添加获取聊天室成员的api
|
||||
13. 修改被封禁用户连接失败的错误码
|
||||
14. 添加好友请求推送
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.38:
|
||||
1. 添加好友请求过期时间配置,可以配置重复发起好友请求时间
|
||||
2. 修正黑名单策略为1时发送消息仍失败的错误
|
||||
3. 增加sdk中聊天室创建接口,增加sdk聊天室相关测试代码
|
||||
4. 修改创建用户时不能指定用户类型的错误
|
||||
5. 增加日志默认大小
|
||||
6. 修改频道发送消息给指定用户错误问题
|
||||
7. 添加检查token是否正确的api
|
||||
8. 修正频道创建错误,修正频道发送消息错误
|
||||
|
||||
---------------
|
||||
Release note 0.37-1:
|
||||
1. 修复聊天室逻辑错误
|
||||
|
||||
---------------
|
||||
Release note 0.37
|
||||
1. 修正sdk中好友相关接口的错误。
|
||||
2. 添加是否运行陌生人聊天的配置。
|
||||
3. 增加获取备注的api。
|
||||
4. 增加用户在线状态回调功能。
|
||||
5. 优化聊天室逻辑,添加用户超时退出聊天室配置和是否发消息自动加入配置。
|
||||
6. 禁止发送消息给被封禁用户。
|
||||
7. 判断是否devicetoken重复时,加上包名条件。
|
||||
8. 添加好友请求相关时间配置。
|
||||
9. 添加频道SDK
|
||||
|
||||
---------------
|
||||
Release note 0.36
|
||||
1. 修正某些特殊情况下群组操作不同步的问题
|
||||
2. 优化用户的session管理
|
||||
|
||||
---------------
|
||||
Release note 0.35
|
||||
1. 修正0.34版本引入的无法拉取消息的严重问题
|
||||
2. 修正单条消息大于512K时无法收取消息问题
|
||||
3. 修改群主被添加进群状态错误问题
|
||||
4. 添加新的搜索类型,新增加按照账户或按照电话号码搜索
|
||||
|
||||
---------------
|
||||
Release note 0.34
|
||||
1.,添加销毁用户server接口和功能
|
||||
2,添加获取用户群组列表接口和功能
|
||||
3,添加用户已删除状态
|
||||
4,解决IM服务调用推送服务内存泄漏问题
|
||||
5,添加服务器为用户缓存消息条数配置
|
||||
|
||||
|
||||
--------------
|
||||
Release note 0.33
|
||||
|
||||
1. 优化用户session逻辑
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.32:
|
||||
1. 排除重复的device token
|
||||
2. 添加关闭多端功能。
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.31:
|
||||
1,解决了黑名单的同步的问题
|
||||
2,解决了黑名单发送消息成功的问题
|
||||
|
||||
--------------
|
||||
|
||||
Release note 0.30:
|
||||
1,重构了黑名单功能,好友关系和黑名单关系分开
|
||||
2,添加敏感词后立即生效
|
||||
3,转让群主后,群成员状态问题修复
|
||||
4,修改离线消息包大小,从1M改为512K
|
||||
@@ -300,11 +300,14 @@ push.ios.server.address http://localhost:8085/ios/push
|
||||
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
|
||||
#message.forward.types 1,2,3
|
||||
|
||||
##敏感消息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.sensitive.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#message.mentionmsg.forward.url http://localhost:8888/im_event/message
|
||||
|
||||
|
||||
##设备信息转发地址
|
||||
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
|
||||
#things_message.forward.url http://localhost:8087/im_event/things/message
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<version>0.92</version>
|
||||
<version>0.94</version>
|
||||
<name>Wildfire Chat</name>
|
||||
<description>Wildfire Chat Server</description>
|
||||
<inceptionYear>2019</inceptionYear>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>wildfirechat-parent</artifactId>
|
||||
<groupId>cn.wildfirechat</groupId>
|
||||
<version>0.92</version>
|
||||
<version>0.94</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.3</version>
|
||||
<version>4.5.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -39,6 +39,24 @@ public class GeneralAdmin {
|
||||
return AdminHttpUtils.httpJsonPost(path, inputChannelId, OutputGetChannelInfo.class);
|
||||
}
|
||||
|
||||
public static IMResult<Void> subscribeChannel(String channelId, String userId) throws Exception {
|
||||
String path = APIPath.Subscribe_Channel;
|
||||
InputSubscribeChannel input = new InputSubscribeChannel(channelId, userId, 1);
|
||||
return AdminHttpUtils.httpJsonPost(path, input, Void.class);
|
||||
}
|
||||
|
||||
public static IMResult<Void> unsubscribeChannel(String channelId, String userId) throws Exception {
|
||||
String path = APIPath.Subscribe_Channel;
|
||||
InputSubscribeChannel input = new InputSubscribeChannel(channelId, userId, 0);
|
||||
return AdminHttpUtils.httpJsonPost(path, input, Void.class);
|
||||
}
|
||||
|
||||
public static IMResult<OutputBooleanValue> isUserSubscribedChannel(String userId, String channelId) throws Exception {
|
||||
String path = APIPath.Check_User_Subscribe_Channel;
|
||||
InputSubscribeChannel input = new InputSubscribeChannel(channelId, userId, 0);
|
||||
return AdminHttpUtils.httpJsonPost(path, input, OutputBooleanValue.class);
|
||||
}
|
||||
|
||||
//以下仅专业版支持
|
||||
public static IMResult<Void> setConversationTop(String userId, int conversationType, String target, int line, boolean isTop) throws Exception {
|
||||
String key = conversationType + "-" + line + "-" + target;
|
||||
|
||||
@@ -9,6 +9,7 @@ import cn.wildfirechat.sdk.model.IMResult;
|
||||
import cn.wildfirechat.sdk.utilities.AdminHttpUtils;
|
||||
import cn.wildfirechat.sdk.utilities.RobotHttpUtils;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
|
||||
@@ -762,6 +763,17 @@ public class Main {
|
||||
} else {
|
||||
System.out.println("Get message delivery failure");
|
||||
}
|
||||
|
||||
conversation = new Conversation();
|
||||
conversation.setTarget("user1");
|
||||
conversation.setType(ProtoConstants.ConversationType.ConversationType_Private);
|
||||
conversation.setLine(0);
|
||||
IMResult<Void> clearConversationResult = MessageAdmin.clearConversation("user2", conversation);
|
||||
if (clearConversationResult != null && clearConversationResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
System.out.println("clear conversation success");
|
||||
} else {
|
||||
System.out.println("clear conversation failure");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> multicastReceivers = Arrays.asList("user2", "user3", "user4");
|
||||
@@ -1183,8 +1195,8 @@ public class Main {
|
||||
}
|
||||
|
||||
PojoGroupMember m = new PojoGroupMember();
|
||||
m.setMember_id("user1");
|
||||
m.setAlias("hello user1");
|
||||
m.setMember_id("user0");
|
||||
m.setAlias("hello user0");
|
||||
|
||||
voidIMResult = robotService.addGroupMembers(groupInfo.getTarget_id(), Arrays.asList(m), null, null);
|
||||
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
@@ -1390,8 +1402,16 @@ public class Main {
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
resultVoid = GeneralAdmin.subscribeChannel(channelId, "userId4");
|
||||
if (resultVoid != null && resultVoid.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
System.out.println("subscribe done");
|
||||
} else {
|
||||
System.out.println("subscribe failure");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
IMResult<OutputStringList> resultStringList = channelServiceApi.getSubscriberList();
|
||||
if (resultStringList != null && resultStringList.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && resultStringList.getResult().getList().contains("userId2") && resultStringList.getResult().getList().contains("userId3")) {
|
||||
if (resultStringList != null && resultStringList.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS && resultStringList.getResult().getList().contains("userId2") && resultStringList.getResult().getList().contains("userId3") && resultStringList.getResult().getList().contains("userId4")) {
|
||||
System.out.println("get subscriber done");
|
||||
} else {
|
||||
System.out.println("get subscriber failure");
|
||||
@@ -1491,7 +1511,7 @@ public class Main {
|
||||
menu21.url = "http://www.sohu.com";
|
||||
menu2.subMenus.add(menu21);
|
||||
|
||||
String menuStr = new Gson().toJson(menus);
|
||||
String menuStr = new GsonBuilder().disableHtmlEscaping().create().toJson(menus);
|
||||
voidIMResult = channelServiceApi.modifyChannelInfo(ProtoConstants.ModifyChannelInfoType.Modify_Channel_Menu, menuStr);
|
||||
if (voidIMResult != null && voidIMResult.getErrorCode() == ErrorCode.ERROR_CODE_SUCCESS) {
|
||||
System.out.println("modify channel menu success");
|
||||
|
||||
@@ -51,6 +51,14 @@ public class MessageAdmin {
|
||||
return AdminHttpUtils.httpJsonPost(path, updateMessageContentData, Void.class);
|
||||
}
|
||||
|
||||
public static IMResult<Void> clearConversation(String userId, Conversation conversation) throws Exception {
|
||||
String path = APIPath.Conversation_Delete;
|
||||
InputUserConversation input = new InputUserConversation();
|
||||
input.userId = userId;
|
||||
input.conversation = conversation;
|
||||
return AdminHttpUtils.httpJsonPost(path, input, Void.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单条消息。如果想要更多消息的读取,可以直接读取IM服务的数据库。
|
||||
* @param messageUid
|
||||
|
||||
@@ -2,17 +2,22 @@ package cn.wildfirechat.sdk.utilities;
|
||||
|
||||
import cn.wildfirechat.sdk.model.IMResult;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import ikidou.reflect.TypeBuilder;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.config.ConnectionConfig;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,10 +25,12 @@ import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class AdminHttpUtils extends JsonUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AdminHttpUtils.class);
|
||||
public static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
|
||||
private static String adminUrl;
|
||||
private static String adminSecret;
|
||||
@@ -32,7 +39,16 @@ public class AdminHttpUtils extends JsonUtils {
|
||||
public static void init(String url, String secret) {
|
||||
adminUrl = url;
|
||||
adminSecret = secret;
|
||||
httpClient = HttpClients.createDefault();
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
cm.setValidateAfterInactivity(1000);
|
||||
httpClient = HttpClients.custom()
|
||||
.setConnectionManager(cm)
|
||||
.evictExpiredConnections()
|
||||
.evictIdleConnections(60L, TimeUnit.SECONDS)
|
||||
.setRetryHandler(DefaultHttpRequestRetryHandler.INSTANCE)
|
||||
.setMaxConnTotal(100)
|
||||
.setMaxConnPerRoute(50)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> IMResult<T> httpGet(String path, Class<T> clazz) throws Exception {
|
||||
@@ -110,7 +126,7 @@ public class AdminHttpUtils extends JsonUtils {
|
||||
|
||||
String jsonStr = "";
|
||||
if (object != null) {
|
||||
jsonStr = new Gson().toJson(object);
|
||||
jsonStr = gson.toJson(object);
|
||||
}
|
||||
LOG.info("http request content: {}", jsonStr);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.wildfirechat.sdk.utilities;
|
||||
|
||||
import cn.wildfirechat.sdk.model.IMResult;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import ikidou.reflect.TypeBuilder;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
@@ -10,8 +11,10 @@ import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -19,10 +22,12 @@ import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class ChannelHttpUtils extends JsonUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChannelHttpUtils.class);
|
||||
public static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
|
||||
private String imurl;
|
||||
private String channelId;
|
||||
@@ -33,7 +38,16 @@ public class ChannelHttpUtils extends JsonUtils {
|
||||
this.imurl = imurl;
|
||||
this.channelId = channelId;
|
||||
this.channelSecret = secret;
|
||||
this.httpClient = HttpClients.createDefault();
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
cm.setValidateAfterInactivity(1000);
|
||||
httpClient = HttpClients.custom()
|
||||
.setConnectionManager(cm)
|
||||
.evictExpiredConnections()
|
||||
.evictIdleConnections(60L, TimeUnit.SECONDS)
|
||||
.setRetryHandler(DefaultHttpRequestRetryHandler.INSTANCE)
|
||||
.setMaxConnTotal(100)
|
||||
.setMaxConnPerRoute(50)
|
||||
.build();
|
||||
}
|
||||
|
||||
public <T> IMResult<T> httpJsonPost(String path, Object object, Class<T> clazz) throws Exception{
|
||||
@@ -62,7 +76,7 @@ public class ChannelHttpUtils extends JsonUtils {
|
||||
|
||||
String jsonStr = "";
|
||||
if (object != null) {
|
||||
jsonStr = new Gson().toJson(object);
|
||||
jsonStr = gson.toJson(object);
|
||||
}
|
||||
LOG.info("http request content: {}", jsonStr);
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@ package cn.wildfirechat.sdk.utilities;
|
||||
|
||||
import cn.wildfirechat.sdk.model.IMResult;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import ikidou.reflect.TypeBuilder;
|
||||
|
||||
public class JsonUtils {
|
||||
|
||||
public static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
public static <T> IMResult<T> fromJsonObject(String content, Class<T> clazz) {
|
||||
TypeBuilder builder = TypeBuilder.newInstance(IMResult.class);
|
||||
if (!clazz.equals(Void.class)) {
|
||||
builder.addTypeParam(clazz);
|
||||
}
|
||||
return new Gson().fromJson(content, builder.build());
|
||||
return gson.fromJson(content, builder.build());
|
||||
}
|
||||
|
||||
public static boolean isNullOrEmpty(String str) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.wildfirechat.sdk.utilities;
|
||||
|
||||
import cn.wildfirechat.sdk.model.IMResult;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import ikidou.reflect.TypeBuilder;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
@@ -11,8 +12,10 @@ import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,10 +23,12 @@ import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class RobotHttpUtils extends JsonUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RobotHttpUtils.class);
|
||||
public static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
|
||||
private final String url;
|
||||
private final String robotId;
|
||||
@@ -34,7 +39,16 @@ public class RobotHttpUtils extends JsonUtils {
|
||||
this.url = url;
|
||||
this.robotId = robotId;
|
||||
this.robotSecret = robotSecret;
|
||||
this.httpClient = HttpClients.createDefault();
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
cm.setValidateAfterInactivity(1000);
|
||||
httpClient = HttpClients.custom()
|
||||
.setConnectionManager(cm)
|
||||
.evictExpiredConnections()
|
||||
.evictIdleConnections(60L, TimeUnit.SECONDS)
|
||||
.setRetryHandler(DefaultHttpRequestRetryHandler.INSTANCE)
|
||||
.setMaxConnTotal(100)
|
||||
.setMaxConnPerRoute(50)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +77,7 @@ public class RobotHttpUtils extends JsonUtils {
|
||||
|
||||
String jsonStr = null;
|
||||
if (object != null) {
|
||||
jsonStr = new Gson().toJson(object);
|
||||
jsonStr = gson.toJson(object);
|
||||
}
|
||||
LOG.info("http request content: {}", jsonStr);
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
从github release处下载源码,或者从工程首页下载源码会编译失败,提示如下
|
||||
```
|
||||
[INFO] BUILD FAILURE
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 51.504 s
|
||||
[INFO] Finished at: 2019-11-04T20:27:21+08:00
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[ERROR] Failed to execute goal pl.project13.maven:git-commit-id-plugin:2.1.5:revision (default) on project distribution: .git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml -> [Help 1]
|
||||
[ERROR]
|
||||
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
|
||||
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
|
||||
|
||||
```
|
||||
原因是项目中有个git的插件需要读取当前工程的提交信息,github打包的源码没有git信息,所以就打包失败。
|
||||
解决办法:git clone下载
|
||||
Reference in New Issue
Block a user