Compare commits

...
13 Commits
Author SHA1 Message Date
heavyrain lee 61dc1e2c2d Version 0.11 -> 0.12 2019-04-20 09:52:15 +08:00
heavyrain lee 2458782c73 Fix modify group not work issue 2019-04-20 09:43:51 +08:00
heavyrain lee 0f05d63a3b Add load history message function 2019-04-19 08:15:27 +08:00
heavyrain lee b82f7dea3d move mysql_tune to docs 2019-04-19 08:14:50 +08:00
heavyrain lee 6df626afd3 Remove useless file 2019-04-19 08:14:22 +08:00
heavyrain lee ac2d2a530a clean useless scripts 2019-04-19 08:13:43 +08:00
heavyrain lee 99a0590c7e Add port of upload token result and add to user list in message 2019-04-14 12:23:43 +08:00
heavyrain.lee 58c98bbbfa 调整再次添加好友逻辑:
1,如果没发过好友请求,或者上次发送好友请求状态为接受,可以发送
2,如果发送过好友请求,且状态不为接受,时间小于7天的,返回已经请求过错误码。
3,如果发送过好友请求,且状态不为接受,时间大于7天的,如果状态为reject,30天以内不能发送(返回拉黑错误码),30天以上可以再次发送
4,如果发送过好友请求,且状态不为接受,时间大于7天的,如果状态为sent,可以再次发送
2019-04-12 16:06:07 +08:00
heavyrain.lee 9560b9c202 1, 修改本地运行时version检查错误。2,修改好友被删除后再次添加好友。3,优化部分流程 2019-04-12 14:37:52 +08:00
imndx 24ebe429cc update readme 2019-04-11 22:58:00 +08:00
heavyrain2012 8ef92d0c1b fix modify group notification timestamp issue 2019-04-04 07:39:41 +08:00
heavyrain2012 e3e122edc4 机器人限频错误 2019-04-03 23:52:36 +08:00
imndx ab0e51feac update readme 2019-04-03 22:50:06 +08:00
41 changed files with 1419 additions and 1052 deletions
+4
View File
@@ -47,3 +47,7 @@ broker/nbactions-Server.xml
maven-metadata.xml
/.gradle/
/bin/
broker/config/git.properties
distribution/src/main/resources/git.properties
broker/h2db
broker/media
-48
View File
@@ -53,51 +53,3 @@ Except for the limited purpose of indicating to the public that the Work is lice
Creative Commons may be contacted at http://creativecommons.org/.
Copyright (c) <2019> <wildfirechat>
996 License Version 1.0 (Draft)
Permission is hereby granted to any individual or legal entity
obtaining a copy of this licensed work (including the source code,
documentation and/or related items, hereinafter collectively referred
to as the "licensed work"), free of charge, to deal with the licensed
work for any purpose, including without limitation, the rights to use,
reproduce, prepare derivative works of, distribute and sublicense the
licensed work, subject to the following conditions:
1. The individual or the legal entity must conspicuously display,
without modification, this License on each redistributed or derivative
copy of the Licensed Work.
2. The individual or the legal entity must strictly comply with all
applicable laws, regulations, rules and standards of the jurisdiction
relating to labor and employment where the individual is physically
located or where the individual was born or naturalized; or where the
legal entity is registered or is operating (whichever is stricter). In
case that the jurisdiction has no such laws, regulations, rules and
standards or its laws, regulations, rules and standards are
unenforceable, the individual or the legal entity are required to
comply with Core International Labor Standards.
3. The individual or the legal entity shall not induce or force its
employee(s), whether full-time or part-time, or its independent
contractor(s), in any methods, to agree in oral or written form, to
directly or indirectly restrict, weaken or relinquish his or her
rights or remedies under such laws, regulations, rules and standards
relating to labor and employment as mentioned above, no matter whether
such written or oral agreement are enforceable under the laws of the
said jurisdiction, nor shall such individual or the legal entity
limit, in any methods, the rights of its employee(s) or independent
contractor(s) from reporting or complaining to the copyright holder or
relevant authorities monitoring the compliance of the license about
its violation(s) of the said license.
THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE
LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
+46
View File
@@ -0,0 +1,46 @@
Copyright (c) <2019> <wildfirechat>
Anti 996 License Version 1.0 (Draft)
Permission is hereby granted to any individual or legal entity
obtaining a copy of this licensed work (including the source code,
documentation and/or related items, hereinafter collectively referred
to as the "licensed work"), free of charge, to deal with the licensed
work for any purpose, including without limitation, the rights to use,
reproduce, modify, prepare derivative works of, distribute, publish
and sublicense the licensed work, subject to the following conditions:
1. The individual or the legal entity must conspicuously display,
without modification, this License and the notice on each redistributed
or derivative copy of the Licensed Work.
2. The individual or the legal entity must strictly comply with all
applicable laws, regulations, rules and standards of the jurisdiction
relating to labor and employment where the individual is physically
located or where the individual was born or naturalized; or where the
legal entity is registered or is operating (whichever is stricter). In
case that the jurisdiction has no such laws, regulations, rules and
standards or its laws, regulations, rules and standards are
unenforceable, the individual or the legal entity are required to
comply with Core International Labor Standards.
3. The individual or the legal entity shall not induce or force its
employee(s), whether full-time or part-time, or its independent
contractor(s), in any methods, to agree in oral or written form, to
directly or indirectly restrict, weaken or relinquish his or her
rights or remedies under such laws, regulations, rules and standards
relating to labor and employment as mentioned above, no matter whether
such written or oral agreement are enforceable under the laws of the
said jurisdiction, nor shall such individual or the legal entity
limit, in any methods, the rights of its employee(s) or independent
contractor(s) from reporting or complaining to the copyright holder or
relevant authorities monitoring the compliance of the license about
its violation(s) of the said license.
THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE
LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
+19 -12
View File
@@ -2,20 +2,20 @@
野火IM是一套跨平台、全开源的即时通讯解决方案,主要包含以下内容。
| 仓库 | 说明 | 备注 |
| ------------------------------------------------------------ | ------------------------------------------------------- | ---- |
| [android-chat](https://github.com/wildfirechat/android-chat) | Android平台的SDK和Demo | |
| [ios-chat](https://github.com/wildfirechat/ios-chat) | iOS平台的SDK和Demo | |
| [pc-chat](https://github.com/wildfirechat/pc-chat) | 基于[Electron](https://electronjs.org/)开发的PC平台Demo | |
| [proto](https://github.com/wildfirechat/proto) | 野火IM的协议栈实现 | |
| [server](https://github.com/wildfirechat/server) | IM server | |
| [app server](https://github.com/wildfirechat/app_server) | 应用服务端Demo | |
| [robot_server](https://github.com/wildfirechat/robot_server) | 机器人服务端Demo | |
| [push_server](https://github.com/wildfirechat/push_server) | 推送服务器 | |
| [docs](https://github.com/wildfirechat/docs) | 野火IM相关文档,包含设计、概念、开发、使用说明 | |
| 仓库 | 说明 | 备注 |
| ------------------------------------------------------------ | ------------------------------------------------------- | ---------------------------------------------- |
| [android-chat](https://github.com/wildfirechat/android-chat) | 野火IM Android App | 可以很方便地进行二次开发,或集成到现有应用当中 |
| [ios-chat](https://github.com/wildfirechat/ios-chat) | 野火IM iOS App | 可以很方便地进行二次开发,或集成到现有应用当中 |
| [pc-chat](https://github.com/wildfirechat/pc-chat) | 基于[Electron](https://electronjs.org/)开发的PC平台应用 | |
| [proto](https://github.com/wildfirechat/proto) | 野火IM的协议栈实现 | |
| [server](https://github.com/wildfirechat/server) | IM server | |
| [app server](https://github.com/wildfirechat/app_server) | 应用服务端 | |
| [robot_server](https://github.com/wildfirechat/robot_server) | 机器人服务端 | |
| [push_server](https://github.com/wildfirechat/push_server) | 推送服务器 | |
| [docs](https://github.com/wildfirechat/docs) | 野火IM相关文档,包含设计、概念、开发、使用说明 | |
# server
本工程为野火IM 社区版IM服务软件。野火IM作为一个通用的即时通讯SDK,可以集成到各种应用中。请阅读[docs](http://docs.wildfirechat.cn)或下载服务器[发布版本](https://github.com/wildfirechat/server/releases)
本工程为野火IM 社区版IM服务软件。野火IM作为一个通用的即时通讯解决方案,可以集成到各种应用中。请阅读[docs](http://docs.wildfirechat.cn)或下载服务器[发布版本](https://github.com/wildfirechat/server/releases)
开发一套IM系统真的很艰辛,请路过的朋友们给点个star,支持我们坚持下去🙏🙏🙏🙏🙏
@@ -53,3 +53,10 @@
<img src="http://static.wildfirechat.cn/ios-location-view.png" width = 50% height = 50% />
<img src="http://static.wildfirechat.cn/ios-voip-view.png" width = 50% height = 50% />
## License
1. Under the Creative Commons Attribution-NoDerivs 3.0 Unported license. See the [LICENSE](https://github.com/wildfirechat/server/blob/wildfirechat/LICENSE) file for details.
2. Under the Anti 996 License. See the [Anti 996 LICENSE](https://github.com/wildfirechat/server/blob/wildfirechat/LICENSE_996) file for details.
-15
View File
@@ -1,15 +0,0 @@
#Generated by Git-Commit-Id-Plugin
#Wed Apr 03 15:25:25 CST 2019
git.commit.id.abbrev=cc82c5b
git.commit.user.email=[email protected]
git.commit.message.full=update version to 0.1.1\n
git.commit.id=cc82c5b420061994bc0621e807bb6c961370aef2
git.commit.message.short=update version to 0.1.1
git.commit.user.name=heavyrain2012
git.build.user.name=heavyrain2012
git.commit.id.describe=0.1.1-dirty
git.build.user.email=[email protected]
git.branch=wildfirechat
git.commit.time=20190403134707
git.build.time=20190403152525
git.remote.origin.url=https\://github.com/wildfirechat/server.git
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.11</version>
<version>0.12</version>
</parent>
<artifactId>moquette-broker</artifactId>
@@ -41,7 +41,7 @@ public class VersionAction extends Action {
response.setContent(new Gson().toJson(GitRepositoryState.getGitRepositoryState()));
} catch (IOException e) {
e.printStackTrace();
response.setContent("No version info!");
response.setContent("{\"version\":\"unknown\"}");
}
}
}
@@ -39,7 +39,7 @@ abstract public class RobotAction extends Action {
return ErrorCode.INVALID_PARAMETER;
}
if (mLimitCounter.isGranted(rid)) {
if (!mLimitCounter.isGranted(rid)) {
return ErrorCode.ERROR_CODE_OVER_FREQUENCY;
}
@@ -76,10 +76,12 @@ public class GetQiniuUploadTokenHandler extends IMHandler<Byte> {
token = auth.uploadToken(bucketName);
resultBuilder.setDomain(bucketDomain)
.setServer(MediaServerConfig.QINIU_SERVER_URL);
resultBuilder.setPort(80);
} else {
token = UploadFileAction.getToken(type);
resultBuilder.setDomain("http://" + MediaServerConfig.SERVER_IP + ":" + MediaServerConfig.HTTP_SERVER_PORT)
.setServer(MediaServerConfig.SERVER_IP);
resultBuilder.setPort(MediaServerConfig.HTTP_SERVER_PORT);
}
resultBuilder.setToken(token);
@@ -26,13 +26,13 @@ abstract public class GroupHandler<T> extends IMHandler<T> {
}
for (int line : lines) {
WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder().setContent(content);
builder.setConversation(builder.getConversationBuilder().setType(ProtoConstants.ConversationType.ConversationType_Group).setTarget(targetId).setLine(line));
long timestamp = System.currentTimeMillis();
WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder().setContent(content).setServerTimestamp(timestamp);
builder.setConversation(builder.getConversationBuilder().setType(ProtoConstants.ConversationType.ConversationType_Group).setTarget(targetId).setLine(line));
builder.setFromUser(fromUser);
long messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(fromUser, null, builder.build(), timestamp);
saveAndPublish(fromUser, null, builder.build());
}
}
@@ -32,7 +32,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
long timestamp = System.currentTimeMillis();
builder.setMessageId(messageId);
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build());
WFCMessage.MessageContent.Builder contentBuilder = WFCMessage.MessageContent.newBuilder().setType(90).setContent("以上是打招呼信息");
builder = WFCMessage.Message.newBuilder();
@@ -44,7 +44,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
messageId = MessageShardingUtil.generateId();
builder.setMessageId(messageId);
saveAndPublish(request.getTargetUid(), null, builder.build(), timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build());
contentBuilder.setContent("你们已经成为好友了,现在可以开始聊天了");
builder.setContent(contentBuilder);
@@ -52,7 +52,7 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
builder.setMessageId(messageId);
timestamp = System.currentTimeMillis();
builder.setServerTimestamp(timestamp);
saveAndPublish(request.getTargetUid(), null, builder.build(), System.currentTimeMillis());
saveAndPublish(request.getTargetUid(), null, builder.build());
publisher.publishNotification(IMTopic.NotifyFriendTopic, request.getTargetUid(), heads[0]);
publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]);
@@ -240,10 +240,10 @@ abstract public class IMHandler<T> {
}
protected long saveAndPublish(String username, String clientID, WFCMessage.Message message, long timestamp) {
protected long saveAndPublish(String username, String clientID, WFCMessage.Message message) {
Set<String> notifyReceivers = new LinkedHashSet<>();
message = m_messagesStore.storeMessage(username, clientID, message, timestamp);
message = m_messagesStore.storeMessage(username, clientID, message);
int pullType = m_messagesStore.getNotifyReceivers(username, message, notifyReceivers);
this.publisher.publish2Receivers(message, notifyReceivers, clientID, pullType);
return message.getMessageId();
@@ -0,0 +1,30 @@
/*
* 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 io.moquette.imhandler;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.ErrorCode;
import win.liyufan.im.IMTopic;
@Handler(value = IMTopic.LoadRemoteMessagesTopic)
public class LoadRemoteMessagesHandler extends IMHandler<WFCMessage.LoadRemoteMessages> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, WFCMessage.LoadRemoteMessages request, Qos1PublishHandler.IMCallback callback) {
ErrorCode errorCode = ErrorCode.ERROR_CODE_SUCCESS;
WFCMessage.PullMessageResult result = m_messagesStore.loadRemoteMessages(fromUser, request.getConversation(), request.getBeforeUid(), request.getCount());
byte[] data = result.toByteArray();
LOG.info("User {} load message with count({}), payload size({})", fromUser, result.getMessageCount(), data.length);
ackPayload.ensureWritable(data.length).writeBytes(data);
return errorCode;
}
}
@@ -99,7 +99,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
if (errorCode == ErrorCode.ERROR_CODE_SUCCESS) {
if (!ignoreMsg) {
saveAndPublish(fromUser, clientID, message, timestamp);
saveAndPublish(fromUser, clientID, message);
}
ackPayload = ackPayload.capacity(20);
ackPayload.writeLong(messageId);
@@ -8,6 +8,7 @@
package io.moquette.persistence;
import cn.wildfirechat.proto.ProtoConstants;
import cn.wildfirechat.proto.WFCMessage;
import cn.wildfirechat.server.ThreadPoolExecutorWrapper;
import com.hazelcast.core.HazelcastInstance;
@@ -532,6 +533,74 @@ public class DatabaseStore {
return null;
}
List<WFCMessage.Message> loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count) {
List<WFCMessage.Message> messages = loadRemoteMessagesFromTable(user, conversation, beforeUid, count, MessageShardingUtil.getMessageTable(beforeUid));
if (messages != null && messages.size() < count) {
String nexTable = MessageShardingUtil.getPreviousMessageTable(beforeUid);
List<WFCMessage.Message> nextMessages = loadRemoteMessagesFromTable(user, conversation, beforeUid, count-messages.size(), nexTable);
if (nextMessages != null) {
messages.addAll(nextMessages);
}
}
return messages;
}
List<WFCMessage.Message> loadRemoteMessagesFromTable(String user, WFCMessage.Conversation conversation, long beforeUid, int count, String table) {
String sql = "select `_from`, `_type`, `_target`, `_line`, `_data`, `_dt` from " + table +" where";
if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Private) {
sql += " _type = ? and _line = ? and _mid > ? and ((_target = ? and _from = ?) or (_target = ? and _from = ?)";
} else {
sql += " _type = ? and _line = ? and _mid > ? and _target = ?";
}
sql += " limit ?";
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
List<WFCMessage.Message> out = new ArrayList<>();
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
int index = 1;
statement.setInt(index++, conversation.getType());
statement.setInt(index++, conversation.getLine());
statement.setLong(index++, beforeUid);
statement.setString(index++, conversation.getTarget());
if (conversation.getType() == ProtoConstants.ConversationType.ConversationType_Private) {
statement.setString(index++, user);
statement.setString(index++, user);
statement.setString(index++, conversation.getTarget());
}
statement.setInt(index++, count);
resultSet = statement.executeQuery();
while (resultSet.next()) {
WFCMessage.Message.Builder builder = WFCMessage.Message.newBuilder();
index = 1;
builder.setMessageId(resultSet.getLong(index++));
builder.setFromUser(resultSet.getString(index++));
WFCMessage.Conversation.Builder cb = WFCMessage.Conversation.newBuilder();
cb.setType(resultSet.getInt(index++));
cb.setTarget(resultSet.getString(index++));
cb.setLine(resultSet.getInt(index++));
builder.setConversation(cb.build());
Blob blob = resultSet.getBlob(index++);
WFCMessage.MessageContent messageContent = WFCMessage.MessageContent.parseFrom(blob.getBinaryStream());
builder.setContent(messageContent);
builder.setServerTimestamp(resultSet.getTimestamp(index++).getTime());
WFCMessage.Message message = builder.build();
out.add(message);
}
} catch (SQLException | IOException e) {
e.printStackTrace();
Utility.printExecption(LOG, e);
} finally {
DBUtil.closeDB(connection, statement, resultSet);
}
return null;
}
void persistUserMessage(final String userId, final long messageId, final long messageSeq) {
mScheduler.execute(()->{
Connection connection = null;
@@ -663,12 +732,31 @@ public class DatabaseStore {
", `_extra`" +
", `_dt`" +
", `_member_count`" +
", `_member_dt`) values(?, ?, ?, ?, ?, ?, ?, ?, ?)";
", `_member_dt`) values(?, ?, ?, ?, ?, ?, ?, ?, ?)" +
" ON DUPLICATE KEY UPDATE " +
"`_name` = ?," +
"`_portrait` = ?," +
"`_owner` = ?," +
"`_type` = ?," +
"`_extra` = ?," +
"`_dt` = ?," +
"`_member_count` = ?," +
"`_member_dt` = ?";
statement = connection.prepareStatement(sql);
int index = 1;
statement.setString(index++, groupInfo.getTargetId());
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
statement.setInt(index++, groupInfo.getType());
statement.setString(index++, groupInfo.getExtra());
statement.setLong(index++, groupInfo.getUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setInt(index++, groupInfo.getMemberCount());
statement.setLong(index++, groupInfo.getMemberUpdateDt() == 0 ? System.currentTimeMillis() : groupInfo.getUpdateDt());
statement.setString(index++, groupInfo.getName());
statement.setString(index++, groupInfo.getPortrait());
statement.setString(index++, groupInfo.getOwner());
@@ -10,12 +10,13 @@ package io.moquette.persistence;
import cn.wildfirechat.proto.WFCMessage;
import com.hazelcast.core.MapLoader;
import com.hazelcast.core.MapStore;
import io.moquette.server.Server;
import java.util.Collection;
import java.util.Map;
public class GroupLoader implements MapLoader<String, WFCMessage.GroupInfo> {
public class GroupLoader implements MapStore<String, WFCMessage.GroupInfo> {
private DatabaseStore getDatabaseStore() {
return Server.getServer().getStore().messagesStore().getDatabaseStore();
}
@@ -51,18 +52,31 @@ public class GroupLoader implements MapLoader<String, WFCMessage.GroupInfo> {
return null;
}
/**
* Loads all of the keys from the store. The returned {@link Iterable} may return the keys lazily
* by loading them in batches. The {@link Iterator} of this {@link Iterable} may implement the
* {@link Closeable} interface in which case it will be closed once iteration is over.
* This is intended for releasing resources such as closing a JDBC result set.
* <p>
* The returned Iterable should not contain any <code>null</code> keys.
*
* @return all the keys. Keys inside the Iterable cannot be null.
*/
@Override
public Iterable<String> loadAllKeys() {
return null;
}
@Override
public void store(String key, WFCMessage.GroupInfo value) {
getDatabaseStore().persistGroupInfo(value);
}
@Override
public void storeAll(Map<String, WFCMessage.GroupInfo> map) {
for (WFCMessage.GroupInfo value : map.values()) {
getDatabaseStore().persistGroupInfo(value);
}
}
@Override
public void delete(String key) {
getDatabaseStore().removeGroupInfoFromDB(key);
}
@Override
public void deleteAll(Collection<String> keys) {
}
}
@@ -150,12 +150,11 @@ public class MemoryMessagesStore implements IMessagesStore {
}
@Override
public WFCMessage.Message storeMessage(String fromUser, String fromClientId, WFCMessage.Message message, long timestamp) {
public WFCMessage.Message storeMessage(String fromUser, String fromClientId, WFCMessage.Message message) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
IMap<Long, MessageBundle> mIMap = hzInstance.getMap(MESSAGES_MAP);
MessageBundle messageBundle = new MessageBundle(message.getMessageId(), fromUser, fromClientId, message);
if (message.getContent().getPersistFlag() == Transparent) {
mIMap.put(message.getMessageId(), messageBundle, 10, TimeUnit.SECONDS);
@@ -181,6 +180,8 @@ public class MemoryMessagesStore implements IMessagesStore {
if (!StringUtil.isNullOrEmpty(message.getToUser())) {
notifyReceivers.add(message.getToUser());
} else if(!message.getToList().isEmpty()) {
notifyReceivers.addAll(message.getToList());
} else {
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
Collection<WFCMessage.GroupMember> members = groupMembers.get(message.getConversation().getTarget());
@@ -345,6 +346,17 @@ public class MemoryMessagesStore implements IMessagesStore {
return builder.build();
}
@Override
public WFCMessage.PullMessageResult loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count) {
WFCMessage.PullMessageResult.Builder builder = WFCMessage.PullMessageResult.newBuilder();
List<WFCMessage.Message> messages = databaseStore.loadRemoteMessages(user, conversation, beforeUid, count);
builder.setCurrent(0).setHead(0);
if(messages != null) {
builder.addAllMessage(messages);
}
return builder.build();
}
@Override
public Collection<UserClientEntry> getChatroomMembers(String chatroomId) {
MultiMap<String, UserClientEntry> chatroomMembers = m_Server.getHazelcastInstance().getMultiMap(CHATROOM_MEMBER_IDS);
@@ -579,7 +591,6 @@ public class MemoryMessagesStore implements IMessagesStore {
.build();
mIMap.put(groupId, groupInfo);
databaseStore.persistGroupInfo(groupInfo);
MultiMap<String, WFCMessage.GroupMember> groupMembers = hzInstance.getMultiMap(GROUP_MEMBERS);
for (WFCMessage.GroupMember member : memberList) {
@@ -756,7 +767,6 @@ public class MemoryMessagesStore implements IMessagesStore {
groupMembers.remove(groupId);
mIMap.remove(groupId);
databaseStore.removeGroupInfoFromDB(groupId);
databaseStore.removeGroupMemberFromDB(groupId);
return ErrorCode.ERROR_CODE_SUCCESS;
@@ -1480,9 +1490,10 @@ public class MemoryMessagesStore implements IMessagesStore {
}
}
if (existRequest != null) {
if (existRequest != null && existRequest.getStatus() != ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) {
if (System.currentTimeMillis() - existRequest.getUpdateDt() > 7 * 24 * 60 * 60 * 1000) {
if (existRequest.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Rejected) {
if (existRequest.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Rejected
&& System.currentTimeMillis() - existRequest.getUpdateDt() < 30 * 24 * 60 * 60 * 1000) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_BLOCKED;
}
requestMap.remove(userId, existRequest);
@@ -1761,6 +1772,7 @@ public class MemoryMessagesStore implements IMessagesStore {
userSettingMap.put(userId, settingEntry);
userGlobalSlientMap.remove(userId);
userConvSlientMap.remove(userId);
userPushHiddenDetail.remove(userId);
return updateDt;
}
@@ -319,7 +319,7 @@ public class Server {
MediaServerConfig.SERVER_IP = getServerIp(config);
MediaServerConfig.HTTP_SERVER_PORT = config.getProperty(BrokerConstants.HTTP_SERVER_PORT);
MediaServerConfig.HTTP_SERVER_PORT = Integer.parseInt(config.getProperty(BrokerConstants.HTTP_SERVER_PORT));
MediaServerConfig.FILE_STROAGE_ROOT = config.getProperty(BrokerConstants.FILE_STORAGE_ROOT, MediaServerConfig.FILE_STROAGE_ROOT);
File file = new File(MediaServerConfig.FILE_STROAGE_ROOT);
@@ -21,7 +21,7 @@ public class MediaServerConfig {
public static String QINIU_BUCKET_FAVORITE_DOMAIN;
public static String SERVER_IP = "localhost";
public static String HTTP_SERVER_PORT = "8090";
public static int HTTP_SERVER_PORT = 8080;
public static String FILE_STROAGE_ROOT = "fs";
public static boolean USER_QINIU = false;
@@ -97,9 +97,10 @@ public interface IMessagesStore {
}
DatabaseStore getDatabaseStore();
WFCMessage.Message storeMessage(String fromUser, String fromClientId, WFCMessage.Message message, long timestamp);
WFCMessage.Message storeMessage(String fromUser, String fromClientId, WFCMessage.Message message);
int getNotifyReceivers(String fromUser, WFCMessage.Message message, Set<String> notifyReceivers);
WFCMessage.PullMessageResult fetchMessage(String user, String exceptClientId, long fromMessageId, int pullType);
WFCMessage.PullMessageResult loadRemoteMessages(String user, WFCMessage.Conversation conversation, long beforeUid, int count);
long insertUserMessages(String sender, int conversationType, String target, int line, int messageContentType, String userId, long messageId);
WFCMessage.GroupInfo createGroup(String operator, WFCMessage.GroupInfo groupInfo, List<WFCMessage.GroupMember> memberList);
ErrorCode addGroupMembers(String operator, String groupId, List<WFCMessage.GroupMember> memberList);
@@ -227,21 +227,25 @@ public class MessagesPublisher {
isSlient = true;
} else {
isSlient = false;
WFCMessage.Conversation conversation;
if (conversationType == ProtoConstants.ConversationType.ConversationType_Private) {
conversation = WFCMessage.Conversation.newBuilder().setType(conversationType).setLine(line).setTarget(sender).build();
} else {
conversation = WFCMessage.Conversation.newBuilder().setType(conversationType).setLine(line).setTarget(target).build();
}
if (m_messagesStore.getUserConversationSlient(user, conversation)) {
LOG.info("The conversation {}-{}-{} is slient", conversation.getType(), conversation.getTarget(), conversation.getLine());
isSlient = true;
}
if (!user.equals(sender)) {
WFCMessage.Conversation conversation;
if (conversationType == ProtoConstants.ConversationType.ConversationType_Private) {
conversation = WFCMessage.Conversation.newBuilder().setType(conversationType).setLine(line).setTarget(sender).build();
} else {
conversation = WFCMessage.Conversation.newBuilder().setType(conversationType).setLine(line).setTarget(target).build();
}
if (m_messagesStore.getUserGlobalSlient(user)) {
LOG.info("The user {} is global sliented", user);
isSlient = true;
if (m_messagesStore.getUserConversationSlient(user, conversation)) {
LOG.info("The conversation {}-{}-{} is slient", conversation.getType(), conversation.getTarget(), conversation.getLine());
isSlient = true;
}
if (m_messagesStore.getUserGlobalSlient(user)) {
LOG.info("The user {} is global sliented", user);
isSlient = true;
}
}
if (!StringUtil.isNullOrEmpty(pushContent) || messageContentType == 400 || messageContentType == 402) {
@@ -67,4 +67,6 @@ public interface IMTopic {
String ChannelPullTopic = "CHP";
String GetTokenTopic = "GETTOKEN";
String LoadRemoteMessagesTopic = "LRM";
}
@@ -60,4 +60,22 @@ public class MessageShardingUtil {
year %= 3;
return "t_messages_" + (year * 12 + month);
}
public static String getPreviousMessageTable(long mid) {
if (DBUtil.IsEmbedDB) {
return null;
}
mid >>= (nodeIdWidth + rotateIdWidth);
Date date = new Date(mid + T201801010000);
int month = date.getMonth();
int year = date.getYear();
year %= 3;
month = month + 1;
if (month == 12) {
month = 0;
year = (year + 3 -1)%3;
}
return "t_messages_" + (year * 12 + month);
}
}
+1 -1
View File
@@ -19,7 +19,7 @@
<!--MySQL数据库用户名-->
<property name="user">root</property>
<!--MySQL数据库密码-->
<property name="password">lt123456</property>
<property name="password">123456</property>
<!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->
<property name="initialPoolSize">10</property>
<!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
mvn clean install -Dmaven.test.skip=true
+1 -1
View File
@@ -6,7 +6,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.11</version>
<version>0.12</version>
</parent>
<modelVersion>4.0.0</modelVersion>
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.11</version>
<version>0.12</version>
</parent>
<artifactId>distribution</artifactId>
@@ -22,11 +22,6 @@
<outputDirectory>bin</outputDirectory>
</file>
<file>
<source>src/main/scripts/machinecode.sh</source>
<outputDirectory>bin</outputDirectory>
</file>
<file>
<source>src/main/resources/log4j.properties</source>
<outputDirectory>config/</outputDirectory>
@@ -76,10 +71,6 @@
<outputDirectory>config/</outputDirectory>
</file>
<file>
<source>src/main/resources/register.py</source>
<outputDirectory>tools/</outputDirectory>
</file>
<file>
<source>../broker/h2/create_table.sql</source>
@@ -1,53 +0,0 @@
# -- coding: utf-8 --
import time
import hashlib
import random
import requests
# 签名方法说明
# 注册用户需要签名,需要在header中加入nonce,timestamp, sign。
# 值如下所示。
# 服务器会检查时间戳,2个小时内有效。注意测试使用时避免过期
# 请注意需要与wildfirechat.conf中的SECRET_KEY保持一致
#需要用到requests库,首先要安装pip
#sudo easy_install pip
#然后在安装requests module
#sudo pip install requests
import sys
if len(sys.argv) < 2:
print 'Usage: python gettoken.py userid'
sys.exit()
user = sys.argv[1]
SECRET_KEY = '123456'
URL = 'http://localhost:18080/admin/user/token'
ts = (int(round(time.time() * 1000)))
random.seed(time.time())
nonce = (int(round(random.random() * 100000)))
orignSign = bytes(nonce) + '|' + SECRET_KEY + '|' + bytes(ts)
sign = hashlib.sha1(orignSign).hexdigest()
headers = {'nonce': bytes(nonce), 'timestamp':bytes(ts), 'sign':sign, 'Content-Type':'application/json'}
payload = {'userId':user}
print 'headers:'
print headers
print
print 'payload:'
print payload
print
r = requests.post(URL, headers = headers, json = payload)
print 'response:'
print(r.status_code)
print r.content
@@ -1,53 +0,0 @@
# -- coding: utf-8 --
import time
import hashlib
import random
import requests
# 签名方法说明
# 注册用户需要签名,需要在header中加入nonce,timestamp, sign。
# 值如下所示。
# 服务器会检查时间戳,2个小时内有效。注意测试使用时避免过期
# 请注意需要与wildfirechat.conf中的SECRET_KEY保持一致
#需要用到requests库,首先要安装pip
#sudo easy_install pip
#然后在安装requests module
#sudo pip install requests
import sys
if len(sys.argv) < 2:
print 'Usage: python getuserinfo.py userid'
sys.exit()
user = sys.argv[1]
SECRET_KEY = '123456'
URL = 'http://localhost/admin/user/info'
ts = (int(round(time.time() * 1000)))
random.seed(time.time())
nonce = (int(round(random.random() * 100000)))
orignSign = bytes(nonce) + '|' + SECRET_KEY + '|' + bytes(ts)
sign = hashlib.sha1(orignSign).hexdigest()
headers = {'nonce': bytes(nonce), 'timestamp':bytes(ts), 'sign':sign, 'Content-Type':'application/json'}
payload = {'userId':user}
print 'headers:'
print headers
print
print 'payload:'
print payload
print
r = requests.post(URL, headers = headers, json = payload)
print 'response:'
print(r.status_code)
print r.content
@@ -1,15 +0,0 @@
#Generated by Git-Commit-Id-Plugin
#Wed Apr 03 15:25:29 CST 2019
git.commit.id.abbrev=cc82c5b
git.commit.user.email=[email protected]
git.commit.message.full=update version to 0.1.1\n
git.commit.id=cc82c5b420061994bc0621e807bb6c961370aef2
git.commit.message.short=update version to 0.1.1
git.commit.user.name=heavyrain2012
git.build.user.name=heavyrain2012
git.commit.id.describe=0.1.1-dirty
git.build.user.email=[email protected]
git.branch=wildfirechat
git.commit.time=20190403134707
git.build.time=20190403152529
git.remote.origin.url=https\://github.com/wildfirechat/server.git
@@ -1,55 +0,0 @@
# -- coding: utf-8 --
import time
import hashlib
import random
import requests
# 签名方法说明
# 注册用户需要签名,需要在header中加入nonce,timestamp, sign。
# 值如下所示。
# 服务器会检查时间戳,2个小时内有效。注意测试使用时避免过期
# 请注意需要与wildfirechat.conf中的SECRET_KEY保持一致
#需要用到requests库,首先要安装pip
#sudo easy_install pip
#然后在安装requests module
#sudo pip install requests
import sys
if len(sys.argv) < 4:
print 'Usage: python register.py username password displayname'
sys.exit()
user = sys.argv[1]
pwd = sys.argv[2]
displayname = sys.argv[3]
SECRET_KEY = '123456'
URL = 'http://localhost:18080/admin/user/create'
ts = (int(round(time.time() * 1000)))
random.seed(time.time())
nonce = (int(round(random.random() * 100000)))
orignSign = bytes(nonce) + '|' + SECRET_KEY + '|' + bytes(ts)
sign = hashlib.sha1(orignSign).hexdigest()
headers = {'nonce': bytes(nonce), 'timestamp':bytes(ts), 'sign':sign, 'Content-Type':'application/json'}
payload = {'name':user, 'password':pwd, 'displayName':displayname}
print 'headers:'
print headers
print
print 'payload:'
print payload
print
r = requests.post(URL, headers = headers, json = payload)
print 'response:'
print(r.status_code)
print r.content
@@ -1,36 +0,0 @@
#!/bin/sh
cd "$(dirname "$0")"
# resolve links - $0 may be a softlink
PRG="$0"
while [ -h "$PRG" ]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
PRGDIR=`dirname "$PRG"`
cd ..
WILDFIRECHAT_HOME=`pwd`
export WILDFIRECHAT_HOME
if [ -f "${JAVA_HOME}/bin/java" ]; then
JAVA=${JAVA_HOME}/bin/java
else
JAVA=java
fi
export JAVA
WILDFIRECHAT_PATH=$WILDFIRECHAT_HOME/
$JAVA -cp "$WILDFIRECHAT_HOME/lib/*" cn.wildfirechat.server.MechineCode $1 $2
-109
View File
@@ -1,109 +0,0 @@
# MySQL 调优
### 1,所有的表都必须有primary key.
因为需要用primary key来表示每一行,最好用自增的整形
### 2, 使用in代替or
SELECT * FROM t WHERE LOC_IN IN (10,20,30);
### 3, 不使用子查询
使用join
### 4. 足够大的 innodb_buffer_pool_size
最大内存数在总的innoDB内存数据160%就行,比如数据大小5G,buffer size设置为8G就行,有个命令来获取应当设置的大小
```
SELECT CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3)) RIBPS FROM
(SELECT SUM(data_length+index_length) Total_InnoDB_Bytes
FROM information_schema.tables WHERE engine='InnoDB') A;
```
> 需要注意这个系统刚开始允许,无法计算出实际使用量。一般需要系统实际允许几个月,或者设置成机器物理内存的一半。
---
### 5. 配置 innodb_log_file_size
使用足够大的写入缓存 innodb_log_file_size
可是须要注意假设用 1G 的 innodb_log_file_size 。假如server当机。须要 10 分钟来恢复。
推荐 innodb_log_file_size 设置为 0.25 * innodb_buffer_pool_size
---
### 6. 配置 innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit = 1 则每次改动写入磁盘
innodb_flush_log_at_trx_commit = 0/2 每秒写入磁盘
假设你的应用不涉及非常高的安全性 (金融系统),或者基础架构足够安全,或者 事务都非常小,都能够用 0 或者 2 来减少磁盘操作。
---
### 7. 避免双写入缓冲
innodb_flush_method=O_DIRECT
---
### 8. innodb_write_io_threads
写IO线程,默认4,最大可设置成64.每个线程可以处理256个pending io request.需要根据您的cpu数和读写比例调整,在当前项目中可设置为物理核数的2倍
---
### 9. innodb_read_io_threads
读IO线程,默认4,最大可设置成64.每个线程可以处理256个pending io request.需要根据您的cpu数和读写比例调整,在当前项目中保持4就可以了
---
### 10. innodb_thread_concurrency
线程并发数,0是不限制。如果设置最大是1000,可以设置成cpu核数的8倍
---
### 11. 关闭swap
对于单独的数据库服务器,在内存足够大的情况下,可以关闭swap
```
sync # 先执行下同步
swapoff -a # 关闭swap分区
swapon -a # 开启swap分区
swapoff -a && swapon -a # 刷新swap空间,即将SWAP里的数据转储回内存,并清空SWAP里的数据。刷新原理就是把swap关闭后再重启。
```
---
### 12. DB连接数
show global variables like "max_connections"; 显示最大连接数
SET GLOBAL max_connections = 2000; 设置最大连接数
### 13. c3p0连接池
修改最大连接数,注意需要确保DB能撑得起集群的最大连接数
### 14. 示例
mysqld.cnf配置
```
[mysqld]
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = /usr/local/mysql/data
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = /usr/local/mysql/data
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 2G
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 512M
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method=O_DIRECT
#innodb_lock_wait_timeout = 50
```
> 以上信息来源于
> https://www.cnblogs.com/jxldjsn/p/6010720.html
> https://www.percona.com/blog/2016/10/12/mysql-5-7-performance-tuning-immediately-after-installation/
> https://www.cnblogs.com/claireyuancy/p/7258314.html
> http://www.codingpedia.org/ama/optimizing-mysql-server-settings/
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging>
<version>0.11</version>
<version>0.12</version>
<name>Wildfire Chat</name>
<description>Wildfire Chat Server</description>
<inceptionYear>2018</inceptionYear>
-7
View File
@@ -1,7 +0,0 @@
protoc -odata.pb wfcmessage.proto
g++ -o convert convert.cpp
./convert
mv pbdata.h ../../../ios-workspace/mars/mars/proto/src/Proto/
rm convert data.pb
protoc --java_out=./ wfcmessage.proto
mv ./cn/wildfirechat/proto/WFCMessage.java ../../client/src/main/java/cn/wildfirechat/proto/
-36
View File
@@ -1,36 +0,0 @@
#include <string>
#include <fstream>
using namespace std;
int main () {
ofstream out("pbdata.h");
ifstream in("data.pb", ios::in | ios::binary);
if (out.is_open() && in.is_open())
{
out << "static unsigned char pbdata[] = { ";
int flag = 0;
int preCh;
while (!in.eof()) {
unsigned char ch = 0;
in.read((char *)&ch, 1);
if (flag == 1) {
out << preCh;
} else if (flag > 1) {
out << ",";
out << preCh;
}
preCh = ch;
flag += 1;
}
out << "};\n";
in.close();
out.close();
}
return 0;
}
-443
View File
@@ -1,443 +0,0 @@
syntax = "proto2";
//package mars.stn;
option java_package = "cn.wildfirechat.proto";
option java_outer_classname = "WFCMessage";
//option optimize_for = LITE_RUNTIME;
message AddFriendRequest {
required string target_uid = 1;
required string reason = 2;
}
message Conversation {
required int32 type = 1;
required string target = 2;
required int32 line = 3;
}
message GroupInfo {
optional string target_id = 1;
required string name = 2;
optional string portrait = 3;
optional string owner = 4;
required int32 type = 5;
optional int32 member_count = 6;
optional string extra = 7;
optional int64 update_dt = 8;
optional int64 member_update_dt = 9;
}
message GroupMember {
required string member_id = 1;
optional string alias = 2;
required int32 type = 3;
optional int64 update_dt = 4;
}
message Group {
required GroupInfo group_info = 1;
repeated GroupMember members = 2;
}
message ChannelInfo {
optional string target_id = 1;
required string name = 2;
optional string portrait = 3;
optional string owner = 4;
//0, public; 1, private; 2 closed;
optional int32 status = 5;
optional string desc = 6;
optional string extra = 7;
optional int64 update_dt = 8;
optional string secret = 9;
optional string callback = 10;
optional int32 automatic = 11;
}
message ModifyChannelInfo {
required string channel_id = 1;
required int32 type = 2;
required string value = 3;
}
message TransferChannel {
required string channel_id = 1;
required string new_owner = 2;
}
message PullChannelInfo {
required string channel_id = 1;
required int64 head = 2;
}
message PullChannelListener {
required string channel_id = 1;
required int32 offset = 2;
required int32 count = 3;
}
message PullChannelListenerResult {
required int32 total_count = 1;
required int32 offset = 2;
repeated string listener = 3;
}
message ListenChannel {
required string channel_id = 1;
required int32 listen = 2;
}
message SearchChannelResult {
repeated ChannelInfo channel = 1;
required string keyword = 2;
}
message MessageContent {
required int32 type = 1;
optional string searchable_content = 2;
optional string push_content = 3;
optional string content = 4;
optional bytes data = 5;
optional int32 mediaType = 6;
optional string remoteMediaUrl = 7;
optional int32 persist_flag= 8;
optional int32 expire_duration= 9;
optional int32 mentioned_type= 10;
repeated string mentioned_target= 11;
}
message AddGroupMemberRequest {
required string group_id = 1;
repeated GroupMember added_member = 2;
repeated int32 to_line = 3;
optional MessageContent notify_content = 4;
}
message CreateGroupRequest {
required Group group = 1;
repeated int32 to_line = 2;
optional MessageContent notify_content = 3;
}
message DismissGroupRequest {
required string group_id = 1;
repeated int32 to_line = 2;
optional MessageContent notify_content = 3;
}
message FriendRequest {
optional string from_uid = 1;
required string to_uid = 2;
required string reason = 3;
optional int32 status = 4;
optional int64 update_dt = 5;
optional bool from_read_status = 6;
optional bool to_read_status = 7;
}
message GeneralResult {
required int32 error_code = 1;
}
message GetUploadTokenResult {
required string domain = 1;
required string token = 2;
required string server = 3;
}
message HandleFriendRequest {
required string target_uid = 1;
required int32 status = 2;
}
message IDBuf {
required string id = 1;
}
message IDListBuf {
repeated string id = 1;
}
message Message {
required Conversation conversation = 1;
required string from_user = 2;
required MessageContent content = 3;
optional int64 message_id = 4;
optional int64 server_timestamp = 5;
optional string to_user = 6;
}
message User {
required string uid = 1;
optional string name = 2;
optional string display_name = 3;
optional string portrait = 4;
optional string mobile = 5;
optional string email = 6;
optional string address = 7;
optional string company = 8;
optional string extra = 9;
optional int64 update_dt = 10;
optional int32 gender = 11;
optional string social = 12;
//0 normal user; 1 robot
optional int32 type = 13;
}
message Robot {
required string uid = 1;
//0 normal; 1 deleted;
required int32 state = 2;
optional string owner = 3;
optional string secret = 4;
optional string callback = 5;
optional string extra = 6;
}
message GetRobotsResult {
repeated Robot entry = 1;
}
message Thing {
required string uid = 1;
//0 normal; 1 deleted;
required int32 state = 2;
required string token = 3;
optional string owner = 4;
optional string extra = 5;
}
message GetThingsResult {
repeated Thing entry = 1;
}
message UploadDeviceTokenRequest {
required int32 platform = 1;
required string app_name = 2;
required string device_token = 3;
required int32 push_type = 4;
}
message ModifyGroupInfoRequest {
required string group_id = 1;
required int32 type = 2;
required string value = 3;
repeated int32 to_line = 4;
optional MessageContent notify_content = 5;
}
message InfoEntry {
required int32 type = 1;
required string value = 2;
}
message ModifyMyInfoRequest {
repeated InfoEntry entry = 1;
}
message NotifyMessage {
required int32 type = 1;
required int64 head = 2;
optional string target = 3;
}
message PullMessageRequest {
required int64 id = 1;
required int32 type = 2;
optional int64 delay = 3;
}
message PullMessageResult {
repeated Message message = 1;
required int64 current = 2;
required int64 head = 3;
}
message PullGroupInfoResult {
repeated GroupInfo info = 1;
}
message PullGroupMemberRequest {
required string target = 1;
required int64 head = 2;
}
message PullGroupMemberResult {
repeated GroupMember member = 1;
}
message UserRequest {
required string uid = 1;
optional int64 update_dt = 2;
}
message PullUserRequest {
repeated UserRequest request = 1;
}
message UserResult {
required User user = 1;
required int32 code = 2;
}
message PullUserResult {
repeated UserResult result = 1;
}
message QuitGroupRequest {
required string group_id = 1;
repeated int32 to_line = 2;
optional MessageContent notify_content = 3;
}
message RemoveGroupMemberRequest {
required string group_id = 1;
repeated string removed_member = 2;
repeated int32 to_line = 3;
optional MessageContent notify_content = 4;
}
message TransferGroupRequest {
required string group_id = 1;
required string new_owner = 2;
repeated int32 to_line = 3;
optional MessageContent notify_content = 4;
}
message ModifyGroupMemberAlias {
required string group_id = 1;
required string alias = 2;
repeated int32 to_line = 3;
optional MessageContent notify_content = 4;
}
message UserSettingEntry {
required int32 scope = 1;
required string key = 2;
required string value = 3;
required int64 update_dt = 4;
}
message ModifyUserSettingReq {
required int32 scope = 1;
required string key = 2;
required string value = 3;
}
message Version {
required int64 version = 1;
}
message GetUserSettingResult {
repeated UserSettingEntry entry = 1;
}
message Friend {
required string uid = 1;
required int32 state = 2;
required int64 update_dt = 3;
}
message GetFriendsResult {
repeated Friend entry = 1;
}
message GetFriendRequestResult {
repeated FriendRequest entry = 1;
}
message ConnectAckPayload {
optional int64 msg_head = 1;
optional int64 friend_head = 2;
optional int64 friend_rq_head = 3;
optional int64 setting_head = 4;
optional string node_addr = 5;
optional int32 node_port = 6;
optional int64 server_time = 7;
}
message IMHttpWrapper {
required string token = 1;
required string client_id = 2;
required string request = 3;
optional bytes data = 4;
}
message SearchUserRequest {
required string keyword = 1;
optional int32 fuzzy = 2;
optional int32 page = 3;
}
message SearchUserResult {
repeated User entry = 1;
}
message GetChatroomInfoRequest {
required string chatroom_id = 1;
optional int64 update_dt = 2;
}
message ChatroomInfo {
required string title = 1;
optional string desc = 2;
optional string portrait = 3;
optional int32 member_count = 4;
optional int64 create_dt = 5;
optional int64 update_dt = 6;
optional string extra = 7;
optional int32 state = 8;
}
message GetChatroomMemberInfoRequest {
required string chatroom_id = 1;
optional int32 max_count = 2;
}
message ChatroomMemberInfo {
optional int32 member_count = 1;
repeated string members = 2;
}
message INT64Buf {
required int64 id = 1;
}
message NotifyRecallMessage {
required int64 id = 1;
required string from_user = 2;
}
message BlackUserRequest {
required string uid = 1;
required int32 status = 2;
}
message RouteRequest {
optional string app = 1;
optional int32 platform = 2;
optional int32 push_type = 3;
optional string device_name = 4;
optional string device_version = 5;
optional string phone_name = 6;
optional string language = 7;
optional string carrier_name = 8;
optional string app_version = 9;
optional string sdk_version = 10;
}
message RouteResponse {
required string host = 1;
required int32 long_port = 2;
required int32 short_port = 3;
}
message GetTokenRequest {
required string user_id = 1;
required string client_id = 2;
}
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
dest=$1
mvn clean install -Dmaven.test.skip=true
if [ -n "$dest" ];then
scp distribution/target/distribution-0.10-bundle-tar.tar.gz ${dest}:~/wildfirechat/
ssh ${dest} 'cd ~/wildfirechat; bash deploy.sh'
sleep 20s
curl im.liyufan.win:8080/api/version
echo ""
echo "curl wildfirechat.cn/api/version"
fi
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId>
<version>0.11</version>
<version>0.12</version>
</parent>
<groupId>net.xmeter</groupId>