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
b15cc7cd
Commit
b15cc7cd
authored
Apr 13, 2022
by
罗长华
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1、完成im-sdk http请求通用功能封装
parent
4ee85807
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
817 additions
and
125 deletions
+817
-125
core/src/main/java/com/wecloud/im/controller/ImClientController.java
+11
-0
core/src/main/java/com/wecloud/im/param/RegisterClientParam.java
+49
-0
core/src/main/java/com/wecloud/im/service/ImClientService.java
+10
-2
core/src/main/java/com/wecloud/im/service/impl/ImClientServiceImpl.java
+31
-0
core/src/main/java/com/wecloud/im/vo/RegisterClientResponse.java
+17
-0
im-sdk/pom.xml
+9
-2
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudIm.java
+12
-15
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudImClient.java
+28
-38
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudImClientBuilder.java
+4
-4
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpClient.java
+35
-12
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpMesssage.java
+21
-0
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpMethod.java
+40
-0
im-sdk/src/main/java/com/wecloud/im/sdk/common/RequestMessage.java
+97
-0
im-sdk/src/main/java/com/wecloud/im/sdk/common/RequestParamSigner.java
+42
-0
im-sdk/src/main/java/com/wecloud/im/sdk/exception/WecloudException.java
+19
-0
im-sdk/src/main/java/com/wecloud/im/sdk/internal/OSSRequestMessageBuilder.java
+101
-0
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudHeaders.java
+14
-0
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudImClientOperation.java
+52
-0
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudImOperation.java
+88
-0
im-sdk/src/main/java/com/wecloud/im/sdk/model/GetSignParam.java
+0
-28
im-sdk/src/main/java/com/wecloud/im/sdk/model/ImClient.java
+5
-24
im-sdk/src/main/java/com/wecloud/im/sdk/model/RegisterClientRequest.java
+38
-0
im-sdk/src/main/java/com/wecloud/im/sdk/model/WebServiceRequest.java
+21
-0
im-sdk/src/main/java/com/wecloud/im/sdk/sample/RegisterClientSample.java
+28
-0
im-sdk/src/main/java/com/wecloud/im/sdk/utils/CodingUtils.java
+17
-0
im-sdk/src/main/java/com/wecloud/im/sdk/utils/HttpHeaders.java
+28
-0
No files found.
core/src/main/java/com/wecloud/im/controller/ImClientController.java
View file @
b15cc7cd
...
@@ -27,6 +27,7 @@ import com.wecloud.im.param.ClientInfoParam;
...
@@ -27,6 +27,7 @@ import com.wecloud.im.param.ClientInfoParam;
import
com.wecloud.im.param.GetClientInfoParam
;
import
com.wecloud.im.param.GetClientInfoParam
;
import
com.wecloud.im.param.GetOnlineStatusParam
;
import
com.wecloud.im.param.GetOnlineStatusParam
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.RegisterClientParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
...
@@ -37,6 +38,7 @@ import com.wecloud.im.vo.ClientInfoVo;
...
@@ -37,6 +38,7 @@ import com.wecloud.im.vo.ClientInfoVo;
import
com.wecloud.im.vo.GetInfoListVo
;
import
com.wecloud.im.vo.GetInfoListVo
;
import
com.wecloud.im.vo.ImOnlineStatusVo
;
import
com.wecloud.im.vo.ImOnlineStatusVo
;
import
com.wecloud.im.vo.MyInfoVo
;
import
com.wecloud.im.vo.MyInfoVo
;
import
com.wecloud.im.vo.RegisterClientResponse
;
import
com.wecloud.im.ws.cache.UserStateCacheManager
;
import
com.wecloud.im.ws.cache.UserStateCacheManager
;
/**
/**
...
@@ -169,5 +171,14 @@ public class ImClientController extends BaseController {
...
@@ -169,5 +171,14 @@ public class ImClientController extends BaseController {
return
ApiResult
.
ok
(
imOnlineStatusVos
);
return
ApiResult
.
ok
(
imOnlineStatusVos
);
}
}
@PostMapping
(
"/registerClient"
)
@ApiOperation
(
value
=
"注册客户端"
)
ApiResult
<
RegisterClientResponse
>
registerClient
(
@RequestBody
RegisterClientParam
param
)
{
Long
clientId
=
imClientService
.
registerClient
(
param
);
RegisterClientResponse
response
=
new
RegisterClientResponse
();
response
.
setUserId
(
clientId
);
return
ApiResult
.
ok
(
response
);
}
}
}
core/src/main/java/com/wecloud/im/param/RegisterClientParam.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
param
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
javax.validation.constraints.NotNull
;
/**
* 注册客户端入参
* @Author luozh
* @Date 2022年04月13日 17:16
* @Version 1.0
*/
@Data
public
class
RegisterClientParam
{
/**
* appKey
*/
@NotNull
(
message
=
"appKey 不能为空"
)
@ApiModelProperty
(
"appKey"
)
private
String
appKey
;
/**
* app 用户id
*/
@NotNull
(
message
=
"用户id 不能为空"
)
@ApiModelProperty
(
"用户id"
)
private
Long
userId
;
/**
* 头像
*/
@ApiModelProperty
(
"头像"
)
private
String
headPortrait
;
/**
* 昵称
*/
@ApiModelProperty
(
"昵称"
)
private
String
nickname
;
/**
* 设备类型
*/
@NotNull
(
message
=
"设备类型 不能为空"
)
@ApiModelProperty
(
"设备类型"
)
private
Integer
deviceType
;
}
core/src/main/java/com/wecloud/im/service/ImClientService.java
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
service
;
package
com
.
wecloud
.
im
.
service
;
import
io.geekidea.springbootplus.framework.common.api.ApiResult
;
import
io.geekidea.springbootplus.framework.common.service.BaseService
;
import
io.geekidea.springbootplus.framework.common.service.BaseService
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
io.geekidea.springbootplus.framework.core.pagination.Paging
;
import
java.util.List
;
import
java.util.List
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.im.entity.ImClient
;
import
com.wecloud.im.entity.ImClient
;
import
com.wecloud.im.param.ClientInfoParam
;
import
com.wecloud.im.param.ClientInfoParam
;
import
com.wecloud.im.param.GetClientInfoParam
;
import
com.wecloud.im.param.GetClientInfoParam
;
...
@@ -14,6 +12,7 @@ import com.wecloud.im.param.ImClientPageParam;
...
@@ -14,6 +12,7 @@ import com.wecloud.im.param.ImClientPageParam;
import
com.wecloud.im.param.ImClientQueryVo
;
import
com.wecloud.im.param.ImClientQueryVo
;
import
com.wecloud.im.param.ImClientSimpleDto
;
import
com.wecloud.im.param.ImClientSimpleDto
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.RegisterClientParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
...
@@ -155,4 +154,13 @@ public interface ImClientService extends BaseService<ImClient> {
...
@@ -155,4 +154,13 @@ public interface ImClientService extends BaseService<ImClient> {
List
<
ImClientSimpleDto
>
getSimpleClients
(
Long
applicationId
,
List
<
String
>
clientIds
);
List
<
ImClientSimpleDto
>
getSimpleClients
(
Long
applicationId
,
List
<
String
>
clientIds
);
List
<
ImClientSimpleDto
>
getSimpleClients
(
List
<
Long
>
ids
);
List
<
ImClientSimpleDto
>
getSimpleClients
(
List
<
Long
>
ids
);
/**
* 注册客户端
* @Author luozh
* @Date 2022年04月13日 05:20:58
* @param param
* @Return
*/
Long
registerClient
(
RegisterClientParam
param
);
}
}
core/src/main/java/com/wecloud/im/service/impl/ImClientServiceImpl.java
View file @
b15cc7cd
...
@@ -40,6 +40,7 @@ import com.wecloud.im.param.ImClientPageParam;
...
@@ -40,6 +40,7 @@ import com.wecloud.im.param.ImClientPageParam;
import
com.wecloud.im.param.ImClientQueryVo
;
import
com.wecloud.im.param.ImClientQueryVo
;
import
com.wecloud.im.param.ImClientSimpleDto
;
import
com.wecloud.im.param.ImClientSimpleDto
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.LogoutParam
;
import
com.wecloud.im.param.RegisterClientParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ClientDeviceUpdateParam
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAdd
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
import
com.wecloud.im.param.add.ImClientHeadPortraitAndNicknameUpdate
;
...
@@ -322,4 +323,34 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
...
@@ -322,4 +323,34 @@ public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClien
return
imClientMapper
.
getSimpleClientsByIds
(
ids
);
return
imClientMapper
.
getSimpleClientsByIds
(
ids
);
}
}
@Override
public
Long
registerClient
(
RegisterClientParam
param
)
{
ImApplication
imApplication
=
imApplicationService
.
getCacheAppByAppKey
(
param
.
getAppKey
());
// 判断client是否存在
ImClient
imClient
=
getOne
(
new
QueryWrapper
<
ImClient
>().
lambda
()
.
eq
(
ImClient:
:
getFkAppid
,
imApplication
.
getId
())
.
eq
(
ImClient:
:
getClientId
,
param
.
getUserId
()));
if
(
imClient
==
null
)
{
imClient
=
new
ImClient
();
imClient
.
setId
(
SnowflakeUtil
.
getId
());
imClient
.
setFkAppid
(
imApplication
.
getId
());
imClient
.
setClientId
(
param
.
getUserId
().
toString
());
imClient
.
setHeadPortrait
(
param
.
getHeadPortrait
());
imClient
.
setNickname
(
param
.
getNickname
());
save
(
imClient
);
ImClientDevice
imClientDevice
=
new
ImClientDevice
();
imClientDevice
.
setId
(
SnowflakeUtil
.
getId
());
imClientDevice
.
setFkAppid
(
imApplication
.
getId
());
imClientDevice
.
setFkClientId
(
imClient
.
getId
());
imClientDevice
.
setValid
(
1
);
imClientDevice
.
setDeviceType
(
param
.
getDeviceType
());
imClientDevice
.
setCreateTime
(
new
Date
());
imClientDevice
.
setUpdateTime
(
new
Date
());
imClientDeviceService
.
save
(
imClientDevice
);
}
return
imClient
.
getId
();
}
}
}
core/src/main/java/com/wecloud/im/vo/RegisterClientResponse.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
vo
;
import
lombok.Data
;
/**
*
* @Author luozh
* @Date 2022年04月13日 17:14
* @Version 1.0
*/
@Data
public
class
RegisterClientResponse
{
private
static
final
long
serialVersionUID
=
1L
;
private
Long
userId
;
}
im-sdk/pom.xml
View file @
b15cc7cd
...
@@ -31,15 +31,22 @@
...
@@ -31,15 +31,22 @@
<dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<artifactId>
fastjson
</artifactId>
<version>
1.2.
67
</version>
<version>
1.2.
80
</version>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<artifactId>
lombok
</artifactId>
<version>
1.18.
16
</version>
<version>
1.18.
22
</version>
<scope>
compile
</scope>
<scope>
compile
</scope>
</dependency>
</dependency>
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
5.7.22
</version>
</dependency>
</dependencies>
</dependencies>
...
...
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudIm.java
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
;
package
com
.
wecloud
.
im
.
sdk
;
import
com.wecloud.im.sdk.model.GetSignParam
;
import
com.wecloud.im.sdk.model.ImClient
;
import
com.wecloud.im.sdk.model.ImClient
;
import
com.wecloud.im.sdk.model.ImFriend
;
import
com.wecloud.im.sdk.model.ImTokenVerify
;
import
com.wecloud.im.sdk.model.Token
;
/**
/**
*
*
...
@@ -13,17 +9,18 @@ import com.wecloud.im.sdk.model.Token;
...
@@ -13,17 +9,18 @@ import com.wecloud.im.sdk.model.Token;
* @Version 1.0
* @Version 1.0
*/
*/
public
interface
WecloudIm
{
public
interface
WecloudIm
{
String
sign
(
GetSignParam
paramGetSignParam
);
Token
token
(
ImTokenVerify
paramImTokenVerify
);
/**
* 注册客户端
* @Author luozh
* @Date 2022年04月13日 04:25:52
* @param userId
* @param headPortrait
* @param nickname
* @param deviceType
* @Return
* @return
*/
ImClient
registerClient
(
Long
userId
,
String
headPortrait
,
String
nickname
,
Integer
deviceType
);
ImClient
getUserClient
(
Long
paramLong
);
Boolean
createClient
(
Long
paramLong
,
String
paramString1
,
String
paramString2
,
Integer
paramInteger
);
ImFriend
getFriendInfo
(
Long
paramLong1
,
Long
paramLong2
);
Boolean
updateHeadPortrait
(
Long
paramLong
,
String
paramString
);
Boolean
updateNickname
(
Long
paramLong
,
String
paramString
);
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudImClient.java
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
;
package
com
.
wecloud
.
im
.
sdk
;
import
java.net.UR
I
;
import
java.net.UR
L
;
import
com.wecloud.im.sdk.
model.GetSignParam
;
import
com.wecloud.im.sdk.
internal.WecloudImClientOperation
;
import
com.wecloud.im.sdk.model.ImClient
;
import
com.wecloud.im.sdk.model.ImClient
;
import
com.wecloud.im.sdk.model.ImFriend
;
import
com.wecloud.im.sdk.model.RegisterClientRequest
;
import
com.wecloud.im.sdk.model.ImTokenVerify
;
import
com.wecloud.im.sdk.model.Token
;
/**
/**
*
*
...
@@ -16,50 +14,42 @@ import com.wecloud.im.sdk.model.Token;
...
@@ -16,50 +14,42 @@ import com.wecloud.im.sdk.model.Token;
*/
*/
public
class
WecloudImClient
implements
WecloudIm
{
public
class
WecloudImClient
implements
WecloudIm
{
private
URI
endpoint
;
/**
* 请求地址
*/
private
URL
apiDomain
;
/**
* 蔚可云分配后台分配的appKey
*/
private
String
appKey
;
private
String
appKey
;
/**
* 蔚可云分配后台分配的appSecret
*/
private
String
appSecret
;
private
String
appSecret
;
public
WecloudImClient
(
URI
endpoint
,
String
appKey
,
String
appSecret
)
{
/* The miscellaneous OSS operations */
this
.
endpoint
=
endpoint
;
private
WecloudImClientOperation
imClientOperation
;
public
WecloudImClient
(
URL
apiDomain
,
String
appKey
,
String
appSecret
)
{
this
.
apiDomain
=
apiDomain
;
this
.
appKey
=
appKey
;
this
.
appKey
=
appKey
;
this
.
appSecret
=
appSecret
;
this
.
appSecret
=
appSecret
;
initOperations
();
}
}
@Override
@Override
public
String
sign
(
GetSignParam
signParam
)
{
public
ImClient
registerClient
(
Long
userId
,
String
headPortrait
,
String
nickname
,
Integer
deviceType
)
{
return
null
;
RegisterClientRequest
registerClientRequest
=
RegisterClientRequest
.
builder
()
.
userId
(
userId
).
headPortrait
(
headPortrait
)
.
nickname
(
nickname
).
deviceType
(
deviceType
)
.
build
();
return
imClientOperation
.
registerClient
(
registerClientRequest
);
}
}
@Override
private
void
initOperations
()
{
public
Token
token
(
ImTokenVerify
tokenVerify
)
{
this
.
imClientOperation
=
new
WecloudImClientOperation
(
apiDomain
,
appKey
,
appSecret
);
return
null
;
}
@Override
public
ImClient
getUserClient
(
Long
userId
)
{
return
null
;
}
@Override
public
Boolean
createClient
(
Long
userId
,
String
headPortrait
,
String
nickname
,
Integer
deviceType
)
{
return
null
;
}
@Override
public
ImFriend
getFriendInfo
(
Long
clientId
,
Long
userId
)
{
return
null
;
}
@Override
public
Boolean
updateHeadPortrait
(
Long
clientId
,
String
headPortrait
)
{
return
null
;
}
@Override
public
Boolean
updateNickname
(
Long
clientId
,
String
nickname
)
{
return
null
;
}
}
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/WecloudImClientBuilder.java
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
;
package
com
.
wecloud
.
im
.
sdk
;
import
java.net.
URI
;
import
java.net.
MalformedURLException
;
import
java.net.UR
ISyntaxException
;
import
java.net.UR
L
;
public
class
WecloudImClientBuilder
{
public
class
WecloudImClientBuilder
{
public
WecloudIm
build
(
String
endpoint
,
String
appKey
,
String
appSecret
)
{
public
WecloudIm
build
(
String
endpoint
,
String
appKey
,
String
appSecret
)
{
try
{
try
{
UR
I
uri
=
new
URI
(
endpoint
);
UR
L
uri
=
new
URL
(
endpoint
);
return
new
WecloudImClient
(
uri
,
appKey
,
appSecret
);
return
new
WecloudImClient
(
uri
,
appKey
,
appSecret
);
}
catch
(
URISyntax
Exception
e
)
{
}
catch
(
MalformedURL
Exception
e
)
{
throw
new
IllegalArgumentException
(
e
);
throw
new
IllegalArgumentException
(
e
);
}
}
}
}
...
...
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpClient.java
View file @
b15cc7cd
...
@@ -10,6 +10,7 @@ import okhttp3.RequestBody;
...
@@ -10,6 +10,7 @@ import okhttp3.RequestBody;
import
okhttp3.Response
;
import
okhttp3.Response
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.net.URLEncoder
;
import
java.net.URLEncoder
;
import
java.security.SecureRandom
;
import
java.security.SecureRandom
;
import
java.security.cert.X509Certificate
;
import
java.security.cert.X509Certificate
;
...
@@ -24,6 +25,7 @@ import javax.net.ssl.TrustManager;
...
@@ -24,6 +25,7 @@ import javax.net.ssl.TrustManager;
import
javax.net.ssl.X509TrustManager
;
import
javax.net.ssl.X509TrustManager
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSON
;
import
com.wecloud.im.sdk.exception.WecloudException
;
/**
/**
*
*
...
@@ -37,7 +39,7 @@ public class HttpClient {
...
@@ -37,7 +39,7 @@ public class HttpClient {
private
static
volatile
Semaphore
semaphore
=
null
;
private
static
volatile
Semaphore
semaphore
=
null
;
private
Map
<
String
,
String
>
headerMap
;
private
Map
<
String
,
String
>
headerMap
;
private
Map
<
String
,
String
>
paramMap
;
private
Map
<
String
,
String
>
paramMap
;
private
String
url
;
private
URL
url
;
private
Request
.
Builder
request
;
private
Request
.
Builder
request
;
/**
/**
...
@@ -92,7 +94,7 @@ public class HttpClient {
...
@@ -92,7 +94,7 @@ public class HttpClient {
* @param url
* @param url
* @return
* @return
*/
*/
public
HttpClient
url
(
String
url
)
{
public
HttpClient
url
(
URL
url
)
{
this
.
url
=
url
;
this
.
url
=
url
;
return
this
;
return
this
;
}
}
...
@@ -113,6 +115,21 @@ public class HttpClient {
...
@@ -113,6 +115,21 @@ public class HttpClient {
}
}
/**
/**
* 添加参数
* @Author luozh
* @Date 2022年04月13日 03:14:34
* @param params
* @Return
*/
public
HttpClient
addParams
(
Map
<
String
,
String
>
params
)
{
if
(
paramMap
==
null
)
{
paramMap
=
new
LinkedHashMap
<>(
16
);
}
paramMap
.
putAll
(
params
);
return
this
;
}
/**
* 添加请求头
* 添加请求头
*
*
* @param key 参数名
* @param key 参数名
...
@@ -127,6 +144,14 @@ public class HttpClient {
...
@@ -127,6 +144,14 @@ public class HttpClient {
return
this
;
return
this
;
}
}
public
HttpClient
addHeaders
(
Map
<
String
,
String
>
headers
)
{
if
(
headerMap
==
null
)
{
headerMap
=
new
LinkedHashMap
<>(
16
);
}
headerMap
.
putAll
(
headers
);
return
this
;
}
/**
/**
* 初始化get方法
* 初始化get方法
*
*
...
@@ -134,7 +159,7 @@ public class HttpClient {
...
@@ -134,7 +159,7 @@ public class HttpClient {
*/
*/
public
HttpClient
get
()
{
public
HttpClient
get
()
{
request
=
new
Request
.
Builder
().
get
();
request
=
new
Request
.
Builder
().
get
();
StringBuilder
urlBuilder
=
new
StringBuilder
(
url
);
StringBuilder
urlBuilder
=
new
StringBuilder
(
url
.
toString
()
);
if
(
paramMap
!=
null
)
{
if
(
paramMap
!=
null
)
{
urlBuilder
.
append
(
"?"
);
urlBuilder
.
append
(
"?"
);
try
{
try
{
...
@@ -184,15 +209,13 @@ public class HttpClient {
...
@@ -184,15 +209,13 @@ public class HttpClient {
*
*
* @return
* @return
*/
*/
public
String
sync
()
{
public
Response
sync
()
{
setHeader
(
request
);
setHeader
(
request
);
try
{
try
{
Response
response
=
okHttpClient
.
newCall
(
request
.
build
()).
execute
();
assert
response
.
body
()
!=
null
;
return
okHttpClient
.
newCall
(
request
.
build
()).
execute
();
return
response
.
body
().
string
();
}
catch
(
Exception
e
)
{
}
catch
(
IOException
e
)
{
throw
new
WecloudException
(
"请求失败:"
+
e
.
getMessage
());
e
.
printStackTrace
();
return
"请求失败:"
+
e
.
getMessage
();
}
}
}
}
...
@@ -218,7 +241,7 @@ public class HttpClient {
...
@@ -218,7 +241,7 @@ public class HttpClient {
try
{
try
{
getSemaphoreInstance
().
acquire
();
getSemaphoreInstance
().
acquire
();
}
catch
(
InterruptedException
e
)
{
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
(
);
throw
new
WecloudException
(
"请求失败:"
+
e
.
getMessage
()
);
}
}
return
buffer
.
toString
();
return
buffer
.
toString
();
}
}
...
@@ -274,7 +297,7 @@ public class HttpClient {
...
@@ -274,7 +297,7 @@ public class HttpClient {
sc
.
init
(
null
,
trustAllCerts
,
new
SecureRandom
());
sc
.
init
(
null
,
trustAllCerts
,
new
SecureRandom
());
ssfFactory
=
sc
.
getSocketFactory
();
ssfFactory
=
sc
.
getSocketFactory
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
throw
new
WecloudException
(
"请求失败:"
+
e
.
getMessage
()
);
}
}
return
ssfFactory
;
return
ssfFactory
;
}
}
...
...
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpMesssage.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
common
;
import
java.util.Map
;
import
java.util.TreeMap
;
/**
* Common class for both HTTP request and HTTP response.
*/
public
abstract
class
HttpMesssage
{
protected
Map
<
String
,
String
>
headers
=
new
TreeMap
<>(
String
.
CASE_INSENSITIVE_ORDER
);
;
public
Map
<
String
,
String
>
getHeaders
()
{
return
headers
;
}
public
void
setHeaders
(
Map
<
String
,
String
>
headers
)
{
this
.
headers
=
headers
;
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/common/HttpMethod.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
common
;
/**
* Http Methods
* @Author luozh
* @Date 2022年04月13日 14:13
* @Version 1.0
*/
public
enum
HttpMethod
{
/**
* HTTP DELETE.
*/
DELETE
,
/**
* HTTP GET
*/
GET
,
/**
* HTTP HEAD
*/
HEAD
,
/**
* HTTP POST
*/
POST
,
/**
* HTTP PUT
*/
PUT
,
/**
* HTTP OPTION
*/
OPTIONS
}
im-sdk/src/main/java/com/wecloud/im/sdk/common/RequestMessage.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
common
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
com.wecloud.im.sdk.model.WebServiceRequest
;
/**
* Represent HTTP requests sent to wecloud im PAAS.
*/
public
class
RequestMessage
extends
HttpMesssage
{
/**
* The service endpoint to which this request should be sent
*/
private
String
endpoint
;
/**
* client id
*/
private
String
clientId
;
/**
* 平台
*/
private
String
platform
;
/**
* The HTTP method to use when sending this request
*/
private
HttpMethod
method
=
HttpMethod
.
GET
;
/**
* Use a LinkedHashMap to preserve the insertion order.
*/
private
Map
<
String
,
String
>
parameters
=
new
LinkedHashMap
<
String
,
String
>();
/**
* The original request provided by user
*/
private
final
WebServiceRequest
originalRequest
;
public
RequestMessage
(
WebServiceRequest
originalRequest
)
{
this
.
originalRequest
=
(
originalRequest
==
null
)
?
WebServiceRequest
.
NOOP
:
originalRequest
;
}
public
void
addHeader
(
String
key
,
String
value
)
{
this
.
headers
.
put
(
key
,
value
);
}
public
String
getEndpoint
()
{
return
endpoint
;
}
public
void
setEndpoint
(
String
endpoint
)
{
this
.
endpoint
=
endpoint
;
}
public
HttpMethod
getMethod
()
{
return
method
;
}
public
void
setMethod
(
HttpMethod
method
)
{
this
.
method
=
method
;
}
public
WebServiceRequest
getOriginalRequest
()
{
return
originalRequest
;
}
public
String
getClientId
()
{
return
clientId
;
}
public
void
setClientId
(
String
clientId
)
{
this
.
clientId
=
clientId
;
}
public
String
getPlatform
()
{
return
platform
;
}
public
void
setPlatform
(
String
platform
)
{
this
.
platform
=
platform
;
}
public
Map
<
String
,
String
>
getParameters
()
{
return
parameters
;
}
public
void
setParameters
(
Map
<
String
,
String
>
parameters
)
{
this
.
parameters
.
clear
();
if
(
parameters
!=
null
&&
!
parameters
.
isEmpty
())
{
this
.
parameters
.
putAll
(
parameters
);
}
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/common/RequestParamSigner.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
common
;
import
cn.hutool.crypto.digest.MD5
;
/**
* 请求参数签名
* @Author luozh
* @Date 2022年04月13日 14:24
* @Version 1.0
*/
public
class
RequestParamSigner
{
/**
* 签名
* @Author luozh
* @Date 2022年04月13日 02:33:18
* @param timestamp 时间戳
* @param clientId client客户端id
* @param appKey appKey
* @param appSecret 密钥
* @param platform 客户端平台: 1 web, 2 安卓, 3 ios, 4 pc-win, 5 pc-macOs
* @Return
*/
public
static
String
sign
(
String
timestamp
,
String
clientId
,
String
appKey
,
String
appSecret
,
String
platform
)
{
return
new
MD5
().
digestHex
(
timestamp
+
clientId
+
appKey
+
appSecret
+
platform
);
}
/**
* qiangming
* @Author luozh
* @Date 2022年04月13日 02:33:30
* @param clientId client客户端id
* @param appKey appKey
* @param appSecret 密钥
* @param platform 客户端平台: 1 web, 2 安卓, 3 ios, 4 pc-win, 5 pc-macOs
* @Return
*/
public
static
String
sign
(
String
clientId
,
String
appKey
,
String
appSecret
,
String
platform
)
{
long
timestamp
=
System
.
currentTimeMillis
();
return
new
MD5
().
digestHex
(
timestamp
+
""
+
clientId
+
appKey
+
appSecret
+
platform
);
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/exception/WecloudException.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
exception
;
/**
*
* @Author luozh
* @Date 2022年04月13日 16:48
* @Version 1.0
*/
public
class
WecloudException
extends
RuntimeException
{
/**
* 错误提示
*/
private
String
message
;
public
WecloudException
(
String
message
)
{
super
(
message
);
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/internal/OSSRequestMessageBuilder.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
internal
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
com.wecloud.im.sdk.common.HttpMethod
;
import
com.wecloud.im.sdk.common.RequestMessage
;
import
com.wecloud.im.sdk.model.WebServiceRequest
;
/**
* HTTP request message builder.
* @Author luozh
* @Date 2022年04月13日 15:49
* @Version 1.0
*/
public
class
OSSRequestMessageBuilder
{
private
String
endpoint
;
private
HttpMethod
method
=
HttpMethod
.
GET
;
private
Map
<
String
,
String
>
headers
=
new
HashMap
<
String
,
String
>();
private
Map
<
String
,
String
>
parameters
=
new
LinkedHashMap
<
String
,
String
>();
private
WebServiceRequest
originalRequest
;
public
String
getEndpoint
()
{
return
endpoint
;
}
public
OSSRequestMessageBuilder
setEndpoint
(
String
endpoint
)
{
this
.
endpoint
=
endpoint
;
return
this
;
}
public
HttpMethod
getMethod
()
{
return
method
;
}
public
OSSRequestMessageBuilder
setMethod
(
HttpMethod
method
)
{
this
.
method
=
method
;
return
this
;
}
public
Map
<
String
,
String
>
getHeaders
()
{
return
Collections
.
unmodifiableMap
(
headers
);
}
public
OSSRequestMessageBuilder
setHeaders
(
Map
<
String
,
String
>
headers
)
{
this
.
headers
=
headers
;
return
this
;
}
public
OSSRequestMessageBuilder
addHeader
(
String
key
,
String
value
)
{
headers
.
put
(
key
,
value
);
return
this
;
}
public
Map
<
String
,
String
>
getParameters
()
{
return
Collections
.
unmodifiableMap
(
parameters
);
}
public
OSSRequestMessageBuilder
setParameters
(
Map
<
String
,
String
>
parameters
)
{
this
.
parameters
=
parameters
;
return
this
;
}
public
OSSRequestMessageBuilder
addParameter
(
String
key
,
String
value
)
{
parameters
.
put
(
key
,
value
);
return
this
;
}
public
WebServiceRequest
getOriginalRequest
()
{
return
originalRequest
;
}
public
OSSRequestMessageBuilder
setOriginalRequest
(
WebServiceRequest
originalRequest
)
{
this
.
originalRequest
=
originalRequest
;
return
this
;
}
public
RequestMessage
build
()
{
Map
<
String
,
String
>
sentHeaders
=
new
HashMap
<
String
,
String
>(
this
.
headers
);
Map
<
String
,
String
>
sentParameters
=
new
LinkedHashMap
<
String
,
String
>(
this
.
parameters
);
Date
now
=
new
Date
();
sentHeaders
.
put
(
WecloudHeaders
.
DATE
,
System
.
currentTimeMillis
()
+
""
);
RequestMessage
request
=
new
RequestMessage
(
this
.
originalRequest
);
request
.
setEndpoint
(
endpoint
);
request
.
setHeaders
(
sentHeaders
);
request
.
setParameters
(
sentParameters
);
request
.
setMethod
(
this
.
method
);
return
request
;
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudHeaders.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
internal
;
import
com.wecloud.im.sdk.utils.HttpHeaders
;
/**
*
* @Author luozh
* @Date 2022年04月13日 14:39
* @Version 1.0
*/
public
interface
WecloudHeaders
extends
HttpHeaders
{
static
final
String
WECLOUD_SIGN
=
"x-wecloud-sign"
;
}
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudImClientOperation.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
internal
;
import
java.net.URL
;
import
java.util.HashMap
;
import
java.util.Map
;
import
com.wecloud.im.sdk.common.ApiResult
;
import
com.wecloud.im.sdk.common.HttpMethod
;
import
com.wecloud.im.sdk.common.RequestMessage
;
import
com.wecloud.im.sdk.model.ImClient
;
import
com.wecloud.im.sdk.model.RegisterClientRequest
;
import
static
com
.
wecloud
.
im
.
sdk
.
utils
.
CodingUtils
.
assertParameterNotNull
;
/**
* client
* @Author luozh
* @Date 2022年04月13日 15:26
* @Version 1.0
*/
public
class
WecloudImClientOperation
extends
WecloudImOperation
{
public
WecloudImClientOperation
(
URL
apiDomain
,
String
appKey
,
String
appSecret
)
{
super
(
apiDomain
,
appKey
,
appSecret
);
}
/**
* 注册客户端
* @Author luozh
* @Date 2022年04月13日 03:38:58
* @param registerClientRequest
* @Return
*/
public
ImClient
registerClient
(
RegisterClientRequest
registerClientRequest
)
{
Long
userId
=
registerClientRequest
.
getUserId
();
// 参数校验
assertParameterNotNull
(
userId
,
"userId"
);
// 校验通过 构建参数
Map
<
String
,
String
>
param
=
new
HashMap
<>();
param
.
put
(
"appKey"
,
appKey
);
param
.
put
(
"userId"
,
registerClientRequest
.
getUserId
()
+
""
);
param
.
put
(
"headPortrait"
,
registerClientRequest
.
getHeadPortrait
());
param
.
put
(
"nickname"
,
registerClientRequest
.
getNickname
());
param
.
put
(
"deviceType"
,
registerClientRequest
.
getDeviceType
()
+
""
);
// 发送请求
RequestMessage
request
=
new
OSSRequestMessageBuilder
().
setEndpoint
(
"/api/imClient/registerClient"
)
.
setMethod
(
HttpMethod
.
POST
).
setParameters
(
param
)
.
setOriginalRequest
(
registerClientRequest
).
build
();
ApiResult
<
ImClient
>
result
=
doOperation
(
request
);
return
result
.
getData
();
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/internal/WecloudImOperation.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
internal
;
import
okhttp3.Response
;
import
java.net.URL
;
import
java.util.HashMap
;
import
java.util.Map
;
import
cn.hutool.core.bean.BeanUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.TypeReference
;
import
com.wecloud.im.sdk.common.ApiResult
;
import
com.wecloud.im.sdk.common.HttpClient
;
import
com.wecloud.im.sdk.common.HttpMethod
;
import
com.wecloud.im.sdk.common.RequestMessage
;
import
com.wecloud.im.sdk.common.RequestParamSigner
;
import
com.wecloud.im.sdk.exception.WecloudException
;
/**
*
* @Author luozh
* @Date 2022年04月13日 13:47
* @Version 1.0
*/
public
abstract
class
WecloudImOperation
{
protected
URL
apiDomain
;
protected
String
appKey
;
protected
String
appSecret
;
public
WecloudImOperation
(
URL
apiDomain
,
String
appKey
,
String
appSecret
)
{
this
.
apiDomain
=
apiDomain
;
this
.
appKey
=
appKey
;
this
.
appSecret
=
appSecret
;
}
protected
<
T
>
ApiResult
<
T
>
doOperation
(
RequestMessage
request
)
{
// 请求头签名
String
signature
=
RequestParamSigner
.
sign
(
request
.
getClientId
(),
request
.
getClientId
(),
this
.
appKey
,
this
.
appSecret
,
request
.
getPlatform
());
request
.
addHeader
(
WecloudHeaders
.
WECLOUD_SIGN
,
signature
);
return
send
(
request
);
}
@SuppressWarnings
(
"unchecked"
)
private
<
T
>
ApiResult
<
T
>
send
(
RequestMessage
request
)
{
try
{
// 组装请求
Map
<
String
,
Object
>
parameters
=
BeanUtil
.
beanToMap
(
request
.
getOriginalRequest
(),
false
,
true
);
Map
<
String
,
String
>
finalParameters
=
new
HashMap
<>();
parameters
.
forEach
((
k
,
v
)
->
{
finalParameters
.
put
(
k
,
v
.
toString
());
});
URL
endpoint
=
new
URL
(
apiDomain
,
request
.
getEndpoint
());
HttpClient
httpClient
=
HttpClient
.
builder
().
url
(
endpoint
).
addHeaders
(
request
.
getHeaders
()).
addParams
(
request
.
getParameters
()).
addParams
(
finalParameters
);
if
(
HttpMethod
.
POST
.
equals
(
request
.
getMethod
()))
{
httpClient
.
post
(
true
);
}
else
{
httpClient
.
get
();
}
Response
response
=
httpClient
.
sync
();
if
(!
Integer
.
valueOf
(
200
).
equals
(
response
.
code
()))
{
throw
new
RuntimeException
(
"请求报错: "
+
response
.
code
());
}
assert
response
.
body
()
!=
null
;
String
responseBody
=
response
.
body
().
toString
();
// 泛型的反序列化
TypeReference
typeRef
=
new
TypeReference
<
ApiResult
<
T
>>()
{
};
return
(
ApiResult
<
T
>)
JSON
.
parseObject
(
responseBody
,
typeRef
);
}
catch
(
Exception
e
)
{
throw
new
WecloudException
(
"发送请求报错: "
+
e
.
getMessage
());
}
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/model/GetSignParam.java
deleted
100644 → 0
View file @
4ee85807
package
com
.
wecloud
.
im
.
sdk
.
model
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* sign
*
* @author wei
* @since 2021-04-29
*/
@Data
public
class
GetSignParam
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
timestamp
;
private
String
clientId
;
private
String
appKey
;
private
Integer
platform
;
private
String
appSecret
;
}
im-sdk/src/main/java/com/wecloud/im/sdk/model/ImClient.java
View file @
b15cc7cd
...
@@ -2,34 +2,15 @@ package com.wecloud.im.sdk.model;
...
@@ -2,34 +2,15 @@ package com.wecloud.im.sdk.model;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.Date
;
/**
/**
* 终端
表
* 终端
*
*
@Author luozh
* @
author wei
* @
Date 2022年04月13日 03:33:47
* @
since 2021-04-27
* @
Version 1.0
*/
*/
@Data
@Data
public
class
ImClient
{
public
class
ImClient
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
final
long
serialVersionUID
=
1L
;
private
Long
id
;
private
Long
userId
;
private
Date
createTime
;
private
Date
lastOfflineTime
;
private
Date
updateTime
;
private
Long
fkAppid
;
private
String
attributes
;
private
String
clientId
;
private
String
headPortrait
;
private
String
nickname
;
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/model/RegisterClientRequest.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
model
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
/**
* 创建client 请求参数
* @Author luozh
* @Date 2022年04月13日 15:28
* @Version 1.0
*/
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@Builder
public
class
RegisterClientRequest
extends
WebServiceRequest
{
/**
* app 用户id
*/
private
Long
userId
;
/**
* 头像
*/
private
String
headPortrait
;
/**
* 昵称
*/
private
String
nickname
;
/**
* 设备类型
*/
private
Integer
deviceType
;
}
im-sdk/src/main/java/com/wecloud/im/sdk/model/WebServiceRequest.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
model
;
import
lombok.Data
;
/**
*
* @Author luozh
* @Date 2022年04月13日 13:59
* @Version 1.0
*/
@Data
public
abstract
class
WebServiceRequest
{
public
static
final
WebServiceRequest
NOOP
=
new
WebServiceRequest
()
{
};
/**
* 预留版本号id
*/
private
String
versionId
;
}
im-sdk/src/main/java/com/wecloud/im/sdk/sample/RegisterClientSample.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
sample
;
import
com.alibaba.fastjson.JSONObject
;
import
com.wecloud.im.sdk.WecloudIm
;
import
com.wecloud.im.sdk.WecloudImClientBuilder
;
import
com.wecloud.im.sdk.model.ImClient
;
/**
*
* @Author luozh
* @Date 2022年04月13日 16:32
* @Version 1.0
*/
public
class
RegisterClientSample
{
public
static
void
main
(
String
[]
args
)
{
WecloudIm
im
=
new
WecloudImClientBuilder
().
build
(
"http://127.0.0.1:8082"
,
"QizKVHcILRWp6Td2"
,
"287d04828099fb7de871e9dda845fa8b6b2302faf2ab3737"
);
Long
userId
=
20220413001L
;
String
headPortrait
=
""
;
String
nickname
=
"luo_test1"
;
Integer
deviceType
=
1
;
ImClient
imClient
=
im
.
registerClient
(
userId
,
headPortrait
,
nickname
,
deviceType
);
System
.
out
.
println
(
"\tregister client result="
+
JSONObject
.
toJSONString
(
imClient
));
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/utils/CodingUtils.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
utils
;
/**
*
* @Author luozh
* @Date 2022年04月13日 15:43
* @Version 1.0
*/
public
class
CodingUtils
{
public
static
void
assertParameterNotNull
(
Object
param
,
String
paramName
)
{
if
(
param
==
null
)
{
throw
new
NullPointerException
(
"参数:"
+
paramName
+
" 不能为空"
);
}
}
}
im-sdk/src/main/java/com/wecloud/im/sdk/utils/HttpHeaders.java
0 → 100644
View file @
b15cc7cd
package
com
.
wecloud
.
im
.
sdk
.
utils
;
/**
* A collection of common HTTP headers.
* @Author luozh
* @Date 2022年04月13日 14:40
* @Version 1.0
*/
public
interface
HttpHeaders
{
public
static
final
String
AUTHORIZATION
=
"Authorization"
;
public
static
final
String
CACHE_CONTROL
=
"Cache-Control"
;
public
static
final
String
CONTENT_DISPOSITION
=
"Content-Disposition"
;
public
static
final
String
CONTENT_ENCODING
=
"Content-Encoding"
;
public
static
final
String
CONTENT_LENGTH
=
"Content-Length"
;
public
static
final
String
CONTENT_MD5
=
"Content-MD5"
;
public
static
final
String
CONTENT_TYPE
=
"Content-Type"
;
public
static
final
String
TRANSFER_ENCODING
=
"Transfer-Encoding"
;
public
static
final
String
DATE
=
"Date"
;
public
static
final
String
ETAG
=
"ETag"
;
public
static
final
String
EXPIRES
=
"Expires"
;
public
static
final
String
HOST
=
"Host"
;
public
static
final
String
LAST_MODIFIED
=
"Last-Modified"
;
public
static
final
String
RANGE
=
"Range"
;
public
static
final
String
LOCATION
=
"Location"
;
public
static
final
String
CONNECTION
=
"Connection"
;
}
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