diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 0bff88e..9ef6f4d 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,7 +4,14 @@
-
+
+
+
+
+
+
+
+
@@ -27,7 +34,7 @@
-
+
{
"customColor": "",
@@ -38,34 +45,34 @@
- {
- "keyToString": {
- "DefaultGoTemplateProperty": "Go File",
- "Go Build.Backend.executor": "Run",
- "Go 构建.Backend.executor": "Run",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "RunOnceActivity.go.formatter.settings.were.checked": "true",
- "RunOnceActivity.go.migrated.go.modules.settings": "true",
- "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
- "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
- "git-widget-placeholder": "refactor/dealer",
- "go.import.settings.migrated": "true",
- "go.sdk.automatically.set": "true",
- "last_opened_file_path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/src/components/admin",
- "node.js.detected.package.eslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "run.code.analysis.last.selected.profile": "pProject Default",
- "settings.editor.selected.configurable": "preferences.pluginManager",
- "ts.external.directory.path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
diff --git a/go.mod b/go.mod
index 3492e42..98f552f 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ toolchain go1.22.1
require (
firebase.google.com/go v3.13.0+incompatible
- git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951
+ git.solsynth.dev/hydrogen/dealer v0.0.0-20240717054512-da433c88615a
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745
github.com/go-playground/validator/v10 v10.17.0
github.com/gofiber/fiber/v2 v2.52.4
@@ -21,10 +21,9 @@ require (
github.com/sideshow/apns2 v0.23.0
github.com/spf13/viper v1.18.2
github.com/sujit-baniya/flash v0.1.8
- golang.org/x/crypto v0.24.0
+ golang.org/x/crypto v0.25.0
google.golang.org/api v0.183.0
- google.golang.org/grpc v1.64.0
- google.golang.org/protobuf v1.34.2
+ google.golang.org/grpc v1.65.0
gorm.io/datatypes v1.2.0
gorm.io/driver/postgres v1.5.4
gorm.io/gorm v1.25.6
@@ -108,16 +107,17 @@ require (
go.opentelemetry.io/otel/trace v1.27.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
- golang.org/x/net v0.26.0 // indirect
+ golang.org/x/net v0.27.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
- golang.org/x/sys v0.21.0 // indirect
+ golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect
+ google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.2 // indirect
diff --git a/go.sum b/go.sum
index 776d28f..ac229f6 100644
--- a/go.sum
+++ b/go.sum
@@ -17,20 +17,8 @@ cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RB
cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80=
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715120403-4e96bb2cd519 h1:HR0JxkVIeN8xyasy99a0i+Vfy46uW1KthPVamCjOTPg=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715120403-4e96bb2cd519/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715142037-d7f5053fc74b h1:7pwMvP+zfl5rn08+Wg1rtcSqq1MtEN72wEmluvhBYIA=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715142037-d7f5053fc74b/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715153944-44861dc01ffb h1:8/dP5qj47UPD9TZFkYH1syRCHSUo16TDutcuMK13eQY=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715153944-44861dc01ffb/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154151-74c9ce063b4e h1:mkV/bshMqDTA3jUwsbb3MxN0d+U0I38S/teeRMoPNsk=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154151-74c9ce063b4e/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154526-59bda7a4117a h1:ozV2DWlcSCLfq3941W6C7vVGlgIQ9PH2TXfnHvSms4o=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154526-59bda7a4117a/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154745-ab0b491f45ff h1:Bzcu+n1YFD09SGoGxuFnqT56u3kK66sQ/vF8PEhbPJQ=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240715154745-ab0b491f45ff/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951 h1:RgZJK4PXhrjhUX75BclBCg2xfetMkswcMwMqfTBtryQ=
-git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
+git.solsynth.dev/hydrogen/dealer v0.0.0-20240717054512-da433c88615a h1:08YaBgZtkrPfiw08l4RjtKI1fdt6wlHc3Ea7NDFtLPg=
+git.solsynth.dev/hydrogen/dealer v0.0.0-20240717054512-da433c88615a/go.mod h1:oPdUxLy6TFeRxiRC/BoNb3YUNcnSiOnJrzFTnCPSoCA=
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745 h1:40BUsQMNXjqHyytkyF9py1HjTAWlRgO6R57YXUrHNy4=
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745/go.mod h1:FsQGSLTl0gvo+9Jmbot02S72suyF9tFTrzDj70Xhifo=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -409,8 +397,8 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
+golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
+golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
@@ -436,8 +424,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
-golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
-golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
+golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
@@ -483,8 +471,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
@@ -525,15 +513,15 @@ google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 h1:HCZ6DlkKtCDAtD8
google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU=
google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
-google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
+google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
+google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/pkg/internal/grpc/notifier.go b/pkg/internal/grpc/notifier.go
index 9c6476f..bad598b 100644
--- a/pkg/internal/grpc/notifier.go
+++ b/pkg/internal/grpc/notifier.go
@@ -3,7 +3,9 @@ package grpc
import (
"context"
"fmt"
+ "git.solsynth.dev/hydrogen/passport/pkg/internal/database"
jsoniter "github.com/json-iterator/go"
+ "github.com/samber/lo"
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
"git.solsynth.dev/hydrogen/passport/pkg/internal/models"
@@ -45,3 +47,82 @@ func (v *Server) NotifyUser(_ context.Context, in *proto.NotifyUserRequest) (*pr
IsSuccess: true,
}, nil
}
+
+func (v *Server) NotifyUserBatch(_ context.Context, in *proto.NotifyUserBatchRequest) (*proto.NotifyResponse, error) {
+ var err error
+ var users []models.Account
+ if users, err = services.GetAccountList(lo.Map(in.GetUserId(), func(item uint64, index int) uint {
+ return uint(item)
+ })); err != nil {
+ return nil, fmt.Errorf("unable to get account: %v", err)
+ }
+
+ var metadata map[string]any
+ _ = jsoniter.Unmarshal(in.GetNotify().GetMetadata(), &metadata)
+
+ var notifications []models.Notification
+ for _, user := range users {
+ notification := models.Notification{
+ Topic: in.GetNotify().GetTopic(),
+ Title: in.GetNotify().GetTitle(),
+ Subtitle: in.GetNotify().Subtitle,
+ Body: in.GetNotify().GetBody(),
+ Metadata: metadata,
+ IsRealtime: in.GetNotify().GetIsRealtime(),
+ IsForcePush: in.GetNotify().GetIsForcePush(),
+ AccountID: user.ID,
+ }
+
+ notifications = append(notifications, notification)
+ }
+
+ if in.GetNotify().GetIsRealtime() {
+ services.PushNotificationBatch(notifications)
+ } else {
+ if err := services.NewNotificationBatch(notifications); err != nil {
+ return nil, err
+ }
+ }
+
+ return &proto.NotifyResponse{
+ IsSuccess: true,
+ }, nil
+}
+
+func (v *Server) NotifyAllUser(_ context.Context, in *proto.NotifyRequest) (*proto.NotifyResponse, error) {
+ var users []models.Account
+ if err := database.C.Find(&users).Error; err != nil {
+ return nil, fmt.Errorf("unable to get account: %v", err)
+ }
+
+ var metadata map[string]any
+ _ = jsoniter.Unmarshal(in.GetMetadata(), &metadata)
+
+ var notifications []models.Notification
+ for _, user := range users {
+ notification := models.Notification{
+ Topic: in.GetTopic(),
+ Title: in.GetTitle(),
+ Subtitle: in.Subtitle,
+ Body: in.GetBody(),
+ Metadata: metadata,
+ IsRealtime: in.GetIsRealtime(),
+ IsForcePush: in.GetIsForcePush(),
+ AccountID: user.ID,
+ }
+
+ notifications = append(notifications, notification)
+ }
+
+ if in.GetIsRealtime() {
+ services.PushNotificationBatch(notifications)
+ } else {
+ if err := services.NewNotificationBatch(notifications); err != nil {
+ return nil, err
+ }
+ }
+
+ return &proto.NotifyResponse{
+ IsSuccess: true,
+ }, nil
+}
diff --git a/pkg/internal/services/accounts.go b/pkg/internal/services/accounts.go
index e6cbc38..58c70a0 100644
--- a/pkg/internal/services/accounts.go
+++ b/pkg/internal/services/accounts.go
@@ -25,6 +25,15 @@ func GetAccount(id uint) (models.Account, error) {
return account, nil
}
+func GetAccountList(id []uint) ([]models.Account, error) {
+ var accounts []models.Account
+ if err := database.C.Where("id IN ?", id).Find(&accounts).Error; err != nil {
+ return accounts, err
+ }
+
+ return accounts, nil
+}
+
func GetAccountWithName(alias string) (models.Account, error) {
var account models.Account
if err := database.C.Where(models.Account{
diff --git a/pkg/internal/services/notifications.go b/pkg/internal/services/notifications.go
index ba70bc3..d6f5148 100644
--- a/pkg/internal/services/notifications.go
+++ b/pkg/internal/services/notifications.go
@@ -6,6 +6,7 @@ import (
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
"git.solsynth.dev/hydrogen/passport/pkg/internal/gap"
"reflect"
+ "sync"
"time"
"firebase.google.com/go/messaging"
@@ -60,6 +61,15 @@ func NewNotification(notification models.Notification) error {
return nil
}
+func NewNotificationBatch(notifications []models.Notification) error {
+ if err := database.C.CreateInBatches(notifications, 1000).Error; err != nil {
+ return err
+ }
+
+ PushNotificationBatch(notifications)
+ return nil
+}
+
// PushNotification will push the notification whatever it exists record in the
// database Recommend pushing another goroutine when you need to push a lot of
// notifications And just use a block statement when you just push one
@@ -153,3 +163,15 @@ func PushNotification(notification models.Notification) error {
return nil
}
+
+func PushNotificationBatch(notifications []models.Notification) {
+ var wg sync.WaitGroup
+ for _, notification := range notifications {
+ wg.Add(1)
+ item := notification
+ go func() {
+ _ = PushNotification(item)
+ wg.Done()
+ }()
+ }
+}