Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["client_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"audience.go",
"callback.go",
"client.go",
"errcode.go",
"message.go",
"notice.go",
"option.go",
"payload.go",
"platform.go",
"report.go",
"schedule.go",
],
importpath = "go-common/app/service/main/push/dao/jpush",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/stat:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,48 @@
package jpush
const (
_audienceTag = "tag"
_audienceTagAnd = "tag_and"
_audienceAlias = "alias"
_audienceID = "registration_id"
_audienceAll = "all"
)
// Audience .
type Audience struct {
Object interface{}
audience map[string][]string
}
// All .
func (a *Audience) All() {
a.Object = _audienceAll
}
// SetID .
func (a *Audience) SetID(ids []string) {
a.set(_audienceID, ids)
}
// SetTag .
func (a *Audience) SetTag(tags []string) {
a.set(_audienceTag, tags)
}
// SetTagAnd .
func (a *Audience) SetTagAnd(tags []string) {
a.set(_audienceTagAnd, tags)
}
// SetAlias .
func (a *Audience) SetAlias(alias []string) {
a.set(_audienceAlias, alias)
}
func (a *Audience) set(key string, v []string) {
if a.Object == nil {
a.audience = map[string][]string{key: v}
a.Object = a.audience
}
a.audience[key] = v
}

View File

@@ -0,0 +1,77 @@
package jpush
const (
// CallbackTypeReceive 送达才回执
CallbackTypeReceive = callbackType(1)
// CallbackTypeClick 点击才回执
CallbackTypeClick = callbackType(2)
// CallbackTypeAll 送达和点击都回执
CallbackTypeAll = callbackType(3)
// StatusSwitchOn 回执时候通知栏开关状态:开
StatusSwitchOn = int(1)
// StatusSwitchOff 回执时候通知栏开关状态:关
StatusSwitchOff = int(2)
defaultCallbackURL = "https://api.bilibili.com/x/push/callback/jpush"
)
type callbackType int
// CallbackReq 消息回执请求体
type CallbackReq struct {
// URL 接受回执数据的URL
URL string `json:"url"`
// Type 需要的回执类型
Type callbackType `json:"type"`
// Params 携带的自定义参数
Params map[string]string `json:"params"`
}
// NewCallbackReq new Callback
func NewCallbackReq() *CallbackReq {
return &CallbackReq{
URL: defaultCallbackURL,
Type: CallbackTypeReceive,
Params: make(map[string]string),
}
}
// SetURL 设置接收回执的URL
func (cb *CallbackReq) SetURL(url string) {
if url == "" {
return
}
cb.URL = url
}
// SetType 设置需要回执的类型
func (cb *CallbackReq) SetType(typ callbackType) {
cb.Type = typ
}
// SetParam 设置自定义参数
func (cb *CallbackReq) SetParam(m map[string]string) {
if m == nil {
return
}
cb.Params = m
}
// CallbackReply 消息回执接收体
type CallbackReply struct {
// Token device token
Token string `json:"registration_id"`
// Platform android or ios
Platform string `json:"platform"`
// Time 消息送达或点击的秒级时间戳
Time int64 `json:"sent_time"`
// Switch 通知栏消息开关
Switch bool `json:"notification_state"`
// Type 送达或点击
Type callbackType `json:"callback_type"`
// Channel 下发通道
Channel int `json:"channel"`
// Params 自定义参数
Params map[string]string `json:"params"`
}

View File

@@ -0,0 +1,92 @@
package jpush
import (
"bytes"
"encoding/base64"
"encoding/json"
"io/ioutil"
"net/http"
"time"
"go-common/library/stat"
"go-common/library/stat/prom"
)
const (
_charset = "UTF-8"
_contentTypeJSON = "application/json"
_pushURL = "https://api.jpush.cn/v3/push"
// _scheduleURL = "https://api.jpush.cn/v3/schedules"
// _reportURL = "https://report.jpush.cn/v3/received"
)
// PushResponse .
type PushResponse struct {
SendNo interface{} `json:"sendno,omitempty"`
MsgID interface{} `json:"msg_id,omitempty"`
IllegalTokens []string `json:"illegal_rids,omitempty"`
Retry bool // 是否需要重试请求
Error struct {
Code int `json:"code"`
Message string `json:"message"`
} `json:"error,omitempty"`
}
// Client jpush http client.
type Client struct {
Auth string
Stats stat.Stat
Timeout time.Duration
}
// NewClient new client.
func NewClient(appKey, secret string, timeout time.Duration) *Client {
auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(appKey+":"+secret))
return &Client{
Auth: auth,
Stats: prom.HTTPClient,
Timeout: timeout,
}
}
// Push push notification.
func (cli *Client) Push(payload *Payload) (res *PushResponse, err error) {
res = new(PushResponse)
if cli.Stats != nil {
now := time.Now()
defer func() {
cli.Stats.Timing(_pushURL, int64(time.Since(now)/time.Millisecond))
// log.Info("jpush stats timing: %v", int64(time.Since(now)/time.Millisecond))
if err != nil {
cli.Stats.Incr(_pushURL, "failed")
}
}()
}
bs, err := payload.ToBytes()
if err != nil {
return
}
req, _ := http.NewRequest("POST", _pushURL, bytes.NewBuffer(bs))
req.Header.Add("Charset", _charset)
req.Header.Add("Authorization", cli.Auth)
req.Header.Add("Content-Type", _contentTypeJSON)
client := &http.Client{Timeout: cli.Timeout}
resp, err := client.Do(req)
if err != nil {
res.Retry = true
return
}
defer resp.Body.Close()
r, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
if err = json.Unmarshal(r, &res); err != nil {
return
}
if res.Error.Code == ErrRetry || res.Error.Code == ErrInternal {
res.Retry = true
}
return
}

