feat: support visitor channel

This commit is contained in:
tt
2025-05-08 10:42:08 +08:00
parent 1c65c5e565
commit 0b06408691
5 changed files with 43 additions and 7 deletions

View File

@@ -111,4 +111,8 @@ conversation: # 最近会话配置
# socketPath: "./wukongimdata/1/wukongim.sock" # 插件unix socket通讯地址
# install: # 默认安装的插件列表 安装最新版本 ${os}: 当前操作系统 ${arch}: 当前操作系统架构。github地址替换https://github.com/WuKongIM/plugins
# - "https://gitee.com/WuKongDev/plugins/releases/download/latest/wk.plugin.ai-example-${os}-${arch}.wkp"
# - "https://gitee.com/WuKongDev/plugins/releases/download/latest/wk.plugin.ai-volcengine-${os}-${arch}.wkp"
# - "https://gitee.com/WuKongDev/plugins/releases/download/latest/wk.plugin.ai-volcengine-${os}-${arch}.wkp"
# customerService:
# visitorsOn: false # 是否开启访客用户访问
# visitorsSuffix: "____vstr" # 访客用户后缀 (带有此后缀的用户将被认为是访客用户访客用户登录免去token验证但是只能给访客频道发送消息)

View File

@@ -17,6 +17,8 @@ demo:
on: true
conversation:
on: true
webhook: # webhook配置 用于接收消息通知事件,详情请查看文档
httpAddr: "http://127.0.0.1:8080/webhooks/wukongim"
cluster:
nodeId: 1 # 节点ID
addr: "tcp://127.0.0.1:10001"
@@ -36,7 +38,6 @@ jwt: ## jwt认证方式
secret: "xxxxx" # jwt密钥
expire: 30d # jwt过期时间
plugin:
install: # 默认安装的插件列表 安装最新版本 ${os}: 当前操作系统 ${arch}: 当前操作系统架构。github地址替换https://github.com/WuKongIM/plugins
# - "https://gitee.com/WuKongDev/plugins/releases/download/latest/wk.plugin.ai-example-${os}-${arch}.wkp"
# - "https://gitee.com/WuKongDev/plugins/releases/download/latest/wk.plugin.ai-volcengine-${os}-${arch}.wkp"
customerService: # 客服配置
visitorsOn: true # 是否开启访客用户访问
visitorsSuffix: "____vstr" # 访客用户后缀 (带有此后缀的用户将被认为是访客用户访客用户登录免去token验证但是只能给访客频道发送消息)

View File

@@ -59,7 +59,7 @@ func (h *Handler) hasPermissionForChannel(channelId string, channelType uint8) (
return wkproto.ReasonSuccess, nil
}
// 客服频道,直接通过
if channelType == wkproto.ChannelTypeCustomerService {
if channelType == wkproto.ChannelTypeCustomerService || channelType == wkproto.ChannelTypeVisitors {
return wkproto.ReasonSuccess, nil
}
@@ -112,6 +112,14 @@ func (h *Handler) hasPermissionForSender(channelId string, channelType uint8, e
return wkproto.ReasonSuccess, nil
}
}
// 访客频道只有自己和客服可以发消息
if channelType == wkproto.ChannelTypeVisitors {
// 因为访客频道的id就是访客的uid所以这里发送者是自己直接通过
// 否则需要走普通频道的流程:判断是否是订阅者,白名单,黑名单这些
if fromUid == channelId {
return wkproto.ReasonSuccess, nil
}
}
// 系统发的消息直接通过
if options.G.IsSystemDevice(e.Conn.DeviceId) {

View File

@@ -71,6 +71,13 @@ type Options struct {
KeyFile string // 私钥文件
}
// 客服相关配置
CustomerService struct {
VisitorsOn bool // 是否开启访客用户
VisitorsSuffix string // 访客用户的后缀(带有此后缀的用户将被认为是访客用户访客用户登录免去token验证但是只能给访客频道发送消息)
}
Logger struct {
Dir string // 日志存储目录
Level zapcore.Level
@@ -349,6 +356,13 @@ func New(op ...Option) *Options {
SystemDeviceId: "____device",
WhitelistOffOfPerson: true,
DeadlockCheck: false,
CustomerService: struct {
VisitorsOn bool
VisitorsSuffix string
}{
VisitorsOn: false,
VisitorsSuffix: "____vstr",
},
Logger: struct {
Dir string
Level zapcore.Level
@@ -768,6 +782,10 @@ func (o *Options) ConfigureWithViper(vp *viper.Viper) {
o.WSSConfig.CertFile = o.getString("wssConfig.certFile", o.WSSConfig.CertFile)
o.WSSConfig.KeyFile = o.getString("wssConfig.keyFile", o.WSSConfig.KeyFile)
// 客服
o.CustomerService.VisitorsOn = o.getBool("customerService.visitorsOn", o.CustomerService.VisitorsOn)
o.CustomerService.VisitorsSuffix = o.getString("customerService.visitorsSuffix", o.CustomerService.VisitorsSuffix)
// 频道
o.Channel.CacheCount = o.getInt("channel.cacheCount", o.Channel.CacheCount)
o.Channel.CreateIfNoExist = o.getBool("channel.createIfNoExist", o.Channel.CreateIfNoExist)
o.Channel.SubscriberCompressOfCount = o.getInt("channel.subscriberCompressOfCount", o.Channel.SubscriberCompressOfCount)
@@ -1248,6 +1266,11 @@ func (o *Options) IsSystemUid(uid string) bool {
return uid == o.SystemUID
}
// IsVisitors 是否是访客
func (o *Options) IsVisitors(uid string) bool {
return strings.HasSuffix(uid, o.CustomerService.VisitorsSuffix)
}
func (o *Options) ConfigFileUsed() string {
if o.vp == nil {
return ""

View File

@@ -74,7 +74,7 @@ func (h *Handler) handleConnect(event *eventbus.Event) (wkproto.ReasonCode, *wkp
return wkproto.ReasonAuthFail, nil, nil
}
devceLevel = wkproto.DeviceLevelSlave // 默认都是slave设备
} else if options.G.TokenAuthOn {
} else if options.G.TokenAuthOn && !options.G.IsVisitors(uid) { // 如果开启了token验证并且不是访客用户
if connectPacket.Token == "" {
h.Error("token is empty")
return wkproto.ReasonAuthFail, nil, errors.New("token is empty")