Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
|
3ab1191cd2 | |
|
164beb90d4 | |
|
a173059aef | |
|
783a2dedfa | |
|
3557a84ae0 | |
|
e4f142324f | |
|
137f53a84d | |
|
952ede1d39 | |
|
ec55bf1878 |
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module git.bit5.ru/backend/push_common
|
||||
|
||||
go 1.19
|
||||
|
||||
require git.bit5.ru/backend/errors v1.0.0
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
git.bit5.ru/backend/errors v1.0.0 h1:WWJ0sly44q1HQjN01X75ZAGKZwwY5Ml+XVDXMjCkToA=
|
||||
git.bit5.ru/backend/errors v1.0.0/go.mod h1:75faRwsnpM0Se00/Bh7fysWQXV8oMjNJFQ6f7+r9k3Y=
|
|
@ -0,0 +1,51 @@
|
|||
package push_common
|
||||
|
||||
type Platform int
|
||||
|
||||
const (
|
||||
PlatformUnknown Platform = 0
|
||||
PlatformIos Platform = 1
|
||||
PlatformAndroid Platform = 2
|
||||
PlatformAmazon Platform = 3
|
||||
PlatformSamsung Platform = 4
|
||||
PlatformHuawei Platform = 5
|
||||
)
|
||||
|
||||
func PlatformToString(p Platform) string {
|
||||
switch p {
|
||||
case PlatformUnknown:
|
||||
return "unknown"
|
||||
case PlatformIos:
|
||||
return "ios"
|
||||
case PlatformAndroid:
|
||||
return "android"
|
||||
case PlatformAmazon:
|
||||
return "amazon"
|
||||
case PlatformSamsung:
|
||||
return "samsung"
|
||||
case PlatformHuawei:
|
||||
return "huawei"
|
||||
}
|
||||
return "error"
|
||||
}
|
||||
|
||||
// Когда в pushd добавляется транспорт для новой платформы,
|
||||
// то эту платформу нужно указать в этой функции.
|
||||
func GetSupportedPlatforms() []Platform {
|
||||
return []Platform{
|
||||
PlatformIos,
|
||||
PlatformAndroid,
|
||||
//PlatformAmazon,
|
||||
PlatformSamsung,
|
||||
PlatformHuawei,
|
||||
}
|
||||
}
|
||||
|
||||
func PlatformsContain(platforms []Platform, p Platform) bool {
|
||||
for _, item := range platforms {
|
||||
if item == p {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
257
push_common.go
257
push_common.go
|
@ -1,5 +1,16 @@
|
|||
package push_common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.bit5.ru/backend/errors"
|
||||
)
|
||||
|
||||
type PushId uint32
|
||||
|
||||
func (id PushId) String() string {
|
||||
|
@ -27,8 +38,254 @@ type PushPreview struct {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type PushDef struct {
|
||||
MaxVersion string `json:"maxVersion"`
|
||||
Platforms []uint32 `json:"platforms"`
|
||||
PlayersIds []uint32 `json:"playersIds"`
|
||||
Stime uint32 `json:"stime"`
|
||||
TextVariants []*TextVariant `json:"textVariants"`
|
||||
ForTest bool `json:"forTest"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
}
|
||||
|
||||
func (pushDef *PushDef) Validate() error {
|
||||
if len(pushDef.TextVariants) == 0 {
|
||||
return errors.New("No text variants")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pushDef *PushDef) Info() string {
|
||||
var strs []string
|
||||
if len(pushDef.Platforms) > 0 {
|
||||
strs = append(strs, "Platforms: "+sliceUint32ToString(pushDef.Platforms, ","))
|
||||
}
|
||||
if len(pushDef.MaxVersion) > 0 {
|
||||
strs = append(strs, "Max.ver: "+pushDef.MaxVersion)
|
||||
}
|
||||
if len(pushDef.PlayersIds) > 0 {
|
||||
playersIdsStr := sliceUint32ToString(pushDef.PlayersIds, ",")
|
||||
strs = append(strs, "Plr.ids: "+playersIdsStr)
|
||||
}
|
||||
return strings.Join(strs, "; ")
|
||||
}
|
||||
|
||||
func sliceUint32ToString(nums []uint32, sep string) string {
|
||||
strs := make([]string, 0, len(nums))
|
||||
for _, num := range nums {
|
||||
str := strconv.FormatUint(uint64(num), 10)
|
||||
strs = append(strs, str)
|
||||
}
|
||||
return strings.Join(strs, sep)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type IncomingPushInfo struct {
|
||||
Id int `json:"id"`
|
||||
MaxVersion string `json:"maxVersion"`
|
||||
Platforms []uint32 `json:"platforms"`
|
||||
PlayersIds []uint32 `json:"playersIds"`
|
||||
TextVariants []*TextVariant `json:"textVariants"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type TextVariant struct {
|
||||
Lang int `json:"lang"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func FindTextVariantByLang(textVariants []*TextVariant, lang int) *TextVariant {
|
||||
for _, textVariant := range textVariants {
|
||||
if textVariant.Lang == lang {
|
||||
return textVariant
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadTextVariantsFromRequest(request *http.Request, textVariants *[]*TextVariant) error {
|
||||
b, err := io.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b == nil {
|
||||
return errors.New("Can not read text variants. Request body bytes is nil.")
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, textVariants)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type PushRequest struct {
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Info string `json:"info"`
|
||||
Label string `json:"label"` //Note: label for firebase
|
||||
Ttl uint32 `json:"ttl"`
|
||||
Jobs []PushJobRequest `json:"jobs"`
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
}
|
||||
|
||||
func (r *PushRequest) DeviceTokenAmount() uint32 {
|
||||
return jobRequests_deviceTokenAmount(r.Jobs)
|
||||
}
|
||||
|
||||
func (r *PushRequest) Validate() error {
|
||||
return validateJobsRequests(r.Jobs)
|
||||
}
|
||||
|
||||
func (r *PushRequest) FindJobByLang(lang int) *PushJobRequest {
|
||||
for _, j := range r.Jobs {
|
||||
if j.Language == lang {
|
||||
return &j
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PushRequest) GetPlatforms() []Platform {
|
||||
var platforms []Platform
|
||||
|
||||
for _, jobRequest := range r.Jobs {
|
||||
p := jobRequest.Platform
|
||||
if !PlatformsContain(platforms, p) {
|
||||
platforms = append(platforms, p)
|
||||
}
|
||||
}
|
||||
|
||||
return platforms
|
||||
}
|
||||
|
||||
type PushLaunchRequest struct {
|
||||
Id int `json:"id"`
|
||||
JobRequests []PushJobRequest `json:"jobs"` // Длина среза jobRequests может быть равна 0.
|
||||
}
|
||||
|
||||
//func (r *PushLaunchRequest) jobAmount() uint32 {
|
||||
// return uint32(len(r.JobRequests))
|
||||
//}
|
||||
|
||||
func (r *PushLaunchRequest) DeviceTokenAmount() uint32 {
|
||||
return jobRequests_deviceTokenAmount(r.JobRequests)
|
||||
}
|
||||
|
||||
func (r *PushLaunchRequest) Validate(ctx context.Context) error {
|
||||
return validateJobsRequests(r.JobRequests)
|
||||
}
|
||||
|
||||
func validateJobsRequests(jobRequests []PushJobRequest) error {
|
||||
for _, jobRequest := range jobRequests {
|
||||
if err := jobRequest.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PushJobRequest struct {
|
||||
Message string `json:"message"`
|
||||
Title string `json:"title"`
|
||||
Platform Platform `json:"platform"`
|
||||
Language int `json:"language"`
|
||||
Utc_delta int `json:"utc_delta"`
|
||||
Device_tokens []string `json:"device_tokens"`
|
||||
}
|
||||
|
||||
func (j *PushJobRequest) Validate() error {
|
||||
if len(j.Message) == 0 {
|
||||
return errors.New("No message")
|
||||
}
|
||||
if len(j.Device_tokens) == 0 {
|
||||
return errors.New("No device tokens")
|
||||
}
|
||||
if j.Platform == PlatformUnknown {
|
||||
return errors.New("No platform")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (req *PushJobRequest) deviceTokenAmount() uint32 {
|
||||
return uint32(len(req.Device_tokens))
|
||||
}
|
||||
|
||||
func jobRequests_deviceTokenAmount(jobRequests []PushJobRequest) uint32 {
|
||||
var total uint32 = 0
|
||||
for _, jobRequest := range jobRequests {
|
||||
total += jobRequest.deviceTokenAmount()
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type PushPayload struct {
|
||||
ImageUrl string `json:"imageUrl"`
|
||||
TextVariants []*TextVariant `json:"textVariants"`
|
||||
}
|
||||
|
||||
func ReadPayloadFromRequest(request *http.Request, payload *PushPayload) error {
|
||||
b, err := io.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b == nil {
|
||||
return errors.New("Can not read text variants. Request body bytes is nil.")
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, payload)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type Push struct {
|
||||
Id uint32 `json:"id"`
|
||||
Status int `json:"status"`
|
||||
Ctime uint32 `json:"ctime"`
|
||||
Mtime uint32 `json:"mtime"`
|
||||
Ttl uint32 `json:"ttl"`
|
||||
Stime uint32 `json:"stime"`
|
||||
Srtime uint32 `json:"srtime"`
|
||||
Info string `json:"info"`
|
||||
Label string `json:"label"`
|
||||
MaxVersion string `json:"maxVersion,omitempty"`
|
||||
Platforms []uint32 `json:"platforms,omitempty"`
|
||||
PlayersIds []uint32 `json:"playersIds,omitempty"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
TextVariants []*TextVariant `json:"textVariants"` // For incoming push only.
|
||||
Jobs []*PushJob `json:"jobs"` // Incoming push has no jobs.
|
||||
Total int `json:"total"`
|
||||
Sent int `json:"sent"` // Incoming push has not field "Sent".
|
||||
Fails int `json:"fails"` // Incoming push has not field "Fails".
|
||||
ForTest bool `json:"forTest,omitempty"`
|
||||
ImageUrl string `json:"imageUrl,omitempty"`
|
||||
}
|
||||
|
||||
func (push *Push) IsDone() bool {
|
||||
return push.Total == (push.Sent + push.Fails)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type JobId uint32
|
||||
|
||||
type PushJob struct {
|
||||
Id JobId `json:"id"`
|
||||
Platform Platform `json:"platform"`
|
||||
Message string `json:"message"`
|
||||
Title string `json:"title"`
|
||||
Language int `json:"language"`
|
||||
Utc_delta int `json:"utc_delta"`
|
||||
Total int `json:"total"`
|
||||
Sent int `json:"sent"`
|
||||
Fails int `json:"fails"`
|
||||
}
|
||||
|
||||
func (job *PushJob) IsDone() bool {
|
||||
return job.Total == (job.Sent + job.Fails)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package push_common
|
||||
|
||||
import "strings"
|
||||
|
||||
type PushType uint8
|
||||
|
||||
const (
|
||||
PushType_User PushType = 1
|
||||
PushType_Auto PushType = 2
|
||||
)
|
||||
|
||||
func PushTypeToString(pt PushType) string {
|
||||
switch pt {
|
||||
case PushType_User:
|
||||
return "user"
|
||||
case PushType_Auto:
|
||||
return "auto"
|
||||
}
|
||||
return "error"
|
||||
}
|
||||
|
||||
const AutoPushInfoPrefix = "#"
|
||||
|
||||
// Автоматическое пуш-оповещение - пуш-оповещение,
|
||||
// которое было создано автоматически (а не пользователем инсайдера).
|
||||
func IsAutoPush(pushInfo string) bool {
|
||||
return strings.HasPrefix(pushInfo, AutoPushInfoPrefix)
|
||||
}
|
||||
|
||||
// Пользовательское пуш-оповещение - пуш-оповещение,
|
||||
// которое было создано пользователем инсайдера (а не автоматически).
|
||||
func IsUserPush(pushInfo string) bool {
|
||||
isAuto := IsAutoPush(pushInfo)
|
||||
return !isAuto
|
||||
}
|
||||
|
||||
func ConvertPushInfoToType(pushInfo string) PushType {
|
||||
if IsAutoPush(pushInfo) {
|
||||
return PushType_Auto
|
||||
} else {
|
||||
return PushType_User
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package push_common
|
||||
|
||||
type ServerInfo struct {
|
||||
RevisionHash string `json:"revisionHash"`
|
||||
Time uint32 `json:"time"`
|
||||
Hostname string `json:"hostname"`
|
||||
RedisConnectionConf *RedisConnectionConf `json:"redisConnectionConf"`
|
||||
ActivePushAmount uint32 `json:"activePushAmount"`
|
||||
UptraceInfo *UptraceInfo `json:"uptraceInfo"`
|
||||
}
|
||||
|
||||
type RedisConnectionConf struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Db int `json:"db"`
|
||||
Prefix string `json:"prefix"`
|
||||
}
|
||||
|
||||
type UptraceInfo struct {
|
||||
UptraceOn bool `json:"uptraceOn"`
|
||||
UptraceDSN string `json:"uptraceDSN"`
|
||||
ServiceName string `json:"serviceName"`
|
||||
ServiceVersion string `json:"serviceVersion"`
|
||||
DeploymentEnvironment string `json:"deploymentEnvironment"`
|
||||
}
|
8
util.go
8
util.go
|
@ -5,11 +5,3 @@ import "strconv"
|
|||
func uint32ToString(n uint32) string {
|
||||
return strconv.FormatUint(uint64(n), 10)
|
||||
}
|
||||
|
||||
type UptraceInfo struct {
|
||||
UptraceOn bool `json:"uptraceOn"`
|
||||
UptraceDSN string `json:"uptraceDSN"`
|
||||
ServiceName string `json:"serviceName"`
|
||||
ServiceVersion string `json:"serviceVersion"`
|
||||
DeploymentEnvironment string `json:"deploymentEnvironment"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue