push server

pull/4/head
hailong 4 years ago
parent dbf2e56f37
commit a7bedf1f79

@ -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…
Cancel
Save