parent
542d479829
commit
25e79e4b77
@ -0,0 +1,65 @@
|
||||
package group
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
pbgroup "github.com/openimsdk/protocol/group"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
)
|
||||
|
||||
func (s *groupServer) SetGroupMute(ctx context.Context, req *pbgroup.SetGroupMuteReq) (*pbgroup.SetGroupMuteResp, error) {
|
||||
opUserID := mcontext.GetOpUserID(ctx)
|
||||
if opUserID == "" {
|
||||
return nil, servererrs.ErrNoPermission.WrapMsg("op user id is empty")
|
||||
}
|
||||
if _, err := s.db.TakeGroupMember(ctx, req.GroupID, opUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.Duration == 0 {
|
||||
return &pbgroup.SetGroupMuteResp{}, s.groupMuteDB.Delete(ctx, opUserID, req.GroupID)
|
||||
}
|
||||
var muteEnd int64
|
||||
if req.Duration != -1 {
|
||||
muteEnd = time.Now().Unix() + req.Duration
|
||||
}
|
||||
return &pbgroup.SetGroupMuteResp{}, s.groupMuteDB.Upsert(ctx, &model.GroupMute{
|
||||
OwnerUserID: opUserID,
|
||||
GroupID: req.GroupID,
|
||||
MuteEndTime: muteEnd,
|
||||
MuteDuration: req.Duration,
|
||||
CreateTime: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *groupServer) GetGroupMute(ctx context.Context, req *pbgroup.GetGroupMuteReq) (*pbgroup.GetGroupMuteResp, error) {
|
||||
opUserID := mcontext.GetOpUserID(ctx)
|
||||
if opUserID == "" {
|
||||
return nil, servererrs.ErrNoPermission.WrapMsg("op user id is empty")
|
||||
}
|
||||
if _, err := s.db.TakeGroupMember(ctx, req.GroupID, opUserID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rec, err := s.groupMuteDB.Get(ctx, opUserID, req.GroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rec == nil {
|
||||
return &pbgroup.GetGroupMuteResp{}, nil
|
||||
}
|
||||
now := time.Now().Unix()
|
||||
if rec.MuteEndTime != 0 && rec.MuteEndTime <= now {
|
||||
return &pbgroup.GetGroupMuteResp{}, nil
|
||||
}
|
||||
duration := rec.MuteDuration
|
||||
if duration == 0 && rec.MuteEndTime == 0 {
|
||||
duration = -1
|
||||
}
|
||||
return &pbgroup.GetGroupMuteResp{
|
||||
Muted: true,
|
||||
MuteEndTime: rec.MuteEndTime,
|
||||
Duration: duration,
|
||||
}, nil
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
)
|
||||
|
||||
// GroupMuteDatabase per-user group notification mute.
|
||||
type GroupMuteDatabase interface {
|
||||
Upsert(ctx context.Context, mute *model.GroupMute) error
|
||||
Delete(ctx context.Context, ownerUserID, groupID string) error
|
||||
ListActiveMutedUserIDs(ctx context.Context, groupID string, candidateUserIDs []string) ([]string, error)
|
||||
Get(ctx context.Context, ownerUserID, groupID string) (*model.GroupMute, error)
|
||||
}
|
||||
|
||||
type groupMuteDatabase struct {
|
||||
db database.GroupMute
|
||||
}
|
||||
|
||||
func NewGroupMuteDatabase(db database.GroupMute) GroupMuteDatabase {
|
||||
return &groupMuteDatabase{db: db}
|
||||
}
|
||||
|
||||
func (g *groupMuteDatabase) Upsert(ctx context.Context, mute *model.GroupMute) error {
|
||||
return g.db.Upsert(ctx, mute)
|
||||
}
|
||||
|
||||
func (g *groupMuteDatabase) Delete(ctx context.Context, ownerUserID, groupID string) error {
|
||||
return g.db.Delete(ctx, ownerUserID, groupID)
|
||||
}
|
||||
|
||||
func (g *groupMuteDatabase) ListActiveMutedUserIDs(ctx context.Context, groupID string, candidateUserIDs []string) ([]string, error) {
|
||||
return g.db.ListActiveMutedUserIDs(ctx, groupID, candidateUserIDs)
|
||||
}
|
||||
|
||||
func (g *groupMuteDatabase) Get(ctx context.Context, ownerUserID, groupID string) (*model.GroupMute, error) {
|
||||
return g.db.Get(ctx, ownerUserID, groupID)
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
)
|
||||
|
||||
// GroupMute persists per-user group notification mute settings.
|
||||
type GroupMute interface {
|
||||
Upsert(ctx context.Context, mute *model.GroupMute) error
|
||||
Delete(ctx context.Context, ownerUserID, groupID string) error
|
||||
// ListActiveMutedUserIDs returns which of candidateUserIDs currently have an active mute on this group.
|
||||
ListActiveMutedUserIDs(ctx context.Context, groupID string, candidateUserIDs []string) ([]string, error)
|
||||
// Get returns one document by owner + group; nil if not found.
|
||||
Get(ctx context.Context, ownerUserID, groupID string) (*model.GroupMute, error)
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package mgo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func NewGroupMuteMongo(db *mongo.Database) (database.GroupMute, error) {
|
||||
coll := db.Collection(database.GroupMuteName)
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "owner_user_id", Value: 1},
|
||||
{Key: "group_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &GroupMuteMgo{coll: coll}, nil
|
||||
}
|
||||
|
||||
type GroupMuteMgo struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (g *GroupMuteMgo) Upsert(ctx context.Context, mute *model.GroupMute) error {
|
||||
if mute.CreateTime.IsZero() {
|
||||
mute.CreateTime = time.Now()
|
||||
}
|
||||
filter := bson.M{
|
||||
"owner_user_id": mute.OwnerUserID,
|
||||
"group_id": mute.GroupID,
|
||||
}
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"mute_end_time": mute.MuteEndTime,
|
||||
"mute_duration": mute.MuteDuration,
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
"owner_user_id": mute.OwnerUserID,
|
||||
"group_id": mute.GroupID,
|
||||
"create_time": mute.CreateTime,
|
||||
},
|
||||
}
|
||||
_, err := g.coll.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true))
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (g *GroupMuteMgo) Delete(ctx context.Context, ownerUserID, groupID string) error {
|
||||
_, err := g.coll.DeleteOne(ctx, bson.M{
|
||||
"owner_user_id": ownerUserID,
|
||||
"group_id": groupID,
|
||||
})
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (g *GroupMuteMgo) ListActiveMutedUserIDs(ctx context.Context, groupID string, candidateUserIDs []string) ([]string, error) {
|
||||
if len(candidateUserIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
now := time.Now().Unix()
|
||||
filter := bson.M{
|
||||
"group_id": groupID,
|
||||
"owner_user_id": bson.M{"$in": candidateUserIDs},
|
||||
"$or": bson.A{
|
||||
bson.M{"mute_end_time": 0},
|
||||
bson.M{"mute_end_time": bson.M{"$gt": now}},
|
||||
},
|
||||
}
|
||||
cur, err := g.coll.Find(ctx, filter, options.Find().SetProjection(bson.M{"owner_user_id": 1, "_id": 0}))
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
defer cur.Close(ctx)
|
||||
var out []string
|
||||
for cur.Next(ctx) {
|
||||
var doc struct {
|
||||
OwnerUserID string `bson:"owner_user_id"`
|
||||
}
|
||||
if err := cur.Decode(&doc); err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
out = append(out, doc.OwnerUserID)
|
||||
}
|
||||
return out, cur.Err()
|
||||
}
|
||||
|
||||
func (g *GroupMuteMgo) Get(ctx context.Context, ownerUserID, groupID string) (*model.GroupMute, error) {
|
||||
var out model.GroupMute
|
||||
err := g.coll.FindOne(ctx, bson.M{
|
||||
"owner_user_id": ownerUserID,
|
||||
"group_id": groupID,
|
||||
}).Decode(&out)
|
||||
if err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// GroupMute is per-user mute of group message notifications (e.g. offline push).
|
||||
// OwnerUserID must be a group member; MuteEndTime 0 means permanent.
|
||||
// MuteDuration is the configured interval at set time: -1 permanent, >0 seconds.
|
||||
type GroupMute struct {
|
||||
OwnerUserID string `bson:"owner_user_id"`
|
||||
GroupID string `bson:"group_id"`
|
||||
MuteEndTime int64 `bson:"mute_end_time"` // Unix seconds; 0 = permanent
|
||||
MuteDuration int64 `bson:"mute_duration"` // -1 permanent, >0 seconds
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
Loading…
Reference in new issue