feat(jpush): add vendor-specific message classification support for push notifications
- Add OPPO category/notify_level support (2024.11.20 regulation: category required when notify_level present) - Add Honor importance field (NORMAL=service/LOW=marketing) for notification classification - Add vivo category field (IM/ACCOUNT) for message scenario identification - Set Xiaomi channel/template defaults in code (system=153609, chat=153608, templates P10761/M10289) - Add classification option to JPush push payloads (0=operation, 1=system) - Update xiaomi template keywords mapping to match actual template placeholders - Add keyword search support for GetFollowers and GetFollowing endpoints - Bind new config fields to environment variables for OPPO/Honor/vivo
This commit is contained in:
84
internal/pkg/jpush/vendor/converters.go
vendored
84
internal/pkg/jpush/vendor/converters.go
vendored
@@ -39,12 +39,32 @@ func (huaweiConverter) Convert(params MessageParams, cfg config.ChannelConfig) m
|
||||
return channelOnlyMap(params.Scene, cfg.Vendor.Huawei.System, cfg.Vendor.Huawei.Chat, cfg.System, cfg.Chat)
|
||||
}
|
||||
|
||||
// vivoConverter VIVO 厂商转换器(仅 channel_id)
|
||||
// vivoConverter VIVO 厂商转换器
|
||||
// channel_id + category(厂商消息场景标识)
|
||||
// classification=1 时 category 必须为系统消息类,不携带 category 会默认按运营消息下发受频控限制
|
||||
type vivoConverter struct{}
|
||||
|
||||
func (vivoConverter) VendorName() string { return "vivo" }
|
||||
func (vivoConverter) Convert(params MessageParams, cfg config.ChannelConfig) map[string]any {
|
||||
return channelOnlyMap(params.Scene, cfg.Vendor.VIVO.System, cfg.Vendor.VIVO.Chat, cfg.System, cfg.Chat)
|
||||
v := cfg.Vendor.VIVO
|
||||
cid := resolveChannelID(params.Scene, v.System, v.Chat, cfg.System, cfg.Chat)
|
||||
category := v.VivoChatCategory
|
||||
if params.Scene == SceneSystem {
|
||||
category = v.VivoSystemCategory
|
||||
}
|
||||
|
||||
if cid == "" && category == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := map[string]any{}
|
||||
if cid != "" {
|
||||
m["channel_id"] = cid
|
||||
}
|
||||
if category != "" {
|
||||
m["category"] = category
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// meizuConverter 魅族厂商转换器(仅 channel_id)
|
||||
@@ -55,12 +75,33 @@ func (meizuConverter) Convert(params MessageParams, cfg config.ChannelConfig) ma
|
||||
return channelOnlyMap(params.Scene, cfg.Vendor.Meizu.System, cfg.Vendor.Meizu.Chat, cfg.System, cfg.Chat)
|
||||
}
|
||||
|
||||
// honorConverter 荣耀厂商转换器(仅 channel_id)
|
||||
// honorConverter 荣耀厂商转换器
|
||||
// channel_id + importance(通知栏消息智能分类)
|
||||
// importance 取值:"NORMAL"=服务与通讯,"LOW"=资讯营销
|
||||
// 注:classification 优先级更高,会覆盖 importance 设置的值
|
||||
type honorConverter struct{}
|
||||
|
||||
func (honorConverter) VendorName() string { return "honor" }
|
||||
func (honorConverter) Convert(params MessageParams, cfg config.ChannelConfig) map[string]any {
|
||||
return channelOnlyMap(params.Scene, cfg.Vendor.Honor.System, cfg.Vendor.Honor.Chat, cfg.System, cfg.Chat)
|
||||
h := cfg.Vendor.Honor
|
||||
cid := resolveChannelID(params.Scene, h.System, h.Chat, cfg.System, cfg.Chat)
|
||||
importance := h.HonorChatImportance
|
||||
if params.Scene == SceneSystem {
|
||||
importance = h.HonorSystemImportance
|
||||
}
|
||||
|
||||
if cid == "" && importance == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := map[string]any{}
|
||||
if cid != "" {
|
||||
m["channel_id"] = cid
|
||||
}
|
||||
if importance != "" {
|
||||
m["importance"] = importance
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// fcmConverter FCM 厂商转换器(仅 channel_id)
|
||||
@@ -104,12 +145,22 @@ func (xiaomiConverter) Convert(params MessageParams, cfg config.ChannelConfig) m
|
||||
}
|
||||
|
||||
// buildMiTemplateParam 生成小米消息模板参数 JSON 字符串
|
||||
// 默认占位符:sender / title / content,可按实际小米模板占位符在集中处调整
|
||||
// 占位符严格匹配小米模板定义的 keywords:
|
||||
// - 私聊模板(M10289 好友聊天): keywords1=title, keywords2=发送者, keywords3=内容
|
||||
// - 系统模板(P10761 系统消息): keywords1=标题, keywords2=内容
|
||||
func buildMiTemplateParam(params MessageParams) string {
|
||||
param := map[string]any{
|
||||
"sender": params.SenderName,
|
||||
"title": params.Title,
|
||||
"content": params.Body,
|
||||
var param map[string]any
|
||||
if params.Scene == SceneSystem {
|
||||
param = map[string]any{
|
||||
"keywords1": params.Title,
|
||||
"keywords2": params.Body,
|
||||
}
|
||||
} else {
|
||||
param = map[string]any{
|
||||
"keywords1": params.Title,
|
||||
"keywords2": params.SenderName,
|
||||
"keywords3": params.Body,
|
||||
}
|
||||
}
|
||||
b, err := json.Marshal(param)
|
||||
if err != nil {
|
||||
@@ -129,11 +180,15 @@ func (oppoConverter) Convert(params MessageParams, cfg config.ChannelConfig) map
|
||||
cid := resolveChannelID(params.Scene, o.System, o.Chat, cfg.System, cfg.Chat)
|
||||
// OPPO 私信模板按场景选择
|
||||
templateID := o.OppoChatPrivateTemplateID
|
||||
category := o.OppoChatCategory
|
||||
notifyLevel := o.OppoChatNotifyLevel
|
||||
if params.Scene == SceneSystem {
|
||||
templateID = o.OppoSystemPrivateTemplateID
|
||||
category = o.OppoSystemCategory
|
||||
notifyLevel = o.OppoSystemNotifyLevel
|
||||
}
|
||||
|
||||
if cid == "" && templateID == "" {
|
||||
if cid == "" && templateID == "" && category == "" && notifyLevel == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -152,5 +207,14 @@ func (oppoConverter) Convert(params MessageParams, cfg config.ChannelConfig) map
|
||||
"sender": params.SenderName,
|
||||
}
|
||||
}
|
||||
// OPPO 2024.11.20 新规:category 消息场景标识,notify_level 提醒等级
|
||||
// 文档约束:使用 notify_level 时 category 必传,否则 OPPO 校验失败
|
||||
// 这里做保护:notify_level 非零但 category 为空时跳过 notify_level
|
||||
if category != "" {
|
||||
m["category"] = category
|
||||
if notifyLevel != 0 {
|
||||
m["notify_level"] = notifyLevel
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user