View File

@@ -0,0 +1,47 @@
package jpush
import (
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func TestPush(t *testing.T) {
Convey("test jpush", t, func() {
var (
ad Audience
notice Notice
plat = NewPlatform(PlatformAndroid)
payload = NewPayload()
cbr = NewCallbackReq()
an = &AndroidNotice{
Title: "test title",
Alert: "test alert",
AlertType: AndroidAlertTypeLight | AndroidAlertTypeSound, // 通知提醒类型
Extras: map[string]interface{}{
"task_id": "tid",
"scheme": "bili:///?type=bilivideo&avid=123",
},
}
)
// ad.SetID([]string{"190e35f7e068f4a19d1"})
ad.SetID([]string{""})
notice.SetAndroidNotice(an)
payload.SetPlatform(plat)
payload.SetAudience(&ad)
payload.SetNotice(&notice)
payload.Options.SetTimelive(1000)
payload.Options.SetReturnInvalidToken(true)
cbr.SetParam(map[string]string{"task": "tid"})
payload.SetCallbackReq(cbr)
// bs, err := payload.ToBytes()
// fmt.Printf("payload(%s) error(%v)", bs, err)
cli := NewClient("62396b3e57f0b2b4b2c7bf48", "588f56e1bedd3c6b46db4863", time.Second)
res, err := cli.Push(payload)
So(err, ShouldBeNil)
t.Logf("push result(%+v)", res)
})
}

View File

@@ -0,0 +1,11 @@
package jpush
const (
// ErrAllTokenInvalid 所有的token都无效
// ErrAllTokensInvalid = int(1060)
// ErrRetry 需要重试
ErrRetry = int(1030)
// ErrInternal 服务方内部错误
ErrInternal = int(1000)
)

View File

@@ -0,0 +1,33 @@
package jpush
// Message .
type Message struct {
Content string `json:"msg_content"`
Title string `json:"title,omitempty"`
ContentType string `json:"content_type,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
// SetContent .
func (m *Message) SetContent(c string) {
m.Content = c
}
// SetTitle .
func (m *Message) SetTitle(title string) {
m.Title = title
}
// SetContentType .
func (m *Message) SetContentType(t string) {
m.ContentType = t
}
// AddExtras .
func (m *Message) AddExtras(key string, value interface{}) {
if m.Extras == nil {
m.Extras = make(map[string]interface{})
}
m.Extras[key] = value
}

View File

@@ -0,0 +1,87 @@
package jpush
const (
// AndroidAlertTypeAll 全开
AndroidAlertTypeAll = -1
// AndroidAlertTypeNone 全关
AndroidAlertTypeNone = 0
// AndroidAlertTypeSound 开声音
AndroidAlertTypeSound = 1
// AndroidAlertTypeVibrate 开振动
AndroidAlertTypeVibrate = 2
// AndroidAlertTypeLight 开呼吸灯
AndroidAlertTypeLight = 4
// AndroidStyleDefault 默认通知栏样式
AndroidStyleDefault = 0
// AndroidStyleBigTxt big_text 字段大文本的形式展示
AndroidStyleBigTxt = 1
// AndroidStyleInbox inbox 字段 json 的每个 key 对应的 value 会被当作文本条目逐条展示
AndroidStyleInbox = 2
// AndroidStylePic big_pic_path 字段的图片URL展示成图片
AndroidStylePic = 3
)
// Notice .
type Notice struct {
Alert string `json:"alert,omitempty"`
Android *AndroidNotice `json:"android,omitempty"`
IOS *IOSNotice `json:"ios,omitempty"`
WINPhone *WinPhoneNotice `json:"winphone,omitempty"`
}
// AndroidNotice .
type AndroidNotice struct {
Alert string `json:"alert"`
Title string `json:"title,omitempty"`
AlertType int `json:"alert_type"`
BuilderID int `json:"builder_id,omitempty"`
Style int `json:"style,omitempty"`
BigPicPath string `json:"big_pic_path,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
// SetPic sets Android notice pic.
func (an *AndroidNotice) SetPic(pic string) {
an.Style = AndroidStylePic
an.BigPicPath = pic
}
// IOSNotice .
type IOSNotice struct {
Alert interface{} `json:"alert"`
Sound string `json:"sound,omitempty"`
Badge string `json:"badge,omitempty"`
ContentAvailable bool `json:"content-available,omitempty"`
MutableContent bool `json:"mutable-content,omitempty"`
Category string `json:"category,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
// WinPhoneNotice .
type WinPhoneNotice struct {
Alert string `json:"alert"`
Title string `json:"title,omitempty"`
OpenPage string `json:"_open_page,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"`
}
// SetAlert .
func (n *Notice) SetAlert(alert string) {
n.Alert = alert
}
// SetAndroidNotice .
func (n *Notice) SetAndroidNotice(an *AndroidNotice) {
n.Android = an
}
// SetIOSNotice .
func (n *Notice) SetIOSNotice(in *IOSNotice) {
n.IOS = in
}
// SetWinPhoneNotice .
func (n *Notice) SetWinPhoneNotice(wn *WinPhoneNotice) {
n.WINPhone = wn
}

View File

@@ -0,0 +1,41 @@
package jpush
// Option .
type Option struct {
SendNo int `json:"sendno,omitempty"`
TimeLive int `json:"time_to_live,omitempty"`
ApnsProduction bool `json:"apns_production"`
OverrideMsgID int64 `json:"override_msg_id,omitempty"`
BigPushDuration int `json:"big_push_duration,omitempty"`
ReturnInvalidToken bool `json:"return_invalid_rid,omitempty"` // 是否同步返回无效的token
}
// SetSendno .
func (o *Option) SetSendno(no int) {
o.SendNo = no
}
// SetTimelive .
func (o *Option) SetTimelive(timelive int) {
o.TimeLive = timelive
}
// SetOverrideMsgID .
func (o *Option) SetOverrideMsgID(id int64) {
o.OverrideMsgID = id
}
// SetApns .
func (o *Option) SetApns(apns bool) {
o.ApnsProduction = apns
}
// SetBigPushDuration .
func (o *Option) SetBigPushDuration(dur int) {
o.BigPushDuration = dur
}
// SetReturnInvalidToken .
func (o *Option) SetReturnInvalidToken(onoff bool) {
o.ReturnInvalidToken = onoff
}

View File

@@ -0,0 +1,61 @@
package jpush
import (
"encoding/json"
)
// Payload .
type Payload struct {
Platform interface{} `json:"platform"`
Audience interface{} `json:"audience"`
Notification interface{} `json:"notification,omitempty"`
Message interface{} `json:"message,omitempty"`
Options *Option `json:"options,omitempty"`
Callback *CallbackReq `json:"callback,omitempty"`
}
// NewPayload .
func NewPayload() *Payload {
return &Payload{
Options: &Option{},
}
}
// SetPlatform .
func (p *Payload) SetPlatform(plat *Platform) {
p.Platform = plat.OS
}
// SetAudience .
func (p *Payload) SetAudience(ad *Audience) {
p.Audience = ad.Object
}
// SetOptions .
func (p *Payload) SetOptions(o *Option) {
p.Options = o
}
// SetMessage .
func (p *Payload) SetMessage(m *Message) {
p.Message = m
}
// SetNotice .
func (p *Payload) SetNotice(notice *Notice) {
p.Notification = notice
}
// SetCallbackReq .
func (p *Payload) SetCallbackReq(cb *CallbackReq) {
p.Callback = cb
}
// ToBytes .
func (p *Payload) ToBytes() ([]byte, error) {
content, err := json.Marshal(p)
if err != nil {
return nil, err
}
return content, nil
}

View File

@@ -0,0 +1,34 @@
package jpush
const (
// PlatformIOS .
PlatformIOS = "ios"
// PlatformAndroid .
PlatformAndroid = "android"
// PlatformWinphone .
PlatformWinphone = "winphone"
// PlatformAll .
PlatformAll = "all"
)
// Platform .
type Platform struct {
OS interface{}
osArray []string
}
// NewPlatform .
func NewPlatform(os ...string) *Platform {
p := new(Platform)
for _, v := range os {
switch v {
case PlatformIOS, PlatformAndroid, PlatformWinphone:
p.osArray = append(p.osArray, v)
case PlatformAll:
p.OS = PlatformAll
return p
}
}
p.OS = p.osArray
return p
}

View File

@@ -0,0 +1 @@
package jpush

View File

@@ -0,0 +1 @@
package jpush