Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wecloud_im_server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
hewei
wecloud_im_server
Commits
f9230d11
Commit
f9230d11
authored
May 18, 2022
by
wei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
服务端api调用 将一名用户添加至会话: ${clientID}通过${type}加入会话 -1014
parent
1a8cfb67
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
198 additions
and
17 deletions
+198
-17
common/src/main/java/com/wecloud/im/controller/serverapi/ApiImConversationMembersController.java
+23
-10
common/src/main/java/com/wecloud/im/param/add/ImConversationMemApiAdd.java
+34
-0
common/src/main/java/com/wecloud/im/service/ImConversationMembersService.java
+4
-0
common/src/main/java/com/wecloud/im/service/impl/ImConversationMembersServiceImpl.java
+122
-2
common/src/main/java/com/wecloud/im/service/impl/ImConversationServiceImpl.java
+13
-5
common/src/main/java/com/wecloud/im/ws/enums/MsgTypeEnum.java
+2
-0
No files found.
common/src/main/java/com/wecloud/im/controller/serverapi/ApiImConversationMembersController.java
View file @
f9230d11
...
@@ -3,11 +3,13 @@ package com.wecloud.im.controller.serverapi;
...
@@ -3,11 +3,13 @@ package com.wecloud.im.controller.serverapi;
import
com.wecloud.im.entity.ImApplication
;
import
com.wecloud.im.entity.ImApplication
;
import
com.wecloud.im.param.ApiImConversationMembersPageParam
;
import
com.wecloud.im.param.ApiImConversationMembersPageParam
;
import
com.wecloud.im.param.ApiImConversationMembersQueryVo
;
import
com.wecloud.im.param.ApiImConversationMembersQueryVo
;
import
com.wecloud.im.param.add.ImConversationMemApiAdd
;
import
com.wecloud.im.service.ImApplicationService
;
import
com.wecloud.im.service.ImApplicationService
;
import
com.wecloud.im.service.ImConversationMembersService
;
import
com.wecloud.im.service.ImConversationMembersService
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.controller.BaseController
;
import
io.geekidea.springbootplus.framework.common.controller.BaseController
;
import
io.geekidea.springbootplus.framework.core.validator.groups.Add
;
import
io.geekidea.springbootplus.framework.log.annotation.OperationLog
;
import
io.geekidea.springbootplus.framework.log.annotation.OperationLog
;
import
io.geekidea.springbootplus.framework.log.enums.OperationLogType
;
import
io.geekidea.springbootplus.framework.log.enums.OperationLogType
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
...
@@ -64,16 +66,27 @@ public class ApiImConversationMembersController extends BaseController {
...
@@ -64,16 +66,27 @@ public class ApiImConversationMembersController extends BaseController {
return
imConversationMembersService
.
getRestApiImConversationMembersList
(
apiImConversationMembersPageParam
,
imApplication
);
return
imConversationMembersService
.
getRestApiImConversationMembersList
(
apiImConversationMembersPageParam
,
imApplication
);
}
}
// /**
/**
// * 添加会话成员表
* 服务端api调用 将一名用户添加至会话: ${clientID}通过${type}加入会话 -1014
// */
*/
// @PostMapping("/add")
@PostMapping
(
"/add"
)
// @OperationLog(name = "添加会话成员表", type = OperationLogType.ADD)
@ApiOperation
(
value
=
" 服务端api调用 将一名用户添加至会话:${clientID}通过${type}加入会话 -1014"
)
// @ApiOperation(value = "添加会话成员表")
public
ApiResult
<
Boolean
>
addImConversationMembers
(
@Validated
(
Add
.
class
)
@RequestBody
ImConversationMemApiAdd
imConversationMemApiAdd
// public ApiResult<Boolean> addImConversationMembers(@Validated(Add.class) @RequestBody ImConversationMembers imConversationMembers) throws Exception {
,
@RequestHeader
String
appkey
,
@RequestHeader
String
appSecret
)
throws
Exception
{
// boolean flag = imConversationMembersService.saveImConversationMembers(imConversationMembers);
// 根据appKey从数据库查询密钥
// return ApiResult.result(flag);
ImApplication
imApplication
=
imApplicationService
.
getOneByAppKey
(
appkey
);
// }
if
(
imApplication
==
null
)
{
return
ApiResult
.
result
(
ApiCode
.
FAIL
,
null
);
}
// 校验appkey 和appSecret
if
(!
imApplication
.
getAppSecret
().
equals
(
appSecret
))
{
return
ApiResult
.
result
(
ApiCode
.
FAIL
,
null
);
}
boolean
flag
=
imConversationMembersService
.
addImConversationMembersApi
(
imConversationMemApiAdd
,
imApplication
);
return
ApiResult
.
result
(
flag
);
}
//
//
// /**
// /**
// * 修改会话成员表
// * 修改会话成员表
...
...
common/src/main/java/com/wecloud/im/param/add/ImConversationMemApiAdd.java
0 → 100644
View file @
f9230d11
package
com
.
wecloud
.
im
.
param
.
add
;
import
io.geekidea.springbootplus.framework.common.entity.BaseEntity
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
/**
* api添加会话成员
*
* @author wei
* @since 2022年05月16日14:13:46
*/
@Data
@Accessors
(
chain
=
true
)
@EqualsAndHashCode
(
callSuper
=
true
)
@ApiModel
(
value
=
"ImConversationMemAttrApiAdd"
)
public
class
ImConversationMemApiAdd
extends
BaseEntity
{
private
static
final
long
serialVersionUID
=
1L
;
@ApiModelProperty
(
value
=
"会话表id"
,
required
=
true
)
private
Long
conversationId
;
@ApiModelProperty
(
"操作者client ID,可为空"
)
private
String
operator
=
""
;
@ApiModelProperty
(
value
=
"被操作的client ID"
,
required
=
true
)
private
String
passivityOperator
;
@ApiModelProperty
(
"加入的类型, link或qrCode等"
)
private
String
joinType
=
""
;
}
common/src/main/java/com/wecloud/im/service/ImConversationMembersService.java
View file @
f9230d11
...
@@ -8,6 +8,7 @@ import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
...
@@ -8,6 +8,7 @@ import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
import
com.wecloud.im.param.ImConversationMembersListParam
;
import
com.wecloud.im.param.ImConversationMembersListParam
;
import
com.wecloud.im.param.ImConversationMembersPageParam
;
import
com.wecloud.im.param.ImConversationMembersPageParam
;
import
com.wecloud.im.param.ImConversationMembersQueryVo
;
import
com.wecloud.im.param.ImConversationMembersQueryVo
;
import
com.wecloud.im.param.add.ImConversationMemApiAdd
;
import
com.wecloud.im.param.add.ImConversationMemAttrUpdate
;
import
com.wecloud.im.param.add.ImConversationMemAttrUpdate
;
import
com.wecloud.im.vo.ImConversationMemberListVo
;
import
com.wecloud.im.vo.ImConversationMemberListVo
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
...
@@ -59,6 +60,9 @@ public interface ImConversationMembersService extends BaseService<ImConversation
...
@@ -59,6 +60,9 @@ public interface ImConversationMembersService extends BaseService<ImConversation
*/
*/
boolean
saveImConversationMembers
(
ImConversationMembers
imConversationMembers
)
throws
Exception
;
boolean
saveImConversationMembers
(
ImConversationMembers
imConversationMembers
)
throws
Exception
;
boolean
addImConversationMembersApi
(
ImConversationMemApiAdd
imConversationMemApiAdd
,
ImApplication
imApplication
);
/**
/**
* 修改
* 修改
*
*
...
...
common/src/main/java/com/wecloud/im/service/impl/ImConversationMembersServiceImpl.java
View file @
f9230d11
...
@@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper;
...
@@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper;
import
com.wecloud.im.entity.ImApplication
;
import
com.wecloud.im.entity.ImApplication
;
import
com.wecloud.im.entity.ImClient
;
import
com.wecloud.im.entity.ImClient
;
import
com.wecloud.im.entity.ImConversationMembers
;
import
com.wecloud.im.entity.ImConversationMembers
;
import
com.wecloud.im.entity.ImMessage
;
import
com.wecloud.im.entity.ImMessageOnlineSend
;
import
com.wecloud.im.mapper.ImConversationMapper
;
import
com.wecloud.im.mapper.ImConversationMapper
;
import
com.wecloud.im.mapper.ImConversationMembersMapper
;
import
com.wecloud.im.mapper.ImConversationMembersMapper
;
import
com.wecloud.im.param.ApiImConversationMembersPageParam
;
import
com.wecloud.im.param.ApiImConversationMembersPageParam
;
...
@@ -17,6 +19,7 @@ import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
...
@@ -17,6 +19,7 @@ import com.wecloud.im.param.ImConvMemeClientRemarkNameParam;
import
com.wecloud.im.param.ImConversationMembersListParam
;
import
com.wecloud.im.param.ImConversationMembersListParam
;
import
com.wecloud.im.param.ImConversationMembersPageParam
;
import
com.wecloud.im.param.ImConversationMembersPageParam
;
import
com.wecloud.im.param.ImConversationMembersQueryVo
;
import
com.wecloud.im.param.ImConversationMembersQueryVo
;
import
com.wecloud.im.param.add.ImConversationMemApiAdd
;
import
com.wecloud.im.param.add.ImConversationMemAttrUpdate
;
import
com.wecloud.im.param.add.ImConversationMemAttrUpdate
;
import
com.wecloud.im.service.ImApplicationService
;
import
com.wecloud.im.service.ImApplicationService
;
import
com.wecloud.im.service.ImClientService
;
import
com.wecloud.im.service.ImClientService
;
...
@@ -24,19 +27,27 @@ import com.wecloud.im.service.ImConversationMembersService;
...
@@ -24,19 +27,27 @@ import com.wecloud.im.service.ImConversationMembersService;
import
com.wecloud.im.service.ImConversationService
;
import
com.wecloud.im.service.ImConversationService
;
import
com.wecloud.im.service.ImMessageService
;
import
com.wecloud.im.service.ImMessageService
;
import
com.wecloud.im.vo.ImConversationMemberListVo
;
import
com.wecloud.im.vo.ImConversationMemberListVo
;
import
com.wecloud.im.ws.enums.MsgTypeEnum
;
import
com.wecloud.im.ws.enums.WsResponseCmdEnum
;
import
com.wecloud.im.ws.model.WsResponseModel
;
import
com.wecloud.im.ws.service.WriteDataService
;
import
com.wecloud.im.ws.service.WriteDataService
;
import
io.geekidea.springbootplus.framework.common.api.ApiCode
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl
;
import
io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl
;
import
io.geekidea.springbootplus.framework.core.pagination.PageInfo
;
import
io.geekidea.springbootplus.framework.core.pagination.PageInfo
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.jwt.JwtToken
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.JwtUtil
;
import
io.geekidea.springbootplus.framework.shiro.util.SnowflakeUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* 会话成员表 服务实现类
* 会话成员表 服务实现类
...
@@ -48,8 +59,7 @@ import java.util.List;
...
@@ -48,8 +59,7 @@ import java.util.List;
@Service
@Service
public
class
ImConversationMembersServiceImpl
extends
BaseServiceImpl
<
ImConversationMembersMapper
,
ImConversationMembers
>
implements
ImConversationMembersService
{
public
class
ImConversationMembersServiceImpl
extends
BaseServiceImpl
<
ImConversationMembersMapper
,
ImConversationMembers
>
implements
ImConversationMembersService
{
private
static
final
JsonMapper
JSON_MAPPER
=
new
JsonMapper
();
// private static final JsonMapper JSON_MAPPER = new JsonMapper();
@Autowired
@Autowired
private
WriteDataService
writeDataService
;
private
WriteDataService
writeDataService
;
...
@@ -202,6 +212,116 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
...
@@ -202,6 +212,116 @@ public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversa
return
super
.
save
(
imConversationMembers
);
return
super
.
save
(
imConversationMembers
);
}
}
@Override
public
boolean
addImConversationMembersApi
(
ImConversationMemApiAdd
imConversationMemApiAdd
,
ImApplication
imApplication
)
{
// 查询该会话所有成员
List
<
ImConversationMembers
>
membersList
=
imConversationMembersService
.
list
(
new
QueryWrapper
<
ImConversationMembers
>().
lambda
()
.
eq
(
ImConversationMembers:
:
getFkAppid
,
imApplication
.
getId
())
.
eq
(
ImConversationMembers:
:
getFkConversationId
,
imConversationMemApiAdd
.
getConversationId
())
);
if
(
membersList
.
isEmpty
())
{
log
.
info
(
"membersList为空,toConversationId:"
+
imConversationMemApiAdd
.
getConversationId
());
return
true
;
}
ImClient
client2
=
imClientService
.
getOne
(
new
QueryWrapper
<
ImClient
>().
lambda
()
.
eq
(
ImClient:
:
getFkAppid
,
imApplication
.
getId
())
.
eq
(
ImClient:
:
getClientId
,
imConversationMemApiAdd
.
getPassivityOperator
()));
// 判断用户是否已经在该会话
ImConversationMembers
members
=
imConversationMembersService
.
getOne
(
new
QueryWrapper
<
ImConversationMembers
>().
lambda
()
.
eq
(
ImConversationMembers:
:
getFkAppid
,
imApplication
.
getId
())
.
eq
(
ImConversationMembers:
:
getFkConversationId
,
imConversationMemApiAdd
.
getConversationId
())
.
eq
(
ImConversationMembers:
:
getFkClientId
,
client2
.
getId
())
);
// 已经在该会话 则跳过
if
(
members
!=
null
)
{
return
true
;
}
Long
imConversationMembersId2
=
SnowflakeUtil
.
getId
();
ImConversationMembers
imConversationMembers2
=
new
ImConversationMembers
();
imConversationMembers2
.
setId
(
imConversationMembersId2
);
imConversationMembers2
.
setCreateTime
(
new
Date
());
imConversationMembers2
.
setFkAppid
(
imApplication
.
getId
());
imConversationMembers2
.
setFkConversationId
(
imConversationMemApiAdd
.
getConversationId
());
imConversationMembers2
.
setFkClientId
(
client2
.
getId
());
// 添加到会话
imConversationMembersService
.
save
(
imConversationMembers2
);
// ws邀请事件通知给群内其他人 ----------
// 生成消息id
long
messageId
=
SnowflakeUtil
.
getId
();
ImMessage
imMessage
=
new
ImMessage
();
Map
<
String
,
Object
>
content
=
new
HashMap
<>();
content
.
put
(
"operator"
,
imConversationMemApiAdd
.
getOperator
());
//操作的client ID
content
.
put
(
"passivityOperator"
,
imConversationMemApiAdd
.
getPassivityOperator
());
//被操作的client ID
content
.
put
(
"joinType"
,
imConversationMemApiAdd
.
getJoinType
());
//被操作的client ID
content
.
put
(
"type"
,
MsgTypeEnum
.
SERVER_INVITE_CLIENT_JOIN_CONVERSATION
.
getUriCode
());
// 服务端api调用 将一名用户添加至会话: ${clientID}通过${type}加入会话 -1014
try
{
String
contentString
=
JSON_MAPPER
.
writeValueAsString
(
content
);
imMessage
.
setContent
(
contentString
);
}
catch
(
JsonProcessingException
e
)
{
e
.
printStackTrace
();
}
// 保存消息至消息表
imMessage
.
setId
(
messageId
);
imMessage
.
setCreateTime
(
new
Date
());
imMessage
.
setFkAppid
(
imApplication
.
getId
());
imMessage
.
setSender
(
0L
);
imMessage
.
setWithdraw
(
false
);
imMessage
.
setEvent
(
true
);
imMessage
.
setSystem
(
false
);
imMessage
.
setSendStatus
(
2
);
imMessage
.
setFkConversationId
(
imConversationMemApiAdd
.
getConversationId
());
boolean
save
=
imMessageService
.
save
(
imMessage
);
// 遍历发送
for
(
ImConversationMembers
conversationMembers
:
membersList
)
{
// 查询接收方
ImClient
imClientReceiver
=
imClientService
.
getOne
(
new
QueryWrapper
<
ImClient
>().
lambda
()
.
eq
(
ImClient:
:
getFkAppid
,
imApplication
.
getId
())
.
eq
(
ImClient:
:
getId
,
conversationMembers
.
getFkClientId
()));
if
(
imClientReceiver
==
null
)
{
continue
;
}
// 封装响应的实体
ImMessageOnlineSend
imMessageOnlineSend
=
new
ImMessageOnlineSend
();
imMessageOnlineSend
.
setMsgId
(
messageId
);
imMessageOnlineSend
.
setSender
(
""
);
imMessageOnlineSend
.
setContent
((
HashMap
)
content
);
imMessageOnlineSend
.
setConversationId
(
conversationMembers
.
getFkConversationId
());
imMessageOnlineSend
.
setWithdraw
(
Boolean
.
FALSE
);
imMessageOnlineSend
.
setEvent
(
Boolean
.
TRUE
);
// 向接收方推送
WsResponseModel
<
ImMessageOnlineSend
>
responseModel
=
new
WsResponseModel
<>();
responseModel
.
setCmd
(
WsResponseCmdEnum
.
CONVERSATION_EVENT_MSG
.
getCmdCode
());
ApiResult
<
Boolean
>
result
=
ApiResult
.
result
(
ApiCode
.
SUCCESS
);
responseModel
.
setCode
(
result
.
getCode
());
responseModel
.
setMsg
(
result
.
getMessage
());
responseModel
.
setData
(
imMessageOnlineSend
);
responseModel
.
setReqId
(
null
);
writeDataService
.
write
(
responseModel
,
imApplication
.
getAppKey
(),
imClientReceiver
.
getClientId
());
}
return
true
;
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
@Override
public
boolean
updateImConversationMembers
(
ImConversationMembers
imConversationMembers
)
throws
Exception
{
public
boolean
updateImConversationMembers
(
ImConversationMembers
imConversationMembers
)
throws
Exception
{
...
...
common/src/main/java/com/wecloud/im/service/impl/ImConversationServiceImpl.java
View file @
f9230d11
...
@@ -229,11 +229,20 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
...
@@ -229,11 +229,20 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
// shiro线程中获取当前token
// shiro线程中获取当前token
JwtToken
curentJwtToken
=
JwtUtil
.
getCurentJwtToken
();
JwtToken
curentJwtToken
=
JwtUtil
.
getCurentJwtToken
();
// 根据appKey查询application
ImApplication
imApplication
=
imApplicationService
.
getOneByAppKey
(
curentJwtToken
.
getAppKey
());
ImClient
imClientSender
=
imClientService
.
getCurentClient
();
ImClient
imClientSender
=
imClientService
.
getCurentClient
();
if
(
addMember
(
imClientToConversation
,
curentJwtToken
.
getAppKey
(),
imClientSender
))
{
return
ApiResult
.
fail
();
}
return
ApiResult
.
ok
();
}
private
boolean
addMember
(
ImClientToConversation
imClientToConversation
,
String
appKey
,
ImClient
imClientSender
)
{
// 根据appKey查询application
ImApplication
imApplication
=
imApplicationService
.
getOneByAppKey
(
appKey
);
// 查询该会话所有成员
// 查询该会话所有成员
List
<
ImConversationMembers
>
membersList
=
imConversationMembersService
.
list
(
List
<
ImConversationMembers
>
membersList
=
imConversationMembersService
.
list
(
new
QueryWrapper
<
ImConversationMembers
>().
lambda
()
new
QueryWrapper
<
ImConversationMembers
>().
lambda
()
...
@@ -244,7 +253,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
...
@@ -244,7 +253,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
);
);
if
(
membersList
.
isEmpty
())
{
if
(
membersList
.
isEmpty
())
{
log
.
info
(
"membersList为空,toConversationId:"
+
imClientToConversation
.
getConversationId
());
log
.
info
(
"membersList为空,toConversationId:"
+
imClientToConversation
.
getConversationId
());
return
ApiResult
.
fail
()
;
return
true
;
}
}
// 将他人添加到会话
// 将他人添加到会话
...
@@ -340,8 +349,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
...
@@ -340,8 +349,7 @@ public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMap
}
}
}
}
return
ApiResult
.
ok
();
return
false
;
}
}
@Override
@Override
...
...
common/src/main/java/com/wecloud/im/ws/enums/MsgTypeEnum.java
View file @
f9230d11
...
@@ -29,6 +29,8 @@ public enum MsgTypeEnum {
...
@@ -29,6 +29,8 @@ public enum MsgTypeEnum {
// 成为新群主 -1013
// 成为新群主 -1013
CONVERSATION_NEW_CREATOR
(-
1013
),
CONVERSATION_NEW_CREATOR
(-
1013
),
// 服务端api调用 将一名用户添加至会话: ${clientID}通过${type}加入会话 -1014
SERVER_INVITE_CLIENT_JOIN_CONVERSATION
(-
1014
),
;
;
private
final
int
uriCode
;
private
final
int
uriCode
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment