Commit f78fded7 authored by shiyu's avatar shiyu

音频安全内容检测

parent 6654f4ea
package com.wwdz.ch.db.domain;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import com.xxdxxs.entity.Entity;
import lombok.Data;
/**
* @author shiyu
* @date 2023/09/28
* @date 2023/10/31
*/
@Data
public class User implements Serializable {
public class User implements Entity {
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database table user
......@@ -95,10 +96,14 @@ public class User implements Serializable {
/**
* 微信登录openid
* 存的是unionid
*/
private String weixinOpenid;
/**
* 微信登录unionid
*/
private String weixinUnionid;
/**
* 支付宝user_id
*/
......@@ -153,6 +158,7 @@ public class User implements Serializable {
sb.append(", profile=").append(profile);
sb.append(", background=").append(background);
sb.append(", weixinOpenid=").append(weixinOpenid);
sb.append(", weixinUnionid=").append(weixinUnionid);
sb.append(", alipayUserId=").append(alipayUserId);
sb.append(", wechatId=").append(wechatId);
sb.append(", status=").append(status);
......@@ -191,6 +197,7 @@ public class User implements Serializable {
&& (this.getProfile() == null ? other.getProfile() == null : this.getProfile().equals(other.getProfile()))
&& (this.getBackground() == null ? other.getBackground() == null : this.getBackground().equals(other.getBackground()))
&& (this.getWeixinOpenid() == null ? other.getWeixinOpenid() == null : this.getWeixinOpenid().equals(other.getWeixinOpenid()))
&& (this.getWeixinUnionid() == null ? other.getWeixinUnionid() == null : this.getWeixinUnionid().equals(other.getWeixinUnionid()))
&& (this.getAlipayUserId() == null ? other.getAlipayUserId() == null : this.getAlipayUserId().equals(other.getAlipayUserId()))
&& (this.getWechatId() == null ? other.getWechatId() == null : this.getWechatId().equals(other.getWechatId()))
&& (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
......@@ -218,6 +225,7 @@ public class User implements Serializable {
result = prime * result + ((getProfile() == null) ? 0 : getProfile().hashCode());
result = prime * result + ((getBackground() == null) ? 0 : getBackground().hashCode());
result = prime * result + ((getWeixinOpenid() == null) ? 0 : getWeixinOpenid().hashCode());
result = prime * result + ((getWeixinUnionid() == null) ? 0 : getWeixinUnionid().hashCode());
result = prime * result + ((getAlipayUserId() == null) ? 0 : getAlipayUserId().hashCode());
result = prime * result + ((getWechatId() == null) ? 0 : getWechatId().hashCode());
result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
......@@ -261,6 +269,7 @@ public class User implements Serializable {
profile("profile", "profile", "VARCHAR", false),
background("background", "background", "VARCHAR", false),
weixinOpenid("weixin_openid", "weixinOpenid", "VARCHAR", false),
weixinUnionid("weixin_unionid", "weixinUnionid", "VARCHAR", false),
alipayUserId("alipay_user_id", "alipayUserId", "VARCHAR", false),
wechatId("wechat_id", "wechatId", "VARCHAR", false),
status("status", "status", "TINYINT", true),
......
......@@ -2113,6 +2113,148 @@ public class UserExample {
return (Criteria) this;
}
public Criteria andWeixinUnionidIsNull() {
addCriterion("weixin_unionid is null");
return (Criteria) this;
}
public Criteria andWeixinUnionidIsNotNull() {
addCriterion("weixin_unionid is not null");
return (Criteria) this;
}
public Criteria andWeixinUnionidEqualTo(String value) {
addCriterion("weixin_unionid =", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidEqualToColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid = ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidNotEqualTo(String value) {
addCriterion("weixin_unionid <>", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidNotEqualToColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid <> ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidGreaterThan(String value) {
addCriterion("weixin_unionid >", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidGreaterThanColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid > ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidGreaterThanOrEqualTo(String value) {
addCriterion("weixin_unionid >=", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidGreaterThanOrEqualToColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid >= ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidLessThan(String value) {
addCriterion("weixin_unionid <", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidLessThanColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid < ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidLessThanOrEqualTo(String value) {
addCriterion("weixin_unionid <=", value, "weixinUnionid");
return (Criteria) this;
}
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table user
*
* @mbg.generated
* @project https://github.com/itfsw/mybatis-generator-plugin
*/
public Criteria andWeixinUnionidLessThanOrEqualToColumn(User.Column column) {
addCriterion(new StringBuilder("weixin_unionid <= ").append(column.getEscapedColumnName()).toString());
return (Criteria) this;
}
public Criteria andWeixinUnionidLike(String value) {
addCriterion("weixin_unionid like", value, "weixinUnionid");
return (Criteria) this;
}
public Criteria andWeixinUnionidNotLike(String value) {
addCriterion("weixin_unionid not like", value, "weixinUnionid");
return (Criteria) this;
}
public Criteria andWeixinUnionidIn(List<String> values) {
addCriterion("weixin_unionid in", values, "weixinUnionid");
return (Criteria) this;
}
public Criteria andWeixinUnionidNotIn(List<String> values) {
addCriterion("weixin_unionid not in", values, "weixinUnionid");
return (Criteria) this;
}
public Criteria andWeixinUnionidBetween(String value1, String value2) {
addCriterion("weixin_unionid between", value1, value2, "weixinUnionid");
return (Criteria) this;
}
public Criteria andWeixinUnionidNotBetween(String value1, String value2) {
addCriterion("weixin_unionid not between", value1, value2, "weixinUnionid");
return (Criteria) this;
}
public Criteria andAlipayUserIdIsNull() {
addCriterion("alipay_user_id is null");
return (Criteria) this;
......
......@@ -15,7 +15,7 @@ public interface UserMapper {
int deleteByPrimaryKey(Long id);
int insert(User record);
long insert(User record);
int insertSelective(User record);
......
......@@ -16,6 +16,7 @@
<result column="profile" jdbcType="VARCHAR" property="profile" />
<result column="background" jdbcType="VARCHAR" property="background" />
<result column="weixin_openid" jdbcType="VARCHAR" property="weixinOpenid" />
<result column="weixin_unionid" jdbcType="VARCHAR" property="weixinUnionid" />
<result column="alipay_user_id" jdbcType="VARCHAR" property="alipayUserId" />
<result column="wechat_id" jdbcType="VARCHAR" property="wechatId" />
<result column="status" jdbcType="TINYINT" property="status" />
......@@ -84,8 +85,8 @@
</sql>
<sql id="Base_Column_List">
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, profile, background, weixin_openid, alipay_user_id, wechat_id,
`status`, add_time, update_time, deleted, share_user_id
nickname, mobile, avatar, profile, background, weixin_openid, weixin_unionid, alipay_user_id,
wechat_id, `status`, add_time, update_time, deleted, share_user_id
</sql>
<select id="selectByExample" parameterType="com.wwdz.ch.db.domain.UserExample" resultMap="BaseResultMap">
select
......@@ -121,8 +122,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, profile, background, weixin_openid, alipay_user_id, wechat_id,
`status`, add_time, update_time, deleted, share_user_id
nickname, mobile, avatar, profile, background, weixin_openid, weixin_unionid, alipay_user_id,
wechat_id, `status`, add_time, update_time, deleted, share_user_id
</otherwise>
</choose>
from user
......@@ -174,8 +175,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, profile, background, weixin_openid, alipay_user_id, wechat_id,
`status`, add_time, update_time, deleted, share_user_id
nickname, mobile, avatar, profile, background, weixin_openid, weixin_unionid, alipay_user_id,
wechat_id, `status`, add_time, update_time, deleted, share_user_id
</otherwise>
</choose>
from user
......@@ -199,16 +200,18 @@
birthday, last_login_time, last_login_ip,
user_level, nickname, mobile,
avatar, profile, background,
weixin_openid, alipay_user_id, wechat_id,
`status`, add_time, update_time,
deleted, share_user_id)
weixin_openid, weixin_unionid, alipay_user_id,
wechat_id, `status`, add_time,
update_time, deleted, share_user_id
)
values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{gender,jdbcType=TINYINT},
#{birthday,jdbcType=DATE}, #{lastLoginTime,jdbcType=TIMESTAMP}, #{lastLoginIp,jdbcType=VARCHAR},
#{userLevel,jdbcType=TINYINT}, #{nickname,jdbcType=VARCHAR}, #{mobile,jdbcType=VARCHAR},
#{avatar,jdbcType=VARCHAR}, #{profile,jdbcType=VARCHAR}, #{background,jdbcType=VARCHAR},
#{weixinOpenid,jdbcType=VARCHAR}, #{alipayUserId,jdbcType=VARCHAR}, #{wechatId,jdbcType=VARCHAR},
#{status,jdbcType=TINYINT}, #{addTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP},
#{deleted,jdbcType=BIT}, #{shareUserId,jdbcType=BIGINT})
#{weixinOpenid,jdbcType=VARCHAR}, #{weixinUnionid,jdbcType=VARCHAR}, #{alipayUserId,jdbcType=VARCHAR},
#{wechatId,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT}, #{addTime,jdbcType=TIMESTAMP},
#{updateTime,jdbcType=TIMESTAMP}, #{deleted,jdbcType=BIT}, #{shareUserId,jdbcType=BIGINT}
)
</insert>
<insert id="insertSelective" parameterType="com.wwdz.ch.db.domain.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
......@@ -255,6 +258,9 @@
<if test="weixinOpenid != null">
weixin_openid,
</if>
<if test="weixinUnionid != null">
weixin_unionid,
</if>
<if test="alipayUserId != null">
alipay_user_id,
</if>
......@@ -317,6 +323,9 @@
<if test="weixinOpenid != null">
#{weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="weixinUnionid != null">
#{weixinUnionid,jdbcType=VARCHAR},
</if>
<if test="alipayUserId != null">
#{alipayUserId,jdbcType=VARCHAR},
</if>
......@@ -391,6 +400,9 @@
<if test="record.weixinOpenid != null">
weixin_openid = #{record.weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="record.weixinUnionid != null">
weixin_unionid = #{record.weixinUnionid,jdbcType=VARCHAR},
</if>
<if test="record.alipayUserId != null">
alipay_user_id = #{record.alipayUserId,jdbcType=VARCHAR},
</if>
......@@ -433,6 +445,7 @@
profile = #{record.profile,jdbcType=VARCHAR},
background = #{record.background,jdbcType=VARCHAR},
weixin_openid = #{record.weixinOpenid,jdbcType=VARCHAR},
weixin_unionid = #{record.weixinUnionid,jdbcType=VARCHAR},
alipay_user_id = #{record.alipayUserId,jdbcType=VARCHAR},
wechat_id = #{record.wechatId,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=TINYINT},
......@@ -486,6 +499,9 @@
<if test="weixinOpenid != null">
weixin_openid = #{weixinOpenid,jdbcType=VARCHAR},
</if>
<if test="weixinUnionid != null">
weixin_unionid = #{weixinUnionid,jdbcType=VARCHAR},
</if>
<if test="alipayUserId != null">
alipay_user_id = #{alipayUserId,jdbcType=VARCHAR},
</if>
......@@ -525,6 +541,7 @@
profile = #{profile,jdbcType=VARCHAR},
background = #{background,jdbcType=VARCHAR},
weixin_openid = #{weixinOpenid,jdbcType=VARCHAR},
weixin_unionid = #{weixinUnionid,jdbcType=VARCHAR},
alipay_user_id = #{alipayUserId,jdbcType=VARCHAR},
wechat_id = #{wechatId,jdbcType=VARCHAR},
`status` = #{status,jdbcType=TINYINT},
......@@ -568,8 +585,8 @@
</when>
<otherwise>
id, username, `password`, gender, birthday, last_login_time, last_login_ip, user_level,
nickname, mobile, avatar, profile, background, weixin_openid, alipay_user_id, wechat_id,
`status`, add_time, update_time, deleted, share_user_id
nickname, mobile, avatar, profile, background, weixin_openid, weixin_unionid, alipay_user_id,
wechat_id, `status`, add_time, update_time, deleted, share_user_id
</otherwise>
</choose>
from user
......@@ -601,4 +618,5 @@
update user set deleted = 1
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>
\ No newline at end of file
package com.wwdz.ch.wx.api;
import com.wwdz.ch.core.util.OkHttpUtil;
import com.wwdz.ch.wx.entity.request.WxCheckMediaRequestDto;
import com.wwdz.ch.wx.manager.WxLoginManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.xml.ws.soap.Addressing;
import java.util.HashMap;
import java.util.Map;
@Component
public class WxAppletApi {
private static final Logger logger = LoggerFactory.getLogger(WxAppletApi.class);
@Value("${dts.wx.app-id}")
private String APPLET_APPID;
@Value("${dts.wx.app-secret}")
private String APPLET_APP_SECRET;
@Autowired
WxLoginManager wxLoginManager;
// 微信小程序音视频内容安全识别地址
private static final String MEDIA_CHECK_URL = "https://api.weixin.qq.com/wxa/media_check_async?access_token=%s";
public String checkMedia(WxCheckMediaRequestDto dto) {
String accessToken = wxLoginManager.getAccessToken();
String url = String.format(MEDIA_CHECK_URL, accessToken);
OkHttpUtil okHttpUtil = OkHttpUtil.builder().url(url);
Map<String, Object> map = new HashMap<>();
map.put("media_url", dto.getMediaUrl());
map.put("media_type", dto.getMediaType());
map.put("version", 2);
map.put("scene", 4);
map.put("openid", dto.getWxOpenId());
okHttpUtil.addParams(map);
okHttpUtil.post(true);
String responseStr = okHttpUtil.async();
logger.info("[chatWithModel] response :{}", responseStr);
return responseStr;
}
}
......@@ -43,6 +43,9 @@ public class UserRequestDto implements Entity {
private Integer loginType;
// 微信openid
private String wxOpenId;
private String wxUnionid;
// 支付宝user_id
private String alipayUserId;
}
package com.wwdz.ch.wx.entity.request;
import com.xxdxxs.entity.Entity;
import lombok.Data;
@Data
public class WxCheckMediaRequestDto implements Entity {
private Long userId;
private String wxOpenId;
private Integer mediaType;
private String mediaUrl;
}
......@@ -18,11 +18,13 @@ import com.wwdz.ch.db.dto.request.EsSearchRequestDto;
import com.wwdz.ch.db.dto.request.FollowFansRecordRequestDto;
import com.wwdz.ch.db.es.ItemEsDao;
import com.wwdz.ch.wx.api.OfficialAccountApi;
import com.wwdz.ch.wx.api.WxAppletApi;
import com.wwdz.ch.wx.constant.CacheCodeConstants;
import com.wwdz.ch.wx.constant.LoginTypeEnum;
import com.wwdz.ch.wx.entity.MessageContentText;
import com.wwdz.ch.wx.entity.request.ItemRequestDto;
import com.wwdz.ch.wx.entity.request.MessageRequestDto;
import com.wwdz.ch.wx.entity.request.WxCheckMediaRequestDto;
import com.wwdz.ch.wx.entity.vo.AgentTranceResponseVo;
import com.wwdz.ch.wx.entity.vo.ItemResponseVo;
import com.wwdz.ch.wx.manager.AlipayLoginManager;
......@@ -137,6 +139,9 @@ public class ItemServiceImpl implements ItemService {
@Autowired
OfficialAccountSubscribeRecordDao officialAccountSubscribeRecordDao;
@Autowired
WxAppletApi wxAppletApi;
@Override
public Result nameList(ItemRequestDto dto) {
try {
......@@ -576,6 +581,16 @@ public class ItemServiceImpl implements ItemService {
item.setViewPermission(Objects.isNull(dto.getViewPermission()) ? ViewPermissionEnum.ALL.getCode() : dto.getViewPermission());
itemDao.insert(item);
//微信音频内容安全识别
WxCheckMediaRequestDto wxCheckMediaRequestDto = new WxCheckMediaRequestDto();
wxCheckMediaRequestDto.setMediaType(2);
wxCheckMediaRequestDto.setMediaUrl(dto.getImages().split(";")[0]);
//查询用户openid
User user = userDao.queryById(dto.getUserId());
wxCheckMediaRequestDto.setWxOpenId(user.getWeixinOpenid());
wxAppletApi.checkMedia(wxCheckMediaRequestDto);
// 新增用户和藏品关联记录
UserItemsRelation userItemsRelation = new UserItemsRelation();
userItemsRelation.setUserId(dto.getUserId());
......
......@@ -210,7 +210,8 @@ public class UserServiceImpl implements UserService {
if (StringUtils.equals("decryptFalse", mobile)) {
return Result.failed(ResultCode.FAILED.getCode(), "用户信息解密失败");
}
dto.setWxOpenId(wxLoginManager.getWxOpenId(dto.getLoginCode()));
dto.setWxOpenId(wxLoginManager.getWxOpenId(dto.getLoginCode()).getOpenid());
dto.setWxUnionid(wxLoginManager.getWxOpenId(dto.getLoginCode()).getUnionid());
}
// 来源是支付宝
if (dto.getLoginType().equals(LoginTypeEnum.ALIPAY.getCode())) {
......@@ -523,13 +524,14 @@ public class UserServiceImpl implements UserService {
user.setUsername(UUID.randomUUID().toString().replace("-", ""));
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
user.setPassword(bCryptPasswordEncoder.encode("Aa123456"));
user.setWeixinOpenid(dto.getWxOpenId());
user.setWeixinUnionid(dto.getWxOpenId());
user.setProfile("");
user.setBackground("");
user.setWechatId("");
user.setMobile(dto.getMobile());
user.setAvatar(avatarUrl);
user.setWeixinOpenid(dto.getWxOpenId());
user.setWeixinUnionid(dto.getWxUnionid());
user.setAlipayUserId(dto.getAlipayUserId());
while (true) {
String nickname = "收藏家" + StringUtil.generateRandomString(10);
......@@ -568,7 +570,7 @@ public class UserServiceImpl implements UserService {
} else {
// 注册过的用户修改最后登录的时间以及绑定微信openid和支付宝user_id
if (org.springframework.util.StringUtils.hasLength(dto.getWxOpenId())) {
user.setWeixinOpenid(dto.getWxOpenId());
user.setWeixinUnionid(dto.getWxOpenId());
}
if (org.springframework.util.StringUtils.hasLength(dto.getAlipayUserId())) {
user.setAlipayUserId(dto.getAlipayUserId());
......
......@@ -6,6 +6,7 @@ import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSON;
import com.wwdz.ch.core.util.OkHttpUtil;
import com.wwdz.ch.core.util.RedisUtils;
import com.wwdz.ch.db.domain.User;
import com.wwdz.ch.wx.entity.request.UserRequestDto;
import com.xxdxxs.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
......@@ -47,6 +48,8 @@ public class WxLoginManager {
// 微信小程序获取短链接地址
private static final String GET_LINK_URL = "https://api.weixin.qq.com/wxa/genwxashortlink?access_token=%s";
@Autowired
private WxMaService wxMaService;
......@@ -59,19 +62,18 @@ public class WxLoginManager {
* @param loginCode
* @return
*/
public String getWxOpenId(String loginCode) {
String openId = "";
public WxMaJscode2SessionResult getWxOpenId(String loginCode) {
WxMaJscode2SessionResult result = null;
try {
logger.info(">>>>>>>>> 获取微信openid, 参数loginCode:{}", loginCode);
WxMaJscode2SessionResult result = this.wxMaService.getUserService().getSessionInfo(loginCode);
result = this.wxMaService.getUserService().getSessionInfo(loginCode);
//实际获取的是unionid,为了和公众号订阅用户关联
openId = result.getUnionid();
logger.info("获取WxMaJscode2SessionResult :{}", result);
logger.info("loginCode:{},获取openId成功 unionid :{}", loginCode, openId);
logger.info("loginCode:{},获取openId成功 unionid :{}, openid:{}", loginCode, result.getUnionid(), result.getOpenid());
} catch (Exception e) {
logger.error("loginCode:{}, 获取微信登录用户的openId失败:{}", loginCode, e);
}
return openId;
return result;
}
/**
......
......@@ -40,7 +40,7 @@ public class OfficialAccountController {
Result<User> result = userService.queryUserInfo(dto);
String openid = null;
if (result.getSuccess() && result.getData() != null) {
openid = result.getData().getWeixinOpenid();
openid = result.getData().getWeixinUnionid();
}
if (openid == null) {
return Result.failed("该用户没有记录下openid");
......
......@@ -51,7 +51,7 @@ public class WxUserFormId {
User user = dtsUserDao.findById(userId);
UserFormidObsolete userFormid = new UserFormidObsolete();
userFormid.setOpenid(user.getWeixinOpenid());
userFormid.setOpenid(user.getWeixinUnionid());
userFormid.setFormid(formId);
userFormid.setIsprepay(false);
userFormid.setUseamount(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment