commit
86bcee514e
@ -0,0 +1,27 @@
|
|||||||
|
.PHONY: all build run gotool install clean help
|
||||||
|
|
||||||
|
BINARY_NAME=open_im_push
|
||||||
|
BIN_DIR=../../bin/
|
||||||
|
LAN_FILE=.go
|
||||||
|
GO_FILE:=${BINARY_NAME}${LAN_FILE}
|
||||||
|
|
||||||
|
all: gotool build
|
||||||
|
|
||||||
|
build:
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o ${BINARY_NAME} ${GO_FILE}
|
||||||
|
|
||||||
|
run:
|
||||||
|
@go run ./
|
||||||
|
|
||||||
|
gotool:
|
||||||
|
go fmt ./
|
||||||
|
go vet ./
|
||||||
|
|
||||||
|
install:
|
||||||
|
make build
|
||||||
|
mv ${BINARY_NAME} ${BIN_DIR}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@if [ -f ${BINARY_NAME} ] ; then rm ${BINARY_NAME} ; fi
|
||||||
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
** description("").
|
||||||
|
** copyright('open-im,www.open-im.io').
|
||||||
|
** author("fg,Gordon@open-im.io").
|
||||||
|
** time(2021/3/22 15:33).
|
||||||
|
*/
|
||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/common/config"
|
||||||
|
"Open_IM/src/common/db"
|
||||||
|
"Open_IM/src/common/db/mysql_model/im_mysql_model"
|
||||||
|
"Open_IM/src/common/kafka"
|
||||||
|
"Open_IM/src/common/log"
|
||||||
|
"Open_IM/src/utils"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rpcServer RPCServer
|
||||||
|
pushCh PushConsumerHandler
|
||||||
|
pushTerminal []int32
|
||||||
|
producer *kafka.Producer
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(rpcPort int) {
|
||||||
|
log.NewPrivateLog(config.Config.ModuleName.PushName)
|
||||||
|
rpcServer.Init(rpcPort)
|
||||||
|
pushCh.Init()
|
||||||
|
pushTerminal = []int32{utils.IOSPlatformID}
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
producer = kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run() {
|
||||||
|
go rpcServer.run()
|
||||||
|
go scheduleDelete()
|
||||||
|
go pushCh.pushConsumerGroup.RegisterHandleAndConsumer(&pushCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func scheduleDelete() {
|
||||||
|
//uid, _ := im_mysql_model.SelectAllUID()
|
||||||
|
//db.DB.DelHistoryChat(0, uid)
|
||||||
|
//log.Info("", "", "sssssssssss")
|
||||||
|
//if err != nil {
|
||||||
|
// db.DB.DelHistoryChat(0, uid)
|
||||||
|
//}
|
||||||
|
|
||||||
|
for {
|
||||||
|
now := time.Now()
|
||||||
|
// 计算下一个零点
|
||||||
|
next := now.Add(time.Hour * 24)
|
||||||
|
next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location())
|
||||||
|
t := time.NewTimer(next.Sub(now))
|
||||||
|
<-t.C
|
||||||
|
|
||||||
|
uid, err := im_mysql_model.SelectAllUID()
|
||||||
|
if err != nil {
|
||||||
|
db.DB.DelHistoryChat(int64(config.Config.Mongo.DBRetainChatRecords), uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
//以下为定时执行的操作
|
||||||
|
scheduleDelete()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
** description("").
|
||||||
|
** copyright('Open_IM,www.Open_IM.io').
|
||||||
|
** author("fg,Gordon@tuoyun.net").
|
||||||
|
** time(2021/5/13 10:33).
|
||||||
|
*/
|
||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/common/config"
|
||||||
|
kfk "Open_IM/src/common/kafka"
|
||||||
|
"Open_IM/src/common/log"
|
||||||
|
pbChat "Open_IM/src/proto/chat"
|
||||||
|
pbRelay "Open_IM/src/proto/relay"
|
||||||
|
"github.com/Shopify/sarama"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fcb func(msg []byte)
|
||||||
|
|
||||||
|
type PushConsumerHandler struct {
|
||||||
|
msgHandle map[string]fcb
|
||||||
|
pushConsumerGroup *kfk.MConsumerGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *PushConsumerHandler) Init() {
|
||||||
|
ms.msgHandle = make(map[string]fcb)
|
||||||
|
ms.msgHandle[config.Config.Kafka.Ms2pschat.Topic] = ms.handleMs2PsChat
|
||||||
|
ms.pushConsumerGroup = kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V0_10_2_0,
|
||||||
|
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.Ms2pschat.Topic}, config.Config.Kafka.Ms2pschat.Addr,
|
||||||
|
config.Config.Kafka.ConsumerGroupID.MsgToPush)
|
||||||
|
}
|
||||||
|
func (ms *PushConsumerHandler) handleMs2PsChat(msg []byte) {
|
||||||
|
log.InfoByKv("msg come from kafka And push!!!", "", "msg", string(msg))
|
||||||
|
pbData := pbChat.MsgSvrToPushSvrChatMsg{}
|
||||||
|
if err := proto.Unmarshal(msg, &pbData); err != nil {
|
||||||
|
log.ErrorByKv("push Unmarshal msg err", "", "msg", string(msg), "err", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sendPbData := pbRelay.MsgToUserReq{}
|
||||||
|
sendPbData.SendTime = pbData.SendTime
|
||||||
|
sendPbData.OperationID = pbData.OperationID
|
||||||
|
sendPbData.ServerMsgID = pbData.MsgID
|
||||||
|
sendPbData.MsgFrom = pbData.MsgFrom
|
||||||
|
sendPbData.ContentType = pbData.ContentType
|
||||||
|
sendPbData.SessionType = pbData.SessionType
|
||||||
|
sendPbData.RecvID = pbData.RecvID
|
||||||
|
sendPbData.Content = pbData.Content
|
||||||
|
sendPbData.SendID = pbData.SendID
|
||||||
|
sendPbData.PlatformID = pbData.PlatformID
|
||||||
|
sendPbData.RecvSeq = pbData.RecvSeq
|
||||||
|
sendPbData.IsEmphasize = pbData.IsEmphasize
|
||||||
|
//Call push module to send message to the user
|
||||||
|
MsgToUser(&sendPbData, pbData.OfflineInfo, pbData.Options)
|
||||||
|
}
|
||||||
|
func (PushConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||||
|
func (PushConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
|
||||||
|
func (ms *PushConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession,
|
||||||
|
claim sarama.ConsumerGroupClaim) error {
|
||||||
|
for msg := range claim.Messages() {
|
||||||
|
log.InfoByKv("kafka get info to mysql", "", "msgTopic", msg.Topic, "msgPartition", msg.Partition, "msg", string(msg.Value))
|
||||||
|
ms.msgHandle[msg.Topic](msg.Value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/common/config"
|
||||||
|
"Open_IM/src/common/log"
|
||||||
|
"Open_IM/src/proto/push"
|
||||||
|
pbRelay "Open_IM/src/proto/relay"
|
||||||
|
"Open_IM/src/utils"
|
||||||
|
"context"
|
||||||
|
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RPCServer struct {
|
||||||
|
rpcPort int
|
||||||
|
rpcRegisterName string
|
||||||
|
etcdSchema string
|
||||||
|
etcdAddr []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RPCServer) Init(rpcPort int) {
|
||||||
|
r.rpcPort = rpcPort
|
||||||
|
r.rpcRegisterName = config.Config.RpcRegisterName.OpenImPushName
|
||||||
|
r.etcdSchema = config.Config.Etcd.EtcdSchema
|
||||||
|
r.etcdAddr = config.Config.Etcd.EtcdAddr
|
||||||
|
}
|
||||||
|
func (r *RPCServer) run() {
|
||||||
|
ip := utils.ServerIP
|
||||||
|
registerAddress := ip + ":" + utils.IntToString(r.rpcPort)
|
||||||
|
listener, err := net.Listen("tcp", registerAddress)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByKv("push module rpc listening port err", "", "err", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
srv := grpc.NewServer()
|
||||||
|
defer srv.GracefulStop()
|
||||||
|
pbPush.RegisterPushMsgServiceServer(srv, r)
|
||||||
|
err = getcdv3.RegisterEtcd(r.etcdSchema, strings.Join(r.etcdAddr, ","), ip, r.rpcPort, r.rpcRegisterName, 10)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByKv("register push module rpc to etcd err", "", "err", err.Error())
|
||||||
|
}
|
||||||
|
err = srv.Serve(listener)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByKv("push module rpc start err", "", "err", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (r *RPCServer) PushMsg(_ context.Context, pbData *pbPush.PushMsgReq) (*pbPush.PushMsgResp, error) {
|
||||||
|
sendPbData := pbRelay.MsgToUserReq{}
|
||||||
|
sendPbData.SendTime = pbData.SendTime
|
||||||
|
sendPbData.OperationID = pbData.OperationID
|
||||||
|
sendPbData.ServerMsgID = pbData.MsgID
|
||||||
|
sendPbData.MsgFrom = pbData.MsgFrom
|
||||||
|
sendPbData.ContentType = pbData.ContentType
|
||||||
|
sendPbData.SessionType = pbData.SessionType
|
||||||
|
sendPbData.RecvID = pbData.RecvID
|
||||||
|
sendPbData.Content = pbData.Content
|
||||||
|
sendPbData.SendID = pbData.SendID
|
||||||
|
sendPbData.PlatformID = pbData.PlatformID
|
||||||
|
sendPbData.RecvSeq = pbData.RecvSeq
|
||||||
|
sendPbData.IsEmphasize = pbData.IsEmphasize
|
||||||
|
//Call push module to send message to the user
|
||||||
|
MsgToUser(&sendPbData, pbData.OfflineInfo, pbData.Options)
|
||||||
|
return &pbPush.PushMsgResp{
|
||||||
|
ResultCode: 0,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
** description("").
|
||||||
|
** copyright('open-im,www.open-im.io').
|
||||||
|
** author("fg,Gordon@open-im.io").
|
||||||
|
** time(2021/3/5 14:31).
|
||||||
|
*/
|
||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/common/config"
|
||||||
|
"Open_IM/src/common/constant"
|
||||||
|
"Open_IM/src/common/log"
|
||||||
|
pbChat "Open_IM/src/proto/chat"
|
||||||
|
pbRelay "Open_IM/src/proto/relay"
|
||||||
|
pbGetInfo "Open_IM/src/proto/user"
|
||||||
|
rpcChat "Open_IM/src/rpc/chat/chat"
|
||||||
|
"Open_IM/src/rpc/user/internal_service"
|
||||||
|
"Open_IM/src/utils"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/skiffer-git/grpc-etcdv3/getcdv3"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EChatContent struct {
|
||||||
|
SessionType int `json:"chatType"`
|
||||||
|
From string `json:"from"`
|
||||||
|
To string `json:"to"`
|
||||||
|
Seq int64 `json:"seq"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func MsgToUser(sendPbData *pbRelay.MsgToUserReq, OfflineInfo, Options string) {
|
||||||
|
var wsResult []*pbRelay.SingleMsgToUser
|
||||||
|
isShouldOfflinePush := true
|
||||||
|
MOptions := utils.JsonStringToMap(Options)
|
||||||
|
isOfflinePush := utils.GetSwitchFromOptions(MOptions, "offlinePush")
|
||||||
|
log.InfoByKv("Get chat from msg_transfer And push chat", sendPbData.OperationID, "PushData", sendPbData)
|
||||||
|
grpcCons := getcdv3.GetConn4Unique(config.Config.Etcd.EtcdSchema, strings.Join(config.Config.Etcd.EtcdAddr, ","), config.Config.RpcRegisterName.OpenImOnlineMessageRelayName)
|
||||||
|
//Online push message
|
||||||
|
for _, v := range grpcCons {
|
||||||
|
msgClient := pbRelay.NewOnlineMessageRelayServiceClient(v)
|
||||||
|
reply, err := msgClient.MsgToUser(context.Background(), sendPbData)
|
||||||
|
if reply != nil && reply.Resp != nil && err == nil {
|
||||||
|
wsResult = append(wsResult, reply.Resp...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isOfflinePush && sendPbData.ContentType != constant.SyncSenderMsg {
|
||||||
|
|
||||||
|
for _, t := range pushTerminal {
|
||||||
|
for _, v := range wsResult {
|
||||||
|
if v.RecvPlatFormID == t && v.ResultCode == 0 {
|
||||||
|
isShouldOfflinePush = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isShouldOfflinePush {
|
||||||
|
//Use offline push messaging
|
||||||
|
var UIDList []string
|
||||||
|
UIDList = append(UIDList, sendPbData.RecvID)
|
||||||
|
var sendUIDList []string
|
||||||
|
sendUIDList = append(sendUIDList, sendPbData.SendID)
|
||||||
|
userInfo, err := internal_service.GetUserInfoClient(&pbGetInfo.GetUserInfoReq{UserIDList: sendUIDList, OperationID: sendPbData.OperationID})
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByArgs(fmt.Sprintf("err=%v,call GetUserInfoClient rpc server failed", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
customContent := EChatContent{
|
||||||
|
SessionType: int(sendPbData.SessionType),
|
||||||
|
From: sendPbData.SendID,
|
||||||
|
To: sendPbData.RecvID,
|
||||||
|
Seq: sendPbData.RecvSeq,
|
||||||
|
}
|
||||||
|
bCustomContent, _ := json.Marshal(customContent)
|
||||||
|
|
||||||
|
jsonCustomContent := string(bCustomContent)
|
||||||
|
switch sendPbData.ContentType {
|
||||||
|
case constant.Text:
|
||||||
|
IOSAccountListPush(UIDList, userInfo.Data[0].Name, sendPbData.Content, jsonCustomContent)
|
||||||
|
case constant.Picture:
|
||||||
|
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Picture], jsonCustomContent)
|
||||||
|
case constant.Voice:
|
||||||
|
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Voice], jsonCustomContent)
|
||||||
|
case constant.Video:
|
||||||
|
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.Video], jsonCustomContent)
|
||||||
|
case constant.File:
|
||||||
|
IOSAccountListPush(UIDList, userInfo.Data[0].Name, constant.ContentType2PushContent[constant.File], jsonCustomContent)
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
isShouldOfflinePush = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendMsgByWS(m *pbChat.WSToMsgSvrChatMsg) {
|
||||||
|
m.MsgID = rpcChat.GetMsgID(m.SendID)
|
||||||
|
pid, offset, err := producer.SendMessage(m, m.SendID)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByKv("sys send msg to kafka failed", m.OperationID, "send data", m.String(), "pid", pid, "offset", offset, "err", err.Error(), "msgKey--sendID", m.SendID)
|
||||||
|
}
|
||||||
|
pid, offset, err = producer.SendMessage(m, m.RecvID)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorByKv("kafka send failed", m.OperationID, "send data", m.String(), "pid", pid, "offset", offset, "err", err.Error(), "msgKey--recvID", m.RecvID)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/common/config"
|
||||||
|
tpns "Open_IM/src/push/sdk/tpns-server-sdk-go/go"
|
||||||
|
"Open_IM/src/push/sdk/tpns-server-sdk-go/go/auth"
|
||||||
|
"Open_IM/src/push/sdk/tpns-server-sdk-go/go/common"
|
||||||
|
"Open_IM/src/push/sdk/tpns-server-sdk-go/go/req"
|
||||||
|
)
|
||||||
|
|
||||||
|
var badgeType = -2
|
||||||
|
var iosAcceptId = auth.Auther{AccessID: config.Config.Push.Tpns.Ios.AccessID, SecretKey: config.Config.Push.Tpns.Ios.SecretKey}
|
||||||
|
|
||||||
|
func IOSAccountListPush(accounts []string, title, content, jsonCustomContent string) {
|
||||||
|
var iosMessage = tpns.Message{
|
||||||
|
Title: title,
|
||||||
|
Content: content,
|
||||||
|
IOS: &tpns.IOSParams{
|
||||||
|
Aps: &tpns.Aps{
|
||||||
|
BadgeType: &badgeType,
|
||||||
|
Sound: "default",
|
||||||
|
Category: "INVITE_CATEGORY",
|
||||||
|
},
|
||||||
|
CustomContent: jsonCustomContent,
|
||||||
|
//CustomContent: `"{"key\":\"value\"}"`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pushReq, reqBody, err := req.NewListAccountPush(accounts, iosMessage)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iosAcceptId.Auth(pushReq, auth.UseSignAuthored, iosAcceptId, reqBody)
|
||||||
|
common.PushAndGetResult(pushReq)
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Open_IM/src/push/logic"
|
||||||
|
"flag"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rpcPort := flag.Int("port", -1, "rpc listening port")
|
||||||
|
flag.Parse()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
logic.Init(*rpcPort)
|
||||||
|
logic.Run()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
b64 "encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Auther struct {
|
||||||
|
AccessID string
|
||||||
|
SecretKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
var UseSignAuthored = true
|
||||||
|
|
||||||
|
func (a *Auther) Auth(req *http.Request, useSignAuthored bool, auth Auther, reqBody string) {
|
||||||
|
|
||||||
|
if useSignAuthored {
|
||||||
|
now := time.Now()
|
||||||
|
timeStamp := now.Unix()
|
||||||
|
req.Header.Add("AccessId", auth.AccessID)
|
||||||
|
req.Header.Add("TimeStamp", strconv.Itoa(int(timeStamp)))
|
||||||
|
sign := GenSign(uint64(timeStamp), auth.AccessID, auth.SecretKey, reqBody)
|
||||||
|
req.Header.Add("Sign", sign)
|
||||||
|
} else {
|
||||||
|
author := makeAuthHeader(a.AccessID, a.SecretKey)
|
||||||
|
//log.Printf("author string:%v", author)
|
||||||
|
req.Header.Add("Authorization", author)
|
||||||
|
}
|
||||||
|
//req.Header.Add("Content-Type", "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeAuthHeader(appID, secretKey string) string {
|
||||||
|
base64Str := base64.StdEncoding.EncodeToString(
|
||||||
|
[]byte(
|
||||||
|
fmt.Sprintf("%s:%s", appID, secretKey),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return fmt.Sprintf("Basic %s", base64Str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenSign(timeStamp uint64, accessId string, secretKey, requestBody string) string {
|
||||||
|
signBody := strconv.Itoa(int(timeStamp)) + accessId + requestBody
|
||||||
|
// Create a new HMAC by defining the hash type and the key (as byte array)
|
||||||
|
h := hmac.New(sha256.New, []byte(secretKey))
|
||||||
|
// Write Data to it
|
||||||
|
h.Write([]byte(signBody))
|
||||||
|
|
||||||
|
// Get result and encode as hexadecimal string
|
||||||
|
sha := hex.EncodeToString(h.Sum(nil))
|
||||||
|
//fmt.Println()
|
||||||
|
//fmt.Println("timeStamp: " + strconv.Itoa(int(timeStamp)) + " accessID:" + accessId + " body:" + requestBody)
|
||||||
|
sEnc := b64.StdEncoding.EncodeToString([]byte(sha))
|
||||||
|
//fmt.Println("final Result " + sEnc)
|
||||||
|
return sEnc
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
MaxIdleConnsPerHost: 100,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
DisableCompression: false,
|
||||||
|
DisableKeepAlives: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
tpns "Open_IM/src/push/sdk/tpns-server-sdk-go/go"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PushAndGetResult(pushReq *http.Request) {
|
||||||
|
c := &http.Client{}
|
||||||
|
rsp, err := c.Do(pushReq)
|
||||||
|
fmt.Println()
|
||||||
|
if err != nil {
|
||||||
|
//fmt.Printf("http err:%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer rsp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(rsp.Body)
|
||||||
|
//fmt.Printf("http ReadAll err:%v, body:%v ", err, string(body))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r := &tpns.CommonRsp{}
|
||||||
|
json.Unmarshal(body, r)
|
||||||
|
//fmt.Printf("push result: %+v", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UploadFile(req *http.Request) (int, error) {
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return 0, fmt.Errorf("response error, status: %s, body: %s", resp.Status, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
type uploadResponse struct {
|
||||||
|
RetCode int `json:"retCode"`
|
||||||
|
ErrMsg string `json:"errMsg"`
|
||||||
|
UploadId int `json:"uploadId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var ur uploadResponse
|
||||||
|
if err := json.Unmarshal(body, &ur); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ur.RetCode != 0 {
|
||||||
|
return 0, fmt.Errorf("response with %d:%s", ur.RetCode, ur.ErrMsg)
|
||||||
|
}
|
||||||
|
return ur.UploadId, nil
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
func ToJson(v interface{}) string {
|
||||||
|
bs, _ := json.Marshal(v)
|
||||||
|
return string(bs)
|
||||||
|
}
|
@ -0,0 +1,256 @@
|
|||||||
|
package tpns
|
||||||
|
|
||||||
|
type CommonRspEnv string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// EnvProd
|
||||||
|
EnvProd CommonRspEnv = "product"
|
||||||
|
// EnvDev
|
||||||
|
EnvDev CommonRspEnv = "dev"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommonRsp struct {
|
||||||
|
// TODO: doc this
|
||||||
|
Seq int64 `json:"seq"`
|
||||||
|
|
||||||
|
PushID string `json:"push_id"`
|
||||||
|
|
||||||
|
RetCode int `json:"ret_code"`
|
||||||
|
|
||||||
|
Environment CommonRspEnv `json:"environment"`
|
||||||
|
|
||||||
|
ErrMsg string `json:"err_msg,omitempty"`
|
||||||
|
|
||||||
|
Result map[string]string `json:"result,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AudienceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AdAll AudienceType = "all"
|
||||||
|
|
||||||
|
AdTag AudienceType = "tag"
|
||||||
|
|
||||||
|
AdToken AudienceType = "token"
|
||||||
|
|
||||||
|
AdTokenList AudienceType = "token_list"
|
||||||
|
|
||||||
|
AdAccount AudienceType = "account"
|
||||||
|
|
||||||
|
AdAccountList AudienceType = "account_list"
|
||||||
|
|
||||||
|
AdPackageAccount AudienceType = "package_account_push"
|
||||||
|
|
||||||
|
AdPackageToken AudienceType = "package_token_push"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MessageType push API message_type
|
||||||
|
type MessageType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MsgTypeNotify MessageType = "notify"
|
||||||
|
|
||||||
|
MsgTypeMessage MessageType = "message"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
AudienceType AudienceType `json:"audience_type"`
|
||||||
|
|
||||||
|
Message Message `json:"message"`
|
||||||
|
|
||||||
|
MessageType MessageType `json:"message_type"`
|
||||||
|
|
||||||
|
Tag []TagRule `json:"tag_rules,omitempty"`
|
||||||
|
|
||||||
|
TokenList []string `json:"token_list,omitempty"`
|
||||||
|
|
||||||
|
AccountList []string `json:"account_list,omitempty"`
|
||||||
|
|
||||||
|
Environment CommonRspEnv `json:"environment,omitempty"`
|
||||||
|
|
||||||
|
UploadId int `json:"upload_id,omitempty"`
|
||||||
|
|
||||||
|
ExpireTime int `json:"expire_time,omitempty"`
|
||||||
|
|
||||||
|
SendTime string `json:"send_time,omitempty"`
|
||||||
|
|
||||||
|
MultiPkg bool `json:"multi_pkg,omitempty"`
|
||||||
|
|
||||||
|
PlanId string `json:"plan_id,omitempty"`
|
||||||
|
|
||||||
|
AccountPushType int `json:"account_push_type,omitempty"`
|
||||||
|
|
||||||
|
PushSpeed int `json:"push_speed,omitempty"`
|
||||||
|
|
||||||
|
CollapseId int `json:"collapse_id"`
|
||||||
|
|
||||||
|
TPNSOnlinePushType int `json:"tpns_online_push_type"`
|
||||||
|
|
||||||
|
ChannelRules []*ChannelDistributeRule `json:"channel_rules,omitempty"`
|
||||||
|
|
||||||
|
LoopParam *PushLoopParam `json:"loop_param,omitempty"`
|
||||||
|
ForceCollapse bool `json:"force_collapse"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TagListOperation string
|
||||||
|
|
||||||
|
type ChannelDistributeRule struct {
|
||||||
|
ChannelName string `json:"channel"`
|
||||||
|
Disable bool `json:"disable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushLoopParam struct {
|
||||||
|
StartDate string `json:"startDate"`
|
||||||
|
|
||||||
|
EndDate string `json:"endDate"`
|
||||||
|
|
||||||
|
LoopType PushLoopType `json:"loopType"`
|
||||||
|
|
||||||
|
LoopDayIndexs []uint32 `json:"loopDayIndexs"`
|
||||||
|
|
||||||
|
DayTimes []string `json:"dayTimes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PushLoopType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
TagListOpAnd TagListOperation = "AND"
|
||||||
|
|
||||||
|
TagListOpOr TagListOperation = "OR"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TagType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
XGAutoProvince TagType = "xg_auto_province"
|
||||||
|
XGAutoActive TagType = "xg_auto_active"
|
||||||
|
XGUserDefine TagType = "xg_user_define"
|
||||||
|
XGAutoVersion TagType = "xg_auto_version"
|
||||||
|
XGAutoSdkversion TagType = "xg_auto_sdkversion"
|
||||||
|
XGAutoDevicebrand TagType = "xg_auto_devicebrand"
|
||||||
|
XGAutoDeviceversion TagType = "xg_auto_deviceversion"
|
||||||
|
XGAutoCountry TagType = "xg_auto_country"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TagRule struct {
|
||||||
|
TagItems []TagItem `json:"tag_items"`
|
||||||
|
|
||||||
|
IsNot bool `json:"is_not"`
|
||||||
|
|
||||||
|
Operator TagListOperation `json:"operator"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TagItem struct {
|
||||||
|
// 标签
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
IsNot bool `json:"is_not"`
|
||||||
|
TagsOperator TagListOperation `json:"tags_operator"`
|
||||||
|
ItemsOperator TagListOperation `json:"items_operator"`
|
||||||
|
TagType TagType `json:"tag_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
|
||||||
|
AcceptTime []AcceptTimeItem `json:"accept_time,omitempty"`
|
||||||
|
|
||||||
|
Android *AndroidParams `json:"android,omitempty"`
|
||||||
|
|
||||||
|
IOS *IOSParams `json:"ios,omitempty"`
|
||||||
|
|
||||||
|
ThreadId string `json:"thread_id,omitempty"`
|
||||||
|
|
||||||
|
ThreadSumtext string `json:"thread_sumtext,omitempty"`
|
||||||
|
|
||||||
|
XGMediaResources string `json:"xg_media_resources,omitempty"`
|
||||||
|
|
||||||
|
XGMediaAudioResources string `json:"xg_media_audio_resources,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AcceptTimeItem struct {
|
||||||
|
Start HourAndMin `json:"start,omitempty"`
|
||||||
|
End HourAndMin `json:"end,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HourAndMin struct {
|
||||||
|
Hour string `json:"hour,omitempty"`
|
||||||
|
Min string `json:"min,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AndroidParams struct {
|
||||||
|
BuilderId *int `json:"builder_id,omitempty"`
|
||||||
|
|
||||||
|
Ring *int `json:"ring,omitempty"`
|
||||||
|
|
||||||
|
RingRaw string `json:"ring_raw,omitempty"`
|
||||||
|
|
||||||
|
Vibrate *int `json:"vibrate,omitempty"`
|
||||||
|
|
||||||
|
Lights *int `json:"lights,omitempty"`
|
||||||
|
|
||||||
|
Clearable *int `json:"clearable,omitempty"`
|
||||||
|
|
||||||
|
IconType *int `json:"icon_type"`
|
||||||
|
|
||||||
|
IconRes string `json:"icon_res,omitempty"`
|
||||||
|
|
||||||
|
StyleId *int `json:"style_id,omitempty"`
|
||||||
|
|
||||||
|
SmallIcon string `json:"small_icon,omitempty"`
|
||||||
|
|
||||||
|
Action *Action `json:"action,omitempty"`
|
||||||
|
|
||||||
|
CustomContent string `json:"custom_content,omitempty"`
|
||||||
|
|
||||||
|
ShowType *int `json:"show_type,omitempty"`
|
||||||
|
|
||||||
|
NChId string `json:"n_ch_id,omitempty"`
|
||||||
|
|
||||||
|
NChName string `json:"n_ch_name,omitempty"`
|
||||||
|
|
||||||
|
HwChId string `json:"hw_ch_id,omitempty"`
|
||||||
|
|
||||||
|
XmChId string `json:"xm_ch_id,omitempty"`
|
||||||
|
|
||||||
|
OppoChId string `json:"oppo_ch_id,omitempty"`
|
||||||
|
|
||||||
|
VivoChId string `json:"vivo_ch_id,omitempty"`
|
||||||
|
|
||||||
|
BadgeType *int `json:"badge_type,omitempty"`
|
||||||
|
|
||||||
|
IconColor *int `json:"icon_color,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action struct {
|
||||||
|
ActionType *int `json:"action_type,omitempty"`
|
||||||
|
Activity string `json:"activity"`
|
||||||
|
AtyAttr AtyAttr `json:"aty_attr,omitempty"`
|
||||||
|
Intent string `json:"intent"`
|
||||||
|
Browser Browser `json:"browser,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Browser struct {
|
||||||
|
Url string `json:"url,omitempty"`
|
||||||
|
Confirm *int `json:"confirm,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AtyAttr struct {
|
||||||
|
AttrIf *int `json:"if,omitempty"`
|
||||||
|
Pf *int `json:"pf,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IOSParams struct {
|
||||||
|
Aps *Aps `json:"aps,omitempty"`
|
||||||
|
|
||||||
|
CustomContent string `json:"custom_content,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Aps struct {
|
||||||
|
Alert map[string]string `json:"alert,omitempty"`
|
||||||
|
BadgeType *int `json:"badge_type,omitempty"`
|
||||||
|
Category string `json:"category,omitempty"`
|
||||||
|
ContentAvailableInt *int `json:"content-available,omitempty"`
|
||||||
|
MutableContent *int `json:"mutable-content,omitempty"`
|
||||||
|
Sound string `json:"sound,omitempty"`
|
||||||
|
}
|
@ -0,0 +1,403 @@
|
|||||||
|
package req
|
||||||
|
|
||||||
|
import (
|
||||||
|
tpns "Open_IM/src/push/sdk/tpns-server-sdk-go/go"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var PushURL = "https://api.tpns.tencent.com/v3/push/app"
|
||||||
|
|
||||||
|
//var PushURL = "https://test.api.tpns.tencent.com/v3/push/app"
|
||||||
|
|
||||||
|
func URL(url string) {
|
||||||
|
PushURL = url
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReqOpt func(*tpns.Request)
|
||||||
|
|
||||||
|
func NewPush(req *tpns.Request, opts ...ReqOpt) (*http.Request, string, error) {
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUploadFileRequest(host string, file string) (*http.Request, error) {
|
||||||
|
fp, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer fp.Close()
|
||||||
|
body := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
part, err := writer.CreateFormFile("file", filepath.Base(fp.Name()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Copy(part, fp)
|
||||||
|
writer.Close()
|
||||||
|
url := host + "/v3/push/package/upload"
|
||||||
|
req, err := http.NewRequest("POST", url, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Add("Content-Type", writer.FormDataContentType())
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSingleAccountPush(
|
||||||
|
message tpns.Message,
|
||||||
|
account string,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdAccountList,
|
||||||
|
AccountList: []string{account},
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListAccountPush(
|
||||||
|
accounts []string, message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdAccountList,
|
||||||
|
AccountList: accounts,
|
||||||
|
Message: message,
|
||||||
|
Environment: tpns.EnvDev,
|
||||||
|
}
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTokenPush(
|
||||||
|
tokens []string, message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdTokenList,
|
||||||
|
TokenList: tokens,
|
||||||
|
Message: message,
|
||||||
|
Environment: tpns.EnvProd,
|
||||||
|
}
|
||||||
|
//fmt.Printf("reqBody :%v", common.ToJson(req))
|
||||||
|
//fmt.Println()
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTagsPush(
|
||||||
|
tagList []tpns.TagRule, message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdTag,
|
||||||
|
Tag: tagList,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
//fmt.Printf("reqBody :%v", common.ToJson(req))
|
||||||
|
//fmt.Println()
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAllPush(
|
||||||
|
message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdAll,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAccountPackagePush(
|
||||||
|
message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdPackageAccount,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTokenPackagePush(
|
||||||
|
message tpns.Message,
|
||||||
|
opts ...ReqOpt,
|
||||||
|
) (*http.Request, string, error) {
|
||||||
|
req := &tpns.Request{
|
||||||
|
MessageType: tpns.MsgTypeNotify,
|
||||||
|
AudienceType: tpns.AdPackageToken,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
return NewPushReq(req, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPushReq(req *tpns.Request, opts ...ReqOpt) (request *http.Request, reqBody string, err error) {
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(req)
|
||||||
|
}
|
||||||
|
bodyBytes, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
reqBody = string(bodyBytes)
|
||||||
|
//fmt.Printf("NewPushReq req:%v", reqBody)
|
||||||
|
request, err = http.NewRequest("POST", PushURL, bytes.NewReader(bodyBytes))
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
request.Header.Add("Content-Type", "application/json")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnvProd() ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Environment = tpns.EnvProd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnvDev() ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Environment = tpns.EnvDev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Title(t string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Title = t
|
||||||
|
if r.Message.IOS != nil {
|
||||||
|
if r.Message.IOS.Aps != nil {
|
||||||
|
r.Message.IOS.Aps.Alert["title"] = t
|
||||||
|
} else {
|
||||||
|
r.Message.IOS.Aps = &tpns.Aps{
|
||||||
|
Alert: map[string]string{"title": t},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.Message.IOS = &tpns.IOSParams{
|
||||||
|
Aps: &tpns.Aps{
|
||||||
|
Alert: map[string]string{"title": t},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Content(c string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Content = c
|
||||||
|
if r.Message.IOS != nil {
|
||||||
|
if r.Message.IOS.Aps != nil {
|
||||||
|
r.Message.IOS.Aps.Alert["body"] = c
|
||||||
|
} else {
|
||||||
|
r.Message.IOS.Aps = &tpns.Aps{
|
||||||
|
Alert: map[string]string{"body": c},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.Message.IOS = &tpns.IOSParams{
|
||||||
|
Aps: &tpns.Aps{
|
||||||
|
Alert: map[string]string{"body": c},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ring(ring *int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.Ring = ring
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RingRaw(rr string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.RingRaw = rr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Vibrate(v *int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.Vibrate = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lights(l *int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.Lights = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Clearable(c *int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.Clearable = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IconType(it *int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.IconType = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IconRes(ir string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.IconRes = ir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AndroidCustomContent(ct string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.Android.CustomContent = ct
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Aps(aps *tpns.Aps) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message.IOS.Aps = aps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AudienceType(at tpns.AudienceType) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.AudienceType = at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Message(m tpns.Message) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Message = m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TokenList(tl []string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.TokenList = tl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TokenListAdd(t string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
if r.TokenList != nil {
|
||||||
|
r.TokenList = append(r.TokenList, t)
|
||||||
|
} else {
|
||||||
|
r.TokenList = []string{t}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AccountList(al []string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.AccountList = al
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ChannelDistributeRules
|
||||||
|
func AddChannelRules(ChannelRules []*tpns.ChannelDistributeRule) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.ChannelRules = ChannelRules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ChannelDistributeRules
|
||||||
|
func AddLoopParam(loopParam *tpns.PushLoopParam) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.LoopParam = loopParam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AccountListAdd(a string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
if r.AccountList != nil {
|
||||||
|
r.AccountList = append(r.AccountList, a)
|
||||||
|
} else {
|
||||||
|
r.AccountList = []string{a}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MessageType(t tpns.MessageType) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.MessageType = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddMultiPkg(multipPkg bool) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.MultiPkg = multipPkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddForceCollapse(forceCollapse bool) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.ForceCollapse = forceCollapse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddTPNSOnlinePushType(onlinePushType int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.TPNSOnlinePushType = onlinePushType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddCollapseId(collapseId int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.CollapseId = collapseId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddPushSpeed(pushSpeed int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.PushSpeed = pushSpeed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddAccountPushType(accountPushType int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.AccountPushType = accountPushType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddPlanId(planId string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.PlanId = planId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddSendTime(sendTime string) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.SendTime = sendTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddExpireTime(expireTime int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.ExpireTime = expireTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddUploadId(UploadId int) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.UploadId = UploadId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddEnvironment(Environment tpns.CommonRspEnv) ReqOpt {
|
||||||
|
return func(r *tpns.Request) {
|
||||||
|
r.Environment = Environment
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue