package com.zchd.zim; import com.zchd.base.BaseService; import com.zchd.base.util.Kv; import com.zchd.zim.bean.ImBean; import com.zchd.zim.bean.SubscribeBean; import com.zchd.zim.entity.AppInfo; import com.zchd.zim.entity.ChannelUser; import com.zchd.zim.entity.ImUser; import net.tccn.zhub.Lock; import net.tccn.zhub.RpcResult; import org.redkale.convert.json.JsonConvert; import org.redkale.net.http.RestMapping; import org.redkale.net.http.RestService; import org.redkale.service.RetResult; import org.redkale.source.ColumnValue; import org.redkale.source.FilterBean; import org.redkale.source.FilterNode; import org.redkale.source.Flipper; import org.redkale.util.AnyValue; import org.redkale.util.Comment; import org.redkale.util.TypeToken; import org.redkale.util.Utility; import org.redkalex.cache.redis.MyRedisCacheSource; import javax.annotation.Resource; import java.io.Serializable; import java.util.List; import java.util.concurrent.CompletableFuture; @RestService(name = "im_account", comment = "账号服务") public class ImAccountService extends BaseService { @Resource(name = "str_cache") protected MyRedisCacheSource strCache; @Resource protected ImMessageMonitor messageMonitor; /*@Resource protected ImAccountService accountService;*/ @Override public void init(AnyValue config) { CompletableFuture.runAsync(() -> { List list = zimSource.queryColumnList("userid", ImUser.class, new Flipper(1, "userid DESC"), (FilterBean) null); int userid = 10000; if (!list.isEmpty()) { userid = Kv.toAs(list.get(0), int.class); } intCache.set("im:max-userid", userid); }); // 游戏用户注册 zhub.rpcSubscribe("im:account-register", new TypeToken() { }, r -> { ImBean bean = r.getValue(); RetResult result = register(bean); if (!result.isSuccess()) { return r.retError(result.getRetinfo()); } return r.render(result.getResult()); }); // 获取游戏用户 IM-TOKEN zhub.rpcSubscribe("im:account-token", new TypeToken() { }, r -> { ImBean bean = r.getValue(); RetResult result = getToken(bean); if (!result.isSuccess()) { return r.retError(result.getRetinfo()); } return r.render(result.getResult()); }); // 为用户新增订阅频道 zhub.rpcSubscribe("im:subscribe", new TypeToken() { }, r -> { SubscribeBean bean = r.getValue(); RetResult result = subscribe(bean); return r.render(result.getResult()); }); // 为用户取消订阅频道 zhub.rpcSubscribe("im:unsubscribe", new TypeToken() { }, r -> { SubscribeBean bean = r.getValue(); RetResult result = unsubscribe(bean); return r.render(result.getResult()); }); // 禁言 todo: ①禁言时长 ②禁言指定频道 zhub.rpcSubscribe("im:banned-talk", new TypeToken() { }, r -> { SubscribeBean bean = r.getValue(); String imtoken = bean.getImtoken(); ImUser user = currentImUser(imtoken); int userid = user.getUserid(); zimSource.updateColumn(ImUser.class, userid, ColumnValue.create("status", ImUser.STATUS_FREEZE_ACTIVE)); intCache.setBit("im:banned-talk", userid, true); return r.render(); }); // 取消禁言 zhub.rpcSubscribe("im:unbanned-talk", new TypeToken() { }, r -> { SubscribeBean bean = r.getValue(); String imtoken = bean.getImtoken(); ImUser user = currentImUser(imtoken); int userid = user.getUserid(); zimSource.updateColumn(ImUser.class, userid, ColumnValue.create("status", 10)); intCache.setBit("im:banned-talk", userid, false); return r.render(); }); } @Comment("获取当前用户ID") public ImUser currentImUser(String token) { ImUser user = strCache.hget("im:user-token", token, new TypeToken() { }.getType()); if (user == null) { user = zimSource.find(ImUser.class, FilterNode.create("imtoken", token)); strCache.hset("im:user-token", token, JsonConvert.root(), user); } return user; } public ImUser getImUser(ImBean bean) { return zimSource.find(ImUser.class, FilterNode.create("guserid", bean.getGuserid()).and("appid", bean.getAppid())); } /*@Comment("获取当前用户ID") public int currentImUserId(String token) { return currentImUser(token).getUserid(); }*/ /* Url: http://127.0.0.1:8021/im_account/register Body: {"appid":"krlq07sx","appsecret":"79eb45ebdabc4d90bfb69949b8fd767e","guserid":"S_C_01_R0001","gender":10,"nickname":"M","face":"http://xxxxxx/xxx"} Body: {"appid":"krlq07sx","appsecret":"79eb45ebdabc4d90bfb69949b8fd767e","guserid":"S_C_01_R0002","gender":20,"nickname":"V","face":"http://xxxxxx/xxx"} */ @RestMapping(name = "register", auth = false, comment = "获取当前登录用户ID") public RetResult register(ImBean bean) { RetResult result = check(bean); if (!result.isSuccess()) { return result; } // 检查有无当前用户 FilterNode node = FilterNode.create("guserid", bean.getGuserid()).and("appid", bean.getAppid()); ImUser user = zimSource.find(ImUser.class, node); if (user == null) { user = ImUser.buildImUser(bean.getGuserid(), bean.getAppid()); int userid = (int) intCache.incr("im:max-userid"); user.setUserid(userid); user.setImtoken(Utility.uuid()); // 生成IM-TOKEN zimSource.insert(user); // intCache.set("im:account-user-token:" + user.getImtoken(), userid); strCache.hset("im:user-token", user.getImtoken(), JsonConvert.root(), user); } return RetResult.success(Kv.of("token", user.getImtoken())); } /* Url: http://127.0.0.1:8021/im_account/register Body: {"appid":"krlq07sx","appsecret":"79eb45ebdabc4d90bfb69949b8fd767e","guserid":"S_C_01_R0001"} Body: {"appid":"krlq07sx","appsecret":"79eb45ebdabc4d90bfb69949b8fd767e","guserid":"S_C_01_R0002"} */ @RestMapping(name = "get_token", auth = false, comment = "获取平台识别Token") public RetResult getToken(ImBean bean) { RetResult result = check(bean); if (!result.isSuccess()) { return result; } FilterNode node = FilterNode.create("appid", bean.getAppid()).and("guserid", bean.getGuserid()); Serializable imtoken = zimSource.findColumn(ImUser.class, "imtoken", node); return RetResult.success(Kv.of("token", imtoken)); } /* Url: http://127.0.0.1:8021/im_app/subscribe Body: {"imtoken":"krlq07sxS_C_01_R00011627473704040","channeltype":"Word","channelvalue":"W_C_01_001"} Body: {"imtoken":"krlq07sxS_C_01_R00021627474715105","channeltype":"Word","channelvalue":"W_C_01_001"} */ @RestMapping(name = "subscribe", auth = false, comment = "给用户订阅频道信息") public RetResult subscribe(SubscribeBean bean) { ImUser user = currentImUser(bean.getImtoken()); int userid = user.getUserid(); Lock lock = zhub.lock("im:channel-create:" + userid, 500); try { // 添加数据库订阅关系 FilterNode node1 = FilterNode.create("appid", user.getAppid()) .and("channeltype", bean.getChanneltype()) .and("channelvalue", bean.getChannelvalue()) .and("userid", userid); if (!zimSource.exists(ChannelUser.class, node1)) { ChannelUser record = ChannelUser.buildChannelUser(userid, user.getAppid(), bean); zimSource.insert(record); // 确保写入库后,再发送订阅事件 messageMonitor.subscribeChannel(userid, record.buildChannelid(), true); } } finally { lock.unLock(); } return RET_SUCCESS; } /* Url: http://127.0.0.1:8021/im_app/unsubscribe Body: {"imtoken":"krlq07sxS_C_01_R00011627473704040","channeltype":"Word","channelvalue":"W_C_01_001"} Body: {"imtoken":"krlq07sxS_C_01_R00021627474715105","channeltype":"Word","channelvalue":"W_C_01_001"} */ @RestMapping(name = "unsubscribe", auth = false, comment = "取消频道订阅") public RetResult unsubscribe(SubscribeBean bean) { ImUser user = currentImUser(bean.getImtoken()); int userid = user.getUserid(); String channelid = user.getAppid() + "-" + bean.getChanneltype() + "-" + bean.getChannelvalue(); messageMonitor.subscribeChannel(userid, channelid, false); // 删除数据库订阅关系 FilterNode node1 = FilterNode.create("appid", user.getAppid()) .and("channeltype", bean.getChanneltype()) .and("channelvalue", bean.getChannelvalue()) .and("userid", userid); zimSource.delete(ChannelUser.class, node1); return RET_SUCCESS; } @Comment("平台安全校验") public RetResult check(ImBean bean) { FilterNode node = FilterNode.create("appid", bean.getAppid()).and("appsecret", bean.getAppsecret()).and("status", 10); if (!zimSource.exists(AppInfo.class, node)) { return retError("平台信息校验失败"); } return RET_SUCCESS; } // ---------------------------------- 测试 ---------------------------------- @RestMapping(name = "test_account_register", auth = false, comment = "rpc测试") public RpcResult testAccountRegister(ImBean bean) { return zhub.rpc("im:account-register", bean); } @RestMapping(name = "test_account_token", auth = false, comment = "rpc测试") public RpcResult testAccountToken(ImBean bean) { return zhub.rpc("im:account-token", bean); } @RestMapping(name = "test_subscribe", auth = false, comment = "rpc测试") public RpcResult testSubscribe(SubscribeBean bean) { return zhub.rpc("im:subscribe", bean); } @RestMapping(name = "test_unsubscribe", auth = false, comment = "rpc测试") public RpcResult testUnsubscribe(SubscribeBean bean) { return zhub.rpc("im:unsubscribe", bean); } }