复制项目
This commit is contained in:
103
pkg/common/db/model/admin/admin.go
Normal file
103
pkg/common/db/model/admin/admin.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"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 NewAdmin(db *mongo.Database) (admindb.AdminInterface, error) {
|
||||
coll := db.Collection("admin")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "account", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Admin{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Admin struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Admin) Take(ctx context.Context, account string) (*admindb.Admin, error) {
|
||||
return mongoutil.FindOne[*admindb.Admin](ctx, o.coll, bson.M{"account": account})
|
||||
}
|
||||
|
||||
func (o *Admin) TakeUserID(ctx context.Context, userID string) (*admindb.Admin, error) {
|
||||
return mongoutil.FindOne[*admindb.Admin](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *Admin) Update(ctx context.Context, account string, update map[string]any) error {
|
||||
if len(update) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": account}, bson.M{"$set": update}, false)
|
||||
}
|
||||
|
||||
func (o *Admin) Create(ctx context.Context, admins []*admindb.Admin) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, admins)
|
||||
}
|
||||
|
||||
func (o *Admin) ChangePassword(ctx context.Context, userID string, newPassword string) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"password": newPassword}}, false)
|
||||
}
|
||||
|
||||
func (o *Admin) ChangeOperationPassword(ctx context.Context, userID string, newPassword string) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"operation_password": newPassword}}, false)
|
||||
}
|
||||
|
||||
func (o *Admin) ClearGoogleAuthKey(ctx context.Context, userID string) error {
|
||||
// 使用 $unset 删除字段,确保字段被完全移除
|
||||
// 注意:$unset 操作符的值可以是任意值(通常使用空字符串或1),MongoDB 会忽略值,只删除字段
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$unset": bson.M{"google_auth_key": 1}}, false)
|
||||
}
|
||||
|
||||
func (o *Admin) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Admin) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.Admin, error) {
|
||||
opt := options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}})
|
||||
filter := bson.M{}
|
||||
|
||||
// 如果有关键词,则进行模糊搜索(账号、昵称、用户ID)
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"nickname": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
|
||||
return mongoutil.FindPage[*admindb.Admin](ctx, o.coll, filter, pagination, opt)
|
||||
}
|
||||
95
pkg/common/db/model/admin/applet.go
Normal file
95
pkg/common/db/model/admin/applet.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/constant"
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewApplet(db *mongo.Database) (admin.AppletInterface, error) {
|
||||
coll := db.Collection("applet")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Applet{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Applet struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Applet) Create(ctx context.Context, applets []*admin.Applet) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, applets)
|
||||
}
|
||||
|
||||
func (o *Applet) Del(ctx context.Context, ids []string) error {
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"id": bson.M{"$in": ids}})
|
||||
}
|
||||
|
||||
func (o *Applet) Update(ctx context.Context, id string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"id": id}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Applet) Take(ctx context.Context, id string) (*admin.Applet, error) {
|
||||
return mongoutil.FindOne[*admin.Applet](ctx, o.coll, bson.M{"id": id})
|
||||
}
|
||||
|
||||
func (o *Applet) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admin.Applet, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
if keyword != "" {
|
||||
filter = bson.M{
|
||||
"$or": []bson.M{
|
||||
{"name": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"app_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"version": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*admin.Applet](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *Applet) FindOnShelf(ctx context.Context) ([]*admin.Applet, error) {
|
||||
return mongoutil.Find[*admin.Applet](ctx, o.coll, bson.M{"status": constant.StatusOnShelf})
|
||||
}
|
||||
|
||||
func (o *Applet) FindID(ctx context.Context, ids []string) ([]*admin.Applet, error) {
|
||||
return mongoutil.Find[*admin.Applet](ctx, o.coll, bson.M{"id": bson.M{"$in": ids}})
|
||||
}
|
||||
84
pkg/common/db/model/admin/application.go
Normal file
84
pkg/common/db/model/admin/application.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func NewApplication(db *mongo.Database) (admindb.ApplicationInterface, error) {
|
||||
coll := db.Collection("application")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "platform", Value: 1},
|
||||
{Key: "version", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "latest", Value: -1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ApplicationMgo{coll: coll}, nil
|
||||
}
|
||||
|
||||
type ApplicationMgo struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) sort() any {
|
||||
return bson.D{{"latest", -1}, {"_id", -1}}
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) LatestVersion(ctx context.Context, platform string) (*admin.Application, error) {
|
||||
return mongoutil.FindOne[*admin.Application](ctx, a.coll, bson.M{"platform": platform}, options.FindOne().SetSort(a.sort()))
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) AddVersion(ctx context.Context, val *admin.Application) error {
|
||||
if val.ID.IsZero() {
|
||||
val.ID = primitive.NewObjectID()
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, a.coll, []*admin.Application{val})
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) UpdateVersion(ctx context.Context, id primitive.ObjectID, update map[string]any) error {
|
||||
if len(update) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, a.coll, bson.M{"_id": id}, bson.M{"$set": update}, true)
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) DeleteVersion(ctx context.Context, id []primitive.ObjectID) error {
|
||||
if len(id) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, a.coll, bson.M{"_id": bson.M{"$in": id}})
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) PageVersion(ctx context.Context, platforms []string, page pagination.Pagination) (int64, []*admin.Application, error) {
|
||||
filter := bson.M{}
|
||||
if len(platforms) > 0 {
|
||||
filter["platform"] = bson.M{"$in": platforms}
|
||||
}
|
||||
return mongoutil.FindPage[*admin.Application](ctx, a.coll, filter, page, options.Find().SetSort(a.sort()))
|
||||
}
|
||||
|
||||
func (a *ApplicationMgo) FindPlatform(ctx context.Context, id []primitive.ObjectID) ([]string, error) {
|
||||
if len(id) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return mongoutil.Find[string](ctx, a.coll, bson.M{"_id": bson.M{"$in": id}}, options.Find().SetProjection(bson.M{"_id": 0, "platform": 1}))
|
||||
}
|
||||
77
pkg/common/db/model/admin/client_config.go
Normal file
77
pkg/common/db/model/admin/client_config.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewClientConfig(db *mongo.Database) (admin.ClientConfigInterface, error) {
|
||||
coll := db.Collection("client_config")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "key", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &ClientConfig{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *ClientConfig) Set(ctx context.Context, config map[string]string) error {
|
||||
for key, value := range config {
|
||||
filter := bson.M{"key": key}
|
||||
update := bson.M{
|
||||
"value": value,
|
||||
}
|
||||
err := mongoutil.UpdateOne(ctx, o.coll, filter, bson.M{"$set": update}, false, options.Update().SetUpsert(true))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ClientConfig) Del(ctx context.Context, keys []string) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"key": bson.M{"$in": keys}})
|
||||
}
|
||||
|
||||
func (o *ClientConfig) Get(ctx context.Context) (map[string]string, error) {
|
||||
cs, err := mongoutil.Find[*admin.ClientConfig](ctx, o.coll, bson.M{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cm := make(map[string]string)
|
||||
for _, config := range cs {
|
||||
cm[config.Key] = config.Value
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
86
pkg/common/db/model/admin/forbidden_account.go
Normal file
86
pkg/common/db/model/admin/forbidden_account.go
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewForbiddenAccount(db *mongo.Database) (admin.ForbiddenAccountInterface, error) {
|
||||
coll := db.Collection("forbidden_account")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &ForbiddenAccount{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ForbiddenAccount struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) Create(ctx context.Context, ms []*admin.ForbiddenAccount) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, ms)
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) Take(ctx context.Context, userID string) (*admin.ForbiddenAccount, error) {
|
||||
return mongoutil.FindOne[*admin.ForbiddenAccount](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) Find(ctx context.Context, userIDs []string) ([]*admin.ForbiddenAccount, error) {
|
||||
return mongoutil.Find[*admin.ForbiddenAccount](ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admin.ForbiddenAccount, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
if keyword != "" {
|
||||
filter = bson.M{
|
||||
"$or": []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"reason": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"operator_user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*admin.ForbiddenAccount](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *ForbiddenAccount) FindAllIDs(ctx context.Context) ([]string, error) {
|
||||
return mongoutil.Find[string](ctx, o.coll, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
|
||||
}
|
||||
99
pkg/common/db/model/admin/invitation_register.go
Normal file
99
pkg/common/db/model/admin/invitation_register.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/constant"
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewInvitationRegister(db *mongo.Database) (admindb.InvitationRegisterInterface, error) {
|
||||
coll := db.Collection("invitation_register")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "invitation_code", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &InvitationRegister{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type InvitationRegister struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Find(ctx context.Context, codes []string) ([]*admindb.InvitationRegister, error) {
|
||||
return mongoutil.Find[*admindb.InvitationRegister](ctx, o.coll, bson.M{"invitation_code": bson.M{"$in": codes}})
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Del(ctx context.Context, codes []string) error {
|
||||
if len(codes) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"invitation_code": bson.M{"$in": codes}})
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Create(ctx context.Context, v []*admindb.InvitationRegister) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, v)
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Take(ctx context.Context, code string) (*admindb.InvitationRegister, error) {
|
||||
return mongoutil.FindOne[*admindb.InvitationRegister](ctx, o.coll, bson.M{"code": code})
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Update(ctx context.Context, code string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"invitation_code": code}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *InvitationRegister) Search(ctx context.Context, keyword string, state int32, userIDs []string, codes []string, pagination pagination.Pagination) (int64, []*admindb.InvitationRegister, error) {
|
||||
filter := bson.M{}
|
||||
switch state {
|
||||
case constant.InvitationCodeUsed:
|
||||
filter = bson.M{"user_id": bson.M{"$ne": ""}}
|
||||
case constant.InvitationCodeUnused:
|
||||
filter = bson.M{"user_id": ""}
|
||||
}
|
||||
|
||||
if len(userIDs) > 0 {
|
||||
filter["user_id"] = bson.M{"$in": userIDs}
|
||||
}
|
||||
if len(codes) > 0 {
|
||||
filter["invitation_code"] = bson.M{"$in": codes}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"invitation_code": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*admindb.InvitationRegister](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
95
pkg/common/db/model/admin/ip_forbidden.go
Normal file
95
pkg/common/db/model/admin/ip_forbidden.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/constant"
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewIPForbidden(db *mongo.Database) (admindb.IPForbiddenInterface, error) {
|
||||
coll := db.Collection("ip_forbidden")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "ip", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &IPForbidden{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type IPForbidden struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *IPForbidden) Take(ctx context.Context, ip string) (*admindb.IPForbidden, error) {
|
||||
return mongoutil.FindOne[*admindb.IPForbidden](ctx, o.coll, bson.M{"ip": ip})
|
||||
}
|
||||
|
||||
func (o *IPForbidden) Find(ctx context.Context, ips []string) ([]*admindb.IPForbidden, error) {
|
||||
return mongoutil.Find[*admindb.IPForbidden](ctx, o.coll, bson.M{"ip": bson.M{"$in": ips}})
|
||||
}
|
||||
|
||||
func (o *IPForbidden) Search(ctx context.Context, keyword string, state int32, pagination pagination.Pagination) (int64, []*admindb.IPForbidden, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
switch state {
|
||||
case constant.LimitNil:
|
||||
case constant.LimitEmpty:
|
||||
filter = bson.M{"limit_register": 0, "limit_login": 0}
|
||||
case constant.LimitOnlyRegisterIP:
|
||||
filter = bson.M{"limit_register": 1, "limit_login": 0}
|
||||
case constant.LimitOnlyLoginIP:
|
||||
filter = bson.M{"limit_register": 0, "limit_login": 1}
|
||||
case constant.LimitRegisterIP:
|
||||
filter = bson.M{"limit_register": 1}
|
||||
case constant.LimitLoginIP:
|
||||
filter = bson.M{"limit_login": 1}
|
||||
case constant.LimitLoginRegisterIP:
|
||||
filter = bson.M{"limit_register": 1, "limit_login": 1}
|
||||
}
|
||||
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"ip": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*admindb.IPForbidden](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *IPForbidden) Create(ctx context.Context, ms []*admindb.IPForbidden) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, ms)
|
||||
}
|
||||
|
||||
func (o *IPForbidden) Delete(ctx context.Context, ips []string) error {
|
||||
if len(ips) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"ip": bson.M{"$in": ips}})
|
||||
}
|
||||
93
pkg/common/db/model/admin/limit_user_login_ip.go
Normal file
93
pkg/common/db/model/admin/limit_user_login_ip.go
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewLimitUserLoginIP(db *mongo.Database) (admin.LimitUserLoginIPInterface, error) {
|
||||
coll := db.Collection("limit_user_login_ip")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "ip", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &LimitUserLoginIP{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type LimitUserLoginIP struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) Create(ctx context.Context, ms []*admin.LimitUserLoginIP) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, ms)
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) Delete(ctx context.Context, ms []*admin.LimitUserLoginIP) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, o.limitUserLoginIPFilter(ms))
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) Count(ctx context.Context, userID string) (uint32, error) {
|
||||
count, err := mongoutil.Count(ctx, o.coll, bson.M{"user_id": userID})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(count), nil
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) Take(ctx context.Context, userID string, ip string) (*admin.LimitUserLoginIP, error) {
|
||||
return mongoutil.FindOne[*admin.LimitUserLoginIP](ctx, o.coll, bson.M{"user_id": userID, "ip": ip})
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admin.LimitUserLoginIP, error) {
|
||||
filter := bson.M{
|
||||
"$or": []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"ip": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
},
|
||||
}
|
||||
return mongoutil.FindPage[*admin.LimitUserLoginIP](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *LimitUserLoginIP) limitUserLoginIPFilter(ips []*admin.LimitUserLoginIP) bson.M {
|
||||
if len(ips) == 0 {
|
||||
return nil
|
||||
}
|
||||
or := make(bson.A, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
or = append(or, bson.M{
|
||||
"user_id": ip.UserID,
|
||||
"ip": ip.IP,
|
||||
})
|
||||
}
|
||||
return bson.M{"$or": or}
|
||||
}
|
||||
76
pkg/common/db/model/admin/register_add_friend.go
Normal file
76
pkg/common/db/model/admin/register_add_friend.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewRegisterAddFriend(db *mongo.Database) (admin.RegisterAddFriendInterface, error) {
|
||||
coll := db.Collection("register_add_friend")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &RegisterAddFriend{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type RegisterAddFriend struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *RegisterAddFriend) Add(ctx context.Context, registerAddFriends []*admin.RegisterAddFriend) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, registerAddFriends)
|
||||
}
|
||||
|
||||
func (o *RegisterAddFriend) Del(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *RegisterAddFriend) FindUserID(ctx context.Context, userIDs []string) ([]string, error) {
|
||||
filter := bson.M{}
|
||||
if len(userIDs) > 0 {
|
||||
filter["user_id"] = bson.M{"$in": userIDs}
|
||||
}
|
||||
return mongoutil.Find[string](ctx, o.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
|
||||
}
|
||||
|
||||
func (o *RegisterAddFriend) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admin.RegisterAddFriend, error) {
|
||||
filter := bson.M{"user_id": bson.M{"$regex": keyword, "$options": "i"}}
|
||||
return mongoutil.FindPage[*admin.RegisterAddFriend](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *RegisterAddFriend) CountTotal(ctx context.Context) (int64, error) {
|
||||
return mongoutil.Count(ctx, o.coll, bson.M{})
|
||||
}
|
||||
90
pkg/common/db/model/admin/register_add_group.go
Normal file
90
pkg/common/db/model/admin/register_add_group.go
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewRegisterAddGroup(db *mongo.Database) (admin.RegisterAddGroupInterface, error) {
|
||||
coll := db.Collection("register_add_group")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "group_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &RegisterAddGroup{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type RegisterAddGroup struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) Add(ctx context.Context, registerAddGroups []*admin.RegisterAddGroup) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, registerAddGroups)
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) Del(ctx context.Context, groupIDs []string) error {
|
||||
if len(groupIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) FindGroupID(ctx context.Context, groupIDs []string) ([]string, error) {
|
||||
filter := bson.M{}
|
||||
if len(groupIDs) > 0 {
|
||||
filter["group_id"] = bson.M{"$in": groupIDs}
|
||||
}
|
||||
return mongoutil.Find[string](ctx, o.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admin.RegisterAddGroup, error) {
|
||||
filter := bson.M{"group_id": bson.M{"$regex": keyword, "$options": "i"}}
|
||||
return mongoutil.FindPage[*admin.RegisterAddGroup](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) CountTotal(ctx context.Context) (int64, error) {
|
||||
return mongoutil.Count(ctx, o.coll, bson.M{})
|
||||
}
|
||||
|
||||
func (o *RegisterAddGroup) CountToday(ctx context.Context) (int64, error) {
|
||||
now := time.Now()
|
||||
todayStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
todayEnd := todayStart.Add(24 * time.Hour)
|
||||
filter := bson.M{
|
||||
"create_time": bson.M{
|
||||
"$gte": todayStart,
|
||||
"$lt": todayEnd,
|
||||
},
|
||||
}
|
||||
return mongoutil.Count(ctx, o.coll, filter)
|
||||
}
|
||||
65
pkg/common/db/model/bot/agent.go
Normal file
65
pkg/common/db/model/bot/agent.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/bot"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"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 NewAgent(db *mongo.Database) (bot.AgentInterface, error) {
|
||||
coll := db.Collection("agent")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Agent{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Agent struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Agent) Create(ctx context.Context, elems ...*bot.Agent) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, elems)
|
||||
}
|
||||
|
||||
func (o *Agent) Take(ctx context.Context, userId string) (*bot.Agent, error) {
|
||||
return mongoutil.FindOne[*bot.Agent](ctx, o.coll, bson.M{"user_id": userId})
|
||||
}
|
||||
|
||||
func (o *Agent) Find(ctx context.Context, userIDs []string) ([]*bot.Agent, error) {
|
||||
return mongoutil.Find[*bot.Agent](ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Agent) Update(ctx context.Context, userID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Agent) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Agent) Page(ctx context.Context, userIDs []string, pagination pagination.Pagination) (int64, []*bot.Agent, error) {
|
||||
filter := bson.M{}
|
||||
if len(userIDs) > 0 {
|
||||
filter["user_id"] = bson.M{"$in": userIDs}
|
||||
}
|
||||
return mongoutil.FindPage[*bot.Agent](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
50
pkg/common/db/model/bot/conversation_resp_id.go
Normal file
50
pkg/common/db/model/bot/conversation_resp_id.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/bot"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"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 NewConversationRespID(db *mongo.Database) (bot.ConversationRespIDInterface, error) {
|
||||
coll := db.Collection("conversation_resp_id")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "conversation_id", Value: 1},
|
||||
{Key: "agent_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &ConversationRespID{coll: coll}, nil
|
||||
}
|
||||
|
||||
type ConversationRespID struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *ConversationRespID) Create(ctx context.Context, elems ...*bot.ConversationRespID) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, elems)
|
||||
}
|
||||
|
||||
func (o *ConversationRespID) Take(ctx context.Context, convID, agentID string) (*bot.ConversationRespID, error) {
|
||||
return mongoutil.FindOne[*bot.ConversationRespID](ctx, o.coll, bson.M{"conversation_id": convID, "agent_id": agentID})
|
||||
}
|
||||
|
||||
func (o *ConversationRespID) Update(ctx context.Context, convID, agentID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"conversation_id": convID, "agent_id": agentID}, bson.M{"$set": data}, false, options.Update().SetUpsert(true))
|
||||
}
|
||||
|
||||
func (o *ConversationRespID) Delete(ctx context.Context, convID, agentID string) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"conversation_id": convID, "agent_id": agentID})
|
||||
}
|
||||
72
pkg/common/db/model/chat/account.go
Normal file
72
pkg/common/db/model/chat/account.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewAccount(db *mongo.Database) (chat.AccountInterface, error) {
|
||||
coll := db.Collection("account")
|
||||
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Account{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Account) Create(ctx context.Context, accounts ...*chat.Account) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, accounts)
|
||||
}
|
||||
|
||||
func (o *Account) Take(ctx context.Context, userId string) (*chat.Account, error) {
|
||||
return mongoutil.FindOne[*chat.Account](ctx, o.coll, bson.M{"user_id": userId})
|
||||
}
|
||||
|
||||
func (o *Account) Update(ctx context.Context, userID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Account) UpdatePassword(ctx context.Context, userId string, password string) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userId}, bson.M{"$set": bson.M{"password": password, "change_time": time.Now()}}, false)
|
||||
}
|
||||
|
||||
func (o *Account) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
247
pkg/common/db/model/chat/attribute.go
Normal file
247
pkg/common/db/model/chat/attribute.go
Normal file
@@ -0,0 +1,247 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewAttribute(db *mongo.Database) (chat.AttributeInterface, error) {
|
||||
coll := db.Collection("attribute")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "account", Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "email", Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "area_code", Value: 1},
|
||||
{Key: "phone_number", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Attribute{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Attribute struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Attribute) Create(ctx context.Context, attribute ...*chat.Attribute) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, attribute)
|
||||
}
|
||||
|
||||
func (o *Attribute) Update(ctx context.Context, userID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Attribute) Find(ctx context.Context, userIds []string) ([]*chat.Attribute, error) {
|
||||
return mongoutil.Find[*chat.Attribute](ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIds}})
|
||||
}
|
||||
|
||||
func (o *Attribute) FindAccount(ctx context.Context, accounts []string) ([]*chat.Attribute, error) {
|
||||
return mongoutil.Find[*chat.Attribute](ctx, o.coll, bson.M{"account": bson.M{"$in": accounts}})
|
||||
}
|
||||
|
||||
func (o *Attribute) FindPhone(ctx context.Context, phoneNumbers []string) ([]*chat.Attribute, error) {
|
||||
return mongoutil.Find[*chat.Attribute](ctx, o.coll, bson.M{"phone_number": bson.M{"$in": phoneNumbers}})
|
||||
}
|
||||
|
||||
func (o *Attribute) Search(ctx context.Context, keyword string, genders []int32, pagination pagination.Pagination) (int64, []*chat.Attribute, error) {
|
||||
filter := bson.M{}
|
||||
if len(genders) > 0 {
|
||||
filter["gender"] = bson.M{
|
||||
"$in": genders,
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"nickname": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"phone_number": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Attribute](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *Attribute) TakePhone(ctx context.Context, areaCode string, phoneNumber string) (*chat.Attribute, error) {
|
||||
return mongoutil.FindOne[*chat.Attribute](ctx, o.coll, bson.M{"area_code": areaCode, "phone_number": phoneNumber})
|
||||
}
|
||||
|
||||
func (o *Attribute) TakeEmail(ctx context.Context, email string) (*chat.Attribute, error) {
|
||||
return mongoutil.FindOne[*chat.Attribute](ctx, o.coll, bson.M{"email": email})
|
||||
}
|
||||
|
||||
func (o *Attribute) TakeAccount(ctx context.Context, account string) (*chat.Attribute, error) {
|
||||
return mongoutil.FindOne[*chat.Attribute](ctx, o.coll, bson.M{"account": account})
|
||||
}
|
||||
|
||||
func (o *Attribute) Take(ctx context.Context, userID string) (*chat.Attribute, error) {
|
||||
return mongoutil.FindOne[*chat.Attribute](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *Attribute) SearchNormalUser(ctx context.Context, keyword string, forbiddenIDs []string, gender int32, startTime, endTime *time.Time, pagination pagination.Pagination) (int64, []*chat.Attribute, error) {
|
||||
filter := bson.M{}
|
||||
if gender == 0 {
|
||||
filter["gender"] = bson.M{
|
||||
"$in": []int32{0, 1, 2},
|
||||
}
|
||||
} else {
|
||||
filter["gender"] = gender
|
||||
}
|
||||
if len(forbiddenIDs) > 0 {
|
||||
filter["user_id"] = bson.M{
|
||||
"$nin": forbiddenIDs,
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"nickname": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"phone_number": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"email": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
// 注册时间范围查询
|
||||
if startTime != nil || endTime != nil {
|
||||
timeFilter := bson.M{}
|
||||
if startTime != nil {
|
||||
timeFilter["$gte"] = *startTime
|
||||
}
|
||||
if endTime != nil {
|
||||
// 使用 $lt(小于)而不是 $lte,确保不包含结束时间当天的数据
|
||||
// 例如:endTime="2025-11-02 00:00:00" 应该查询到 2025-11-01 23:59:59,不包含 11月2日的数据
|
||||
timeFilter["$lt"] = *endTime
|
||||
}
|
||||
if len(timeFilter) > 0 {
|
||||
filter["create_time"] = timeFilter
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Attribute](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
// SearchNormalUserWithUserIDs 按条件搜索用户(支持额外的userIDs过滤)
|
||||
func (o *Attribute) SearchNormalUserWithUserIDs(ctx context.Context, keyword string, forbiddenIDs []string, gender int32, startTime, endTime *time.Time, userIDs []string, pagination pagination.Pagination) (int64, []*chat.Attribute, error) {
|
||||
filter := bson.M{}
|
||||
if gender == 0 {
|
||||
filter["gender"] = bson.M{
|
||||
"$in": []int32{0, 1, 2},
|
||||
}
|
||||
} else {
|
||||
filter["gender"] = gender
|
||||
}
|
||||
|
||||
// 构建user_id过滤条件:需要同时满足在userIDs中,且不在forbiddenIDs中
|
||||
userIDConditions := []bson.M{}
|
||||
if len(userIDs) > 0 {
|
||||
userIDConditions = append(userIDConditions, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
if len(forbiddenIDs) > 0 {
|
||||
userIDConditions = append(userIDConditions, bson.M{"user_id": bson.M{"$nin": forbiddenIDs}})
|
||||
}
|
||||
if len(userIDConditions) > 0 {
|
||||
if len(userIDConditions) == 1 {
|
||||
filter["user_id"] = userIDConditions[0]["user_id"]
|
||||
} else {
|
||||
// 需要同时满足多个条件,使用 $and
|
||||
filter["$and"] = userIDConditions
|
||||
}
|
||||
}
|
||||
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"nickname": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"phone_number": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"email": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
// 注册时间范围查询
|
||||
if startTime != nil || endTime != nil {
|
||||
timeFilter := bson.M{}
|
||||
if startTime != nil {
|
||||
timeFilter["$gte"] = *startTime
|
||||
}
|
||||
if endTime != nil {
|
||||
timeFilter["$lt"] = *endTime
|
||||
}
|
||||
if len(timeFilter) > 0 {
|
||||
filter["create_time"] = timeFilter
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Attribute](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Attribute) SearchUser(ctx context.Context, keyword string, userIDs []string, genders []int32, pagination pagination.Pagination) (int64, []*chat.Attribute, error) {
|
||||
filter := bson.M{}
|
||||
if len(genders) > 0 {
|
||||
filter["gender"] = bson.M{
|
||||
"$in": genders,
|
||||
}
|
||||
}
|
||||
if len(userIDs) > 0 {
|
||||
filter["user_id"] = bson.M{
|
||||
"$in": userIDs,
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"nickname": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"phone_number": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"email": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Attribute](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *Attribute) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
145
pkg/common/db/model/chat/credential.go
Normal file
145
pkg/common/db/model/chat/credential.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"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 NewCredential(db *mongo.Database) (chat.CredentialInterface, error) {
|
||||
coll := db.Collection("credential")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "type", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "account", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Credential{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Credential struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Credential) Create(ctx context.Context, credential ...*chat.Credential) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, credential)
|
||||
}
|
||||
|
||||
func (o *Credential) CreateOrUpdateAccount(ctx context.Context, credential *chat.Credential) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{
|
||||
"user_id": credential.UserID,
|
||||
"type": credential.Type,
|
||||
}, bson.M{
|
||||
"$set": bson.M{
|
||||
"account": credential.Account,
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
"user_id": credential.UserID,
|
||||
"type": credential.Type,
|
||||
"allow_change": credential.AllowChange,
|
||||
},
|
||||
}, false, options.Update().SetUpsert(true))
|
||||
}
|
||||
|
||||
func (o *Credential) Update(ctx context.Context, userID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Credential) Find(ctx context.Context, userID string) ([]*chat.Credential, error) {
|
||||
return mongoutil.Find[*chat.Credential](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *Credential) FindAccount(ctx context.Context, accounts []string) ([]*chat.Credential, error) {
|
||||
return mongoutil.Find[*chat.Credential](ctx, o.coll, bson.M{"account": bson.M{"$in": accounts}})
|
||||
}
|
||||
|
||||
func (o *Credential) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*chat.Credential, error) {
|
||||
return o.SearchUser(ctx, keyword, nil, pagination)
|
||||
}
|
||||
|
||||
func (o *Credential) TakeAccount(ctx context.Context, account string) (*chat.Credential, error) {
|
||||
return mongoutil.FindOne[*chat.Credential](ctx, o.coll, bson.M{"account": account})
|
||||
}
|
||||
|
||||
func (o *Credential) Take(ctx context.Context, userID string) (*chat.Credential, error) {
|
||||
return mongoutil.FindOne[*chat.Credential](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *Credential) SearchNormalUser(ctx context.Context, keyword string, forbiddenIDs []string, pagination pagination.Pagination) (int64, []*chat.Credential, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
if len(forbiddenIDs) > 0 {
|
||||
filter["user_id"] = bson.M{
|
||||
"$nin": forbiddenIDs,
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Credential](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *Credential) SearchUser(ctx context.Context, keyword string, userIDs []string, pagination pagination.Pagination) (int64, []*chat.Credential, error) {
|
||||
filter := bson.M{}
|
||||
|
||||
if len(userIDs) > 0 {
|
||||
filter["user_id"] = bson.M{
|
||||
"$in": userIDs,
|
||||
}
|
||||
}
|
||||
if keyword != "" {
|
||||
filter["$or"] = []bson.M{
|
||||
{"user_id": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"account": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
}
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Credential](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *Credential) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Credential) DeleteByUserIDType(ctx context.Context, credentials ...*chat.Credential) error {
|
||||
if len(credentials) == 0 {
|
||||
return nil
|
||||
}
|
||||
var filters []bson.M
|
||||
for _, credential := range credentials {
|
||||
filters = append(filters, bson.M{
|
||||
"user_id": credential.UserID,
|
||||
"type": credential.Type,
|
||||
})
|
||||
}
|
||||
|
||||
query := bson.M{"$or": filters}
|
||||
|
||||
return mongoutil.DeleteMany(ctx, o.coll, query)
|
||||
}
|
||||
151
pkg/common/db/model/chat/favorite.go
Normal file
151
pkg/common/db/model/chat/favorite.go
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewFavorite(db *mongo.Database) (chat.FavoriteInterface, error) {
|
||||
coll := db.Collection("favorite")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "type", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "status", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Favorite{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Favorite struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Favorite) Create(ctx context.Context, favorites ...*chat.Favorite) error {
|
||||
for _, favorite := range favorites {
|
||||
if favorite.ID == "" {
|
||||
favorite.ID = primitive.NewObjectID().Hex()
|
||||
}
|
||||
if favorite.CreateTime.IsZero() {
|
||||
favorite.CreateTime = time.Now()
|
||||
}
|
||||
if favorite.UpdateTime.IsZero() {
|
||||
favorite.UpdateTime = time.Now()
|
||||
}
|
||||
if favorite.Status == 0 {
|
||||
favorite.Status = 1 // 默认为正常状态
|
||||
}
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, o.coll, favorites)
|
||||
}
|
||||
|
||||
func (o *Favorite) Take(ctx context.Context, favoriteID string) (*chat.Favorite, error) {
|
||||
return mongoutil.FindOne[*chat.Favorite](ctx, o.coll, bson.M{"_id": favoriteID, "status": 1})
|
||||
}
|
||||
|
||||
func (o *Favorite) FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chat.Favorite, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
"status": 1,
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Favorite](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Favorite) FindByUserIDAndType(ctx context.Context, userID string, favoriteType int32, pagination pagination.Pagination) (int64, []*chat.Favorite, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
"type": favoriteType,
|
||||
"status": 1,
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Favorite](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Favorite) SearchByKeyword(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*chat.Favorite, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
"status": 1,
|
||||
"$or": []bson.M{
|
||||
{"title": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"content": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
{"description": bson.M{"$regex": keyword, "$options": "i"}},
|
||||
},
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Favorite](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Favorite) Update(ctx context.Context, favoriteID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
data["update_time"] = time.Now()
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": favoriteID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *Favorite) Delete(ctx context.Context, favoriteIDs []string) error {
|
||||
if len(favoriteIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
// 软删除:将状态设置为0
|
||||
_, err := o.coll.UpdateMany(ctx, bson.M{"_id": bson.M{"$in": favoriteIDs}}, bson.M{"$set": bson.M{"status": 0, "update_time": time.Now()}})
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (o *Favorite) DeleteByUserID(ctx context.Context, userID string) error {
|
||||
// 软删除:将状态设置为0
|
||||
_, err := o.coll.UpdateMany(ctx, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"status": 0, "update_time": time.Now()}})
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (o *Favorite) CountByUserID(ctx context.Context, userID string) (int64, error) {
|
||||
return mongoutil.Count(ctx, o.coll, bson.M{"user_id": userID, "status": 1})
|
||||
}
|
||||
|
||||
func (o *Favorite) FindByTags(ctx context.Context, userID string, tags []string, pagination pagination.Pagination) (int64, []*chat.Favorite, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
"status": 1,
|
||||
"tags": bson.M{"$in": tags},
|
||||
}
|
||||
return mongoutil.FindPage[*chat.Favorite](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
81
pkg/common/db/model/chat/register.go
Normal file
81
pkg/common/db/model/chat/register.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
func NewRegister(db *mongo.Database) (chat.RegisterInterface, error) {
|
||||
coll := db.Collection("register")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Register{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Register struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Register) Create(ctx context.Context, registers ...*chat.Register) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, registers)
|
||||
}
|
||||
|
||||
func (o *Register) CountTotal(ctx context.Context, before *time.Time) (int64, error) {
|
||||
filter := bson.M{}
|
||||
if before != nil {
|
||||
filter["create_time"] = bson.M{"$lt": before}
|
||||
}
|
||||
return mongoutil.Count(ctx, o.coll, filter)
|
||||
}
|
||||
|
||||
func (o *Register) CountToday(ctx context.Context) (int64, error) {
|
||||
now := time.Now()
|
||||
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
endOfDay := startOfDay.Add(24 * time.Hour)
|
||||
|
||||
filter := bson.M{
|
||||
"create_time": bson.M{
|
||||
"$gte": startOfDay,
|
||||
"$lt": endOfDay,
|
||||
},
|
||||
}
|
||||
return mongoutil.Count(ctx, o.coll, filter)
|
||||
}
|
||||
|
||||
func (o *Register) Delete(ctx context.Context, userIDs []string) error {
|
||||
if len(userIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
106
pkg/common/db/model/chat/scheduled_task.go
Normal file
106
pkg/common/db/model/chat/scheduled_task.go
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewScheduledTask(db *mongo.Database) (chat.ScheduledTaskInterface, error) {
|
||||
coll := db.Collection("scheduled_tasks")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "status", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &ScheduledTask{coll: coll}, nil
|
||||
}
|
||||
|
||||
type ScheduledTask struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) Create(ctx context.Context, tasks ...*chat.ScheduledTask) error {
|
||||
for _, task := range tasks {
|
||||
if task.ID == "" {
|
||||
task.ID = primitive.NewObjectID().Hex()
|
||||
}
|
||||
if task.CreateTime.IsZero() {
|
||||
task.CreateTime = time.Now()
|
||||
}
|
||||
if task.UpdateTime.IsZero() {
|
||||
task.UpdateTime = time.Now()
|
||||
}
|
||||
if task.Status == 0 {
|
||||
task.Status = 1 // 默认为启用状态
|
||||
}
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, o.coll, tasks)
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) Take(ctx context.Context, taskID string) (*chat.ScheduledTask, error) {
|
||||
return mongoutil.FindOne[*chat.ScheduledTask](ctx, o.coll, bson.M{"_id": taskID})
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chat.ScheduledTask, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
}
|
||||
return mongoutil.FindPage[*chat.ScheduledTask](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) FindAll(ctx context.Context, pagination pagination.Pagination) (int64, []*chat.ScheduledTask, error) {
|
||||
filter := bson.M{}
|
||||
return mongoutil.FindPage[*chat.ScheduledTask](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) Update(ctx context.Context, taskID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
data["update_time"] = time.Now()
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": taskID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *ScheduledTask) Delete(ctx context.Context, taskIDs []string) error {
|
||||
if len(taskIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := o.coll.DeleteMany(ctx, bson.M{"_id": bson.M{"$in": taskIDs}})
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
422
pkg/common/db/model/chat/sensitive_word.go
Normal file
422
pkg/common/db/model/chat/sensitive_word.go
Normal file
@@ -0,0 +1,422 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"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 NewSensitiveWord(db *mongo.Database) (chat.SensitiveWordInterface, error) {
|
||||
coll := db.Collection("sensitive_words")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "word", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "status", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
// 创建配置集合
|
||||
configColl := db.Collection("sensitive_word_configs")
|
||||
_, err = configColl.Indexes().CreateOne(context.Background(), mongo.IndexModel{
|
||||
Keys: bson.D{
|
||||
{Key: "enable_filter", Value: 1},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
// 检查并初始化默认配置
|
||||
ctx := context.Background()
|
||||
count, err := configColl.CountDocuments(ctx, bson.M{})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
// 创建默认配置
|
||||
defaultConfig := &chat.SensitiveWordConfig{
|
||||
ID: "default",
|
||||
EnableFilter: true,
|
||||
FilterMode: 1,
|
||||
ReplaceChar: "***",
|
||||
WhitelistUsers: []string{},
|
||||
WhitelistGroups: []string{},
|
||||
LogEnabled: true,
|
||||
AutoApprove: false,
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
|
||||
_, err = configColl.InsertOne(ctx, defaultConfig)
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
return &SensitiveWord{coll: coll, configColl: configColl}, nil
|
||||
}
|
||||
|
||||
type SensitiveWord struct {
|
||||
coll *mongo.Collection
|
||||
configColl *mongo.Collection
|
||||
}
|
||||
|
||||
// ==================== 敏感词管理 ====================
|
||||
|
||||
func (o *SensitiveWord) CreateSensitiveWord(ctx context.Context, word *chat.SensitiveWord) error {
|
||||
word.CreateTime = time.Now()
|
||||
word.UpdateTime = time.Now()
|
||||
return mongoutil.InsertMany(ctx, o.coll, []*chat.SensitiveWord{word})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) UpdateSensitiveWord(ctx context.Context, id string, data map[string]any) error {
|
||||
data["update_time"] = time.Now()
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": id}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) DeleteSensitiveWord(ctx context.Context, ids []string) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"_id": bson.M{"$in": ids}})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWord(ctx context.Context, id string) (*chat.SensitiveWord, error) {
|
||||
return mongoutil.FindOne[*chat.SensitiveWord](ctx, o.coll, bson.M{"_id": id})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) SearchSensitiveWords(ctx context.Context, keyword string, action int32, status int32, pagination pagination.Pagination) (int64, []*chat.SensitiveWord, error) {
|
||||
filter := bson.M{}
|
||||
if keyword != "" {
|
||||
filter["word"] = bson.M{"$regex": keyword, "$options": "i"}
|
||||
}
|
||||
if action > 0 {
|
||||
filter["action"] = action
|
||||
}
|
||||
if status > 0 {
|
||||
filter["status"] = status
|
||||
}
|
||||
|
||||
return mongoutil.FindPage[*chat.SensitiveWord](ctx, o.coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetAllSensitiveWords(ctx context.Context) ([]*chat.SensitiveWord, error) {
|
||||
return mongoutil.Find[*chat.SensitiveWord](ctx, o.coll, bson.M{})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetEnabledSensitiveWords(ctx context.Context) ([]*chat.SensitiveWord, error) {
|
||||
return mongoutil.Find[*chat.SensitiveWord](ctx, o.coll, bson.M{"status": chat.SensitiveStatusEnabled})
|
||||
}
|
||||
|
||||
// ==================== 敏感词检测和过滤 ====================
|
||||
|
||||
func (o *SensitiveWord) CheckSensitiveWords(ctx context.Context, content string) ([]*chat.SensitiveWord, error) {
|
||||
words, err := o.GetEnabledSensitiveWords(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var matchedWords []*chat.SensitiveWord
|
||||
contentLower := strings.ToLower(content)
|
||||
|
||||
for _, word := range words {
|
||||
if strings.Contains(contentLower, strings.ToLower(word.Word)) {
|
||||
matchedWords = append(matchedWords, word)
|
||||
}
|
||||
}
|
||||
|
||||
return matchedWords, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) FilterContent(ctx context.Context, content string) (string, []*chat.SensitiveWord, error) {
|
||||
words, err := o.CheckSensitiveWords(ctx, content)
|
||||
if err != nil {
|
||||
return content, nil, err
|
||||
}
|
||||
|
||||
if len(words) == 0 {
|
||||
return content, words, nil
|
||||
}
|
||||
|
||||
filteredContent := content
|
||||
for _, word := range words {
|
||||
replaceChar := "***"
|
||||
filteredContent = strings.ReplaceAll(filteredContent, word.Word, replaceChar)
|
||||
}
|
||||
|
||||
return filteredContent, words, nil
|
||||
}
|
||||
|
||||
// ==================== 敏感词日志管理 ====================
|
||||
|
||||
func (o *SensitiveWord) CreateSensitiveWordLog(ctx context.Context, log *chat.SensitiveWordLog) error {
|
||||
log.CreateTime = time.Now()
|
||||
return mongoutil.InsertMany(ctx, o.coll.Database().Collection("sensitive_word_logs"), []*chat.SensitiveWordLog{log})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWordLogs(ctx context.Context, userID, groupID string, pagination pagination.Pagination) (int64, []*chat.SensitiveWordLog, error) {
|
||||
filter := bson.M{}
|
||||
if userID != "" {
|
||||
filter["user_id"] = userID
|
||||
}
|
||||
if groupID != "" {
|
||||
filter["group_id"] = groupID
|
||||
}
|
||||
|
||||
coll := o.coll.Database().Collection("sensitive_word_logs")
|
||||
return mongoutil.FindPage[*chat.SensitiveWordLog](ctx, coll, filter, pagination)
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) DeleteSensitiveWordLogs(ctx context.Context, ids []string) error {
|
||||
coll := o.coll.Database().Collection("sensitive_word_logs")
|
||||
return mongoutil.DeleteMany(ctx, coll, bson.M{"_id": bson.M{"$in": ids}})
|
||||
}
|
||||
|
||||
// ==================== 敏感词分组管理 ====================
|
||||
|
||||
func (o *SensitiveWord) CreateSensitiveWordGroup(ctx context.Context, group *chat.SensitiveWordGroup) error {
|
||||
group.CreateTime = time.Now()
|
||||
group.UpdateTime = time.Now()
|
||||
return mongoutil.InsertMany(ctx, o.coll.Database().Collection("sensitive_word_groups"), []*chat.SensitiveWordGroup{group})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) UpdateSensitiveWordGroup(ctx context.Context, id string, data map[string]any) error {
|
||||
data["update_time"] = time.Now()
|
||||
coll := o.coll.Database().Collection("sensitive_word_groups")
|
||||
return mongoutil.UpdateOne(ctx, coll, bson.M{"_id": id}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) DeleteSensitiveWordGroup(ctx context.Context, ids []string) error {
|
||||
coll := o.coll.Database().Collection("sensitive_word_groups")
|
||||
return mongoutil.DeleteMany(ctx, coll, bson.M{"_id": bson.M{"$in": ids}})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWordGroup(ctx context.Context, id string) (*chat.SensitiveWordGroup, error) {
|
||||
coll := o.coll.Database().Collection("sensitive_word_groups")
|
||||
return mongoutil.FindOne[*chat.SensitiveWordGroup](ctx, coll, bson.M{"_id": id})
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetAllSensitiveWordGroups(ctx context.Context) ([]*chat.SensitiveWordGroup, error) {
|
||||
coll := o.coll.Database().Collection("sensitive_word_groups")
|
||||
return mongoutil.Find[*chat.SensitiveWordGroup](ctx, coll, bson.M{})
|
||||
}
|
||||
|
||||
// ==================== 敏感词配置管理 ====================
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWordConfig(ctx context.Context) (*chat.SensitiveWordConfig, error) {
|
||||
// 查找配置(默认配置已在初始化时创建)
|
||||
config, err := mongoutil.FindOne[*chat.SensitiveWordConfig](ctx, o.configColl, bson.M{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) UpdateSensitiveWordConfig(ctx context.Context, config *chat.SensitiveWordConfig) error {
|
||||
config.UpdateTime = time.Now()
|
||||
if config.ID == "" {
|
||||
config.ID = "default"
|
||||
}
|
||||
filter := bson.M{"_id": config.ID}
|
||||
fmt.Println("UpdateSensitiveWordConfig", "_________55", config, o.configColl.Name())
|
||||
err := mongoutil.UpdateOne(ctx, o.configColl, filter, bson.M{"$set": config}, true)
|
||||
fmt.Println("UpdateSensitiveWordConfig", "_________44", config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) IsFilterEnabled(ctx context.Context) (bool, error) {
|
||||
config, err := o.GetSensitiveWordConfig(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return config.EnableFilter, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetFilterMode(ctx context.Context) (int32, error) {
|
||||
// 简化实现,返回默认值
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetReplaceChar(ctx context.Context) (string, error) {
|
||||
config, err := o.GetSensitiveWordConfig(ctx)
|
||||
if err != nil {
|
||||
return "***", err
|
||||
}
|
||||
if config.ReplaceChar == "" {
|
||||
return "***", nil
|
||||
}
|
||||
return config.ReplaceChar, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) IsUserInWhitelist(ctx context.Context, userID string) (bool, error) {
|
||||
config, err := o.GetSensitiveWordConfig(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, id := range config.WhitelistUsers {
|
||||
if id == userID {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) IsGroupInWhitelist(ctx context.Context, groupID string) (bool, error) {
|
||||
config, err := o.GetSensitiveWordConfig(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, id := range config.WhitelistGroups {
|
||||
if id == groupID {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ==================== 批量操作 ====================
|
||||
|
||||
func (o *SensitiveWord) BatchCreateSensitiveWords(ctx context.Context, words []*chat.SensitiveWord) error {
|
||||
now := time.Now()
|
||||
for _, word := range words {
|
||||
word.CreateTime = now
|
||||
word.UpdateTime = now
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, o.coll, words)
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) BatchUpdateSensitiveWords(ctx context.Context, updates map[string]map[string]any) error {
|
||||
for id, data := range updates {
|
||||
data["update_time"] = time.Now()
|
||||
err := mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": id}, bson.M{"$set": data}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) BatchDeleteSensitiveWords(ctx context.Context, ids []string) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"_id": bson.M{"$in": ids}})
|
||||
}
|
||||
|
||||
// ==================== 统计信息 ====================
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWordStats(ctx context.Context) (map[string]int64, error) {
|
||||
stats := make(map[string]int64)
|
||||
|
||||
// 总数
|
||||
total, err := mongoutil.Count(ctx, o.coll, bson.M{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["total"] = total
|
||||
|
||||
// 启用数量
|
||||
enabled, err := mongoutil.Count(ctx, o.coll, bson.M{"status": chat.SensitiveStatusEnabled})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["enabled"] = enabled
|
||||
|
||||
// 禁用数量
|
||||
disabled, err := mongoutil.Count(ctx, o.coll, bson.M{"status": chat.SensitiveStatusDisabled})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["disabled"] = disabled
|
||||
|
||||
// 替换模式数量
|
||||
replace, err := mongoutil.Count(ctx, o.coll, bson.M{"action": chat.SensitiveActionReplace})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["replace"] = replace
|
||||
|
||||
// 拦截模式数量
|
||||
block, err := mongoutil.Count(ctx, o.coll, bson.M{"action": chat.SensitiveActionBlock})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["block"] = block
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (o *SensitiveWord) GetSensitiveWordLogStats(ctx context.Context, startTime, endTime time.Time) (map[string]int64, error) {
|
||||
stats := make(map[string]int64)
|
||||
coll := o.coll.Database().Collection("sensitive_word_logs")
|
||||
|
||||
filter := bson.M{
|
||||
"create_time": bson.M{
|
||||
"$gte": startTime,
|
||||
"$lte": endTime,
|
||||
},
|
||||
}
|
||||
|
||||
// 总数
|
||||
total, err := mongoutil.Count(ctx, coll, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["total"] = total
|
||||
|
||||
// 替换数量
|
||||
replaceFilter := bson.M{}
|
||||
for k, v := range filter {
|
||||
replaceFilter[k] = v
|
||||
}
|
||||
replaceFilter["action"] = chat.SensitiveActionReplace
|
||||
replace, err := mongoutil.Count(ctx, coll, replaceFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["replace"] = replace
|
||||
|
||||
// 拦截数量
|
||||
blockFilter := bson.M{}
|
||||
for k, v := range filter {
|
||||
blockFilter[k] = v
|
||||
}
|
||||
blockFilter["action"] = chat.SensitiveActionBlock
|
||||
block, err := mongoutil.Count(ctx, coll, blockFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats["block"] = block
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
121
pkg/common/db/model/chat/system_config.go
Normal file
121
pkg/common/db/model/chat/system_config.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewSystemConfig(db *mongo.Database) (chat.SystemConfigInterface, error) {
|
||||
coll := db.Collection("system_configs")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "key", Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "enabled", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &SystemConfig{coll: coll}, nil
|
||||
}
|
||||
|
||||
type SystemConfig struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *SystemConfig) Create(ctx context.Context, configs ...*chat.SystemConfig) error {
|
||||
for _, config := range configs {
|
||||
if config.CreateTime.IsZero() {
|
||||
config.CreateTime = time.Now()
|
||||
}
|
||||
if config.UpdateTime.IsZero() {
|
||||
config.UpdateTime = time.Now()
|
||||
}
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, o.coll, configs)
|
||||
}
|
||||
|
||||
func (o *SystemConfig) Take(ctx context.Context, key string) (*chat.SystemConfig, error) {
|
||||
return mongoutil.FindOne[*chat.SystemConfig](ctx, o.coll, bson.M{"key": key})
|
||||
}
|
||||
|
||||
func (o *SystemConfig) FindByKeys(ctx context.Context, keys []string) ([]*chat.SystemConfig, error) {
|
||||
if len(keys) == 0 {
|
||||
return []*chat.SystemConfig{}, nil
|
||||
}
|
||||
return mongoutil.Find[*chat.SystemConfig](ctx, o.coll, bson.M{"key": bson.M{"$in": keys}}, options.Find().SetSort(bson.D{{Key: "key", Value: 1}}))
|
||||
}
|
||||
|
||||
func (o *SystemConfig) FindAll(ctx context.Context, pagination pagination.Pagination) (int64, []*chat.SystemConfig, error) {
|
||||
filter := bson.M{}
|
||||
return mongoutil.FindPage[*chat.SystemConfig](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "key", Value: 1}}))
|
||||
}
|
||||
|
||||
func (o *SystemConfig) Update(ctx context.Context, key string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
data["update_time"] = time.Now()
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"key": key}, bson.M{"$set": data}, false)
|
||||
}
|
||||
|
||||
func (o *SystemConfig) UpdateValue(ctx context.Context, key string, value string) error {
|
||||
return o.Update(ctx, key, map[string]any{"value": value})
|
||||
}
|
||||
|
||||
func (o *SystemConfig) UpdateEnabled(ctx context.Context, key string, enabled bool) error {
|
||||
return o.Update(ctx, key, map[string]any{"enabled": enabled})
|
||||
}
|
||||
|
||||
func (o *SystemConfig) Delete(ctx context.Context, keys []string) error {
|
||||
if len(keys) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := o.coll.DeleteMany(ctx, bson.M{"key": bson.M{"$in": keys}})
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
|
||||
func (o *SystemConfig) GetEnabledConfigs(ctx context.Context) ([]*chat.SystemConfig, error) {
|
||||
filter := bson.M{
|
||||
"enabled": true,
|
||||
}
|
||||
return mongoutil.Find[*chat.SystemConfig](ctx, o.coll, filter, options.Find().SetSort(bson.D{{Key: "key", Value: 1}}))
|
||||
}
|
||||
|
||||
func (o *SystemConfig) GetAppConfigs(ctx context.Context) ([]*chat.SystemConfig, error) {
|
||||
filter := bson.M{
|
||||
"show_in_app": true,
|
||||
"enabled": true, // 同时要求 enabled=true
|
||||
}
|
||||
return mongoutil.Find[*chat.SystemConfig](ctx, o.coll, filter, options.Find().SetSort(bson.D{{Key: "key", Value: 1}}))
|
||||
}
|
||||
198
pkg/common/db/model/chat/user_login_record.go
Normal file
198
pkg/common/db/model/chat/user_login_record.go
Normal file
@@ -0,0 +1,198 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewUserLoginRecord(db *mongo.Database) (chat.UserLoginRecordInterface, error) {
|
||||
coll := db.Collection("user_login_record")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
// 用于 CountTotal 查询:根据 create_time 范围查询
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "create_time", Value: 1},
|
||||
},
|
||||
},
|
||||
// 用于 CountTodayActiveUsers 和 CountRangeEverydayTotal:根据 login_time 范围查询
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "login_time", Value: 1},
|
||||
},
|
||||
},
|
||||
// 用于 GetLatestLoginIP:根据 user_id 查询,按 login_time 降序排序
|
||||
// 同时优化聚合查询中的 user_id 分组操作
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "login_time", Value: -1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &UserLoginRecord{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type UserLoginRecord struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) Create(ctx context.Context, records ...*chat.UserLoginRecord) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, records)
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
|
||||
filter := bson.M{}
|
||||
if before != nil {
|
||||
filter["create_time"] = bson.M{"$lt": before}
|
||||
}
|
||||
return mongoutil.Count(ctx, o.coll, filter)
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) CountTodayActiveUsers(ctx context.Context) (int64, error) {
|
||||
now := time.Now()
|
||||
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
endOfDay := startOfDay.Add(24 * time.Hour)
|
||||
|
||||
filter := bson.M{
|
||||
"login_time": bson.M{
|
||||
"$gte": startOfDay,
|
||||
"$lt": endOfDay,
|
||||
},
|
||||
}
|
||||
|
||||
// 使用聚合管道统计不同的用户数
|
||||
pipeline := []bson.M{
|
||||
{"$match": filter},
|
||||
{"$group": bson.M{
|
||||
"_id": "$user_id",
|
||||
}},
|
||||
{"$count": "count"},
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Count int64 `bson:"count"`
|
||||
}
|
||||
results, err := mongoutil.Aggregate[Result](ctx, o.coll, pipeline)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(results) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return results[0].Count, nil
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) CountRangeEverydayTotal(ctx context.Context, start *time.Time, end *time.Time) (map[string]int64, int64, error) {
|
||||
pipeline := make([]bson.M, 0, 4)
|
||||
if start != nil || end != nil {
|
||||
filter := bson.M{}
|
||||
if start != nil {
|
||||
filter["$gte"] = start
|
||||
}
|
||||
if end != nil {
|
||||
filter["$lt"] = end
|
||||
}
|
||||
pipeline = append(pipeline, bson.M{"$match": bson.M{"login_time": filter}})
|
||||
}
|
||||
pipeline = append(pipeline,
|
||||
bson.M{
|
||||
"$project": bson.M{
|
||||
"_id": 0,
|
||||
"user_id": 1,
|
||||
"login_time": bson.M{
|
||||
"$dateToString": bson.M{
|
||||
"format": "%Y-%m-%d",
|
||||
"date": "$login_time",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
bson.M{
|
||||
"$group": bson.M{
|
||||
"_id": bson.M{
|
||||
"user_id": "$user_id",
|
||||
"login_time": "$login_time",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
bson.M{
|
||||
"$group": bson.M{
|
||||
"_id": "$_id.login_time",
|
||||
"count": bson.M{
|
||||
"$sum": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
type Temp struct {
|
||||
ID string `bson:"_id"`
|
||||
Count int64 `bson:"count"`
|
||||
}
|
||||
res, err := mongoutil.Aggregate[Temp](ctx, o.coll, pipeline)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
var loginCount int64
|
||||
countMap := make(map[string]int64, len(res))
|
||||
for _, r := range res {
|
||||
loginCount += r.Count
|
||||
countMap[r.ID] = r.Count
|
||||
}
|
||||
return countMap, loginCount, nil
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) GetLatestLoginIP(ctx context.Context, userID string) (string, error) {
|
||||
filter := bson.M{"user_id": userID}
|
||||
opts := options.FindOne().SetSort(bson.D{{Key: "login_time", Value: -1}})
|
||||
|
||||
record, err := mongoutil.FindOne[chat.UserLoginRecord](ctx, o.coll, filter, opts)
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return "", nil // 用户没有登录记录,返回空字符串
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
return record.IP, nil
|
||||
}
|
||||
|
||||
func (o *UserLoginRecord) Search(ctx context.Context, userID, ip string, pagination pagination.Pagination) (int64, []*chat.UserLoginRecord, error) {
|
||||
filter := bson.M{}
|
||||
if userID != "" {
|
||||
filter["user_id"] = userID
|
||||
}
|
||||
if ip != "" {
|
||||
filter["ip"] = ip
|
||||
}
|
||||
return mongoutil.FindPage[*chat.UserLoginRecord](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "login_time", Value: -1}}))
|
||||
}
|
||||
146
pkg/common/db/model/chat/verify_code.go
Normal file
146
pkg/common/db/model/chat/verify_code.go
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
)
|
||||
|
||||
type mongoVerifyCode struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
Account string `bson:"account"`
|
||||
Platform string `bson:"platform"`
|
||||
Code string `bson:"code"`
|
||||
Duration uint `bson:"duration"`
|
||||
Count int `bson:"count"`
|
||||
Used bool `bson:"used"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func NewVerifyCode(db *mongo.Database) (chat.VerifyCodeInterface, error) {
|
||||
coll := db.Collection("verify_code")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "account", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &VerifyCode{
|
||||
coll: coll,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type VerifyCode struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *VerifyCode) parseID(s string) (primitive.ObjectID, error) {
|
||||
objID, err := primitive.ObjectIDFromHex(s)
|
||||
if err != nil {
|
||||
var zero primitive.ObjectID
|
||||
return zero, errs.Wrap(err)
|
||||
}
|
||||
return objID, nil
|
||||
}
|
||||
|
||||
func (o *VerifyCode) Add(ctx context.Context, ms []*chat.VerifyCode) error {
|
||||
tmp := make([]mongoVerifyCode, 0, len(ms))
|
||||
for i, m := range ms {
|
||||
var objID primitive.ObjectID
|
||||
if m.ID == "" {
|
||||
objID = primitive.NewObjectID()
|
||||
ms[i].ID = objID.Hex()
|
||||
} else {
|
||||
var err error
|
||||
objID, err = o.parseID(m.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
tmp = append(tmp, mongoVerifyCode{
|
||||
ID: objID,
|
||||
Account: m.Account,
|
||||
Platform: m.Platform,
|
||||
Code: m.Code,
|
||||
Duration: m.Duration,
|
||||
Count: m.Count,
|
||||
Used: m.Used,
|
||||
CreateTime: m.CreateTime,
|
||||
})
|
||||
}
|
||||
return mongoutil.InsertMany(ctx, o.coll, tmp)
|
||||
}
|
||||
|
||||
func (o *VerifyCode) RangeNum(ctx context.Context, account string, start time.Time, end time.Time) (int64, error) {
|
||||
filter := bson.M{
|
||||
"account": account,
|
||||
"create_time": bson.M{
|
||||
"$gte": start,
|
||||
"$lte": end,
|
||||
},
|
||||
}
|
||||
return mongoutil.Count(ctx, o.coll, filter)
|
||||
}
|
||||
|
||||
func (o *VerifyCode) TakeLast(ctx context.Context, account string) (*chat.VerifyCode, error) {
|
||||
filter := bson.M{
|
||||
"account": account,
|
||||
}
|
||||
opt := options.FindOne().SetSort(bson.M{"_id": -1})
|
||||
last, err := mongoutil.FindOne[*mongoVerifyCode](ctx, o.coll, filter, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chat.VerifyCode{
|
||||
ID: last.ID.Hex(),
|
||||
Account: last.Account,
|
||||
Platform: last.Platform,
|
||||
Code: last.Code,
|
||||
Duration: last.Duration,
|
||||
Count: last.Count,
|
||||
Used: last.Used,
|
||||
CreateTime: last.CreateTime,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *VerifyCode) Incr(ctx context.Context, id string) error {
|
||||
objID, err := o.parseID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": objID}, bson.M{"$inc": bson.M{"count": 1}}, false)
|
||||
}
|
||||
|
||||
func (o *VerifyCode) Delete(ctx context.Context, id string) error {
|
||||
objID, err := o.parseID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mongoutil.DeleteOne(ctx, o.coll, bson.M{"_id": objID})
|
||||
}
|
||||
217
pkg/common/db/model/chat/wallet.go
Normal file
217
pkg/common/db/model/chat/wallet.go
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewWallet(db *mongo.Database) (chatdb.WalletInterface, error) {
|
||||
coll := db.Collection("wallets")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "user_id", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Wallet{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Wallet struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Wallet) Create(ctx context.Context, wallets ...*chatdb.Wallet) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, wallets)
|
||||
}
|
||||
|
||||
func (o *Wallet) Take(ctx context.Context, userID string) (*chatdb.Wallet, error) {
|
||||
return mongoutil.FindOne[*chatdb.Wallet](ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
|
||||
func (o *Wallet) Find(ctx context.Context, userIDs []string) ([]*chatdb.Wallet, error) {
|
||||
return mongoutil.Find[*chatdb.Wallet](ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Wallet) Update(ctx context.Context, userID string, data map[string]any) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": data}, true)
|
||||
}
|
||||
|
||||
func (o *Wallet) UpdateBalance(ctx context.Context, userID string, balance int64) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"balance": balance}}, true)
|
||||
}
|
||||
|
||||
// IncrementBalance 原子更新余额,使用 $inc 操作符防止并发问题
|
||||
// 返回更新前后的余额
|
||||
// 如果 amount 是负数(扣款),会检查余额是否足够,余额不足时返回错误
|
||||
func (o *Wallet) IncrementBalance(ctx context.Context, userID string, amount int64) (beforeBalance int64, afterBalance int64, err error) {
|
||||
// 如果 amount 是负数(扣款),需要确保余额不会变为负数
|
||||
filter := bson.M{"user_id": userID}
|
||||
if amount < 0 {
|
||||
// 扣款时,确保余额足够(balance >= -amount,即 balance + amount >= 0)
|
||||
// 例如:余额 100,扣款 -150,则 balance >= 150 不满足,更新失败
|
||||
filter["balance"] = bson.M{"$gte": -amount}
|
||||
}
|
||||
|
||||
update := bson.M{
|
||||
"$inc": bson.M{"balance": amount},
|
||||
"$set": bson.M{"update_time": time.Now()},
|
||||
}
|
||||
|
||||
opts := options.FindOneAndUpdate().
|
||||
SetReturnDocument(options.After). // 返回更新后的文档
|
||||
SetUpsert(true) // 如果不存在则创建
|
||||
|
||||
var wallet chatdb.Wallet
|
||||
err = o.coll.FindOneAndUpdate(ctx, filter, update, opts).Decode(&wallet)
|
||||
if err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
// 如果是因为余额不足导致更新失败(filter 条件不满足)
|
||||
if amount < 0 {
|
||||
// 获取当前余额用于错误提示
|
||||
currentWallet, takeErr := o.Take(ctx, userID)
|
||||
if takeErr == nil && currentWallet != nil {
|
||||
return currentWallet.Balance, currentWallet.Balance, errs.NewCodeError(errs.ErrArgs.Code(),
|
||||
fmt.Sprintf("余额不足:当前余额为 %d 分,需要 %d 分", currentWallet.Balance, -amount))
|
||||
}
|
||||
// 如果钱包不存在,说明余额为0,无法扣款
|
||||
return 0, 0, errs.NewCodeError(errs.ErrArgs.Code(), fmt.Sprintf("余额不足:钱包不存在或余额为0,需要 %d 分", -amount))
|
||||
}
|
||||
// 如果是增加余额但钱包不存在,应该由 upsert 创建,不应该到这里
|
||||
// 如果到这里说明有其他问题
|
||||
return 0, 0, errs.NewCodeError(errs.ErrArgs.Code(), "更新钱包余额失败")
|
||||
}
|
||||
return 0, 0, errs.Wrap(err)
|
||||
}
|
||||
|
||||
// 计算更新前的余额
|
||||
beforeBalance = wallet.Balance - amount
|
||||
afterBalance = wallet.Balance
|
||||
|
||||
// 双重检查:确保余额不为负数(虽然 filter 已经保证,但为了安全再加一次检查)
|
||||
if afterBalance < 0 {
|
||||
// 如果余额为负数,回滚操作
|
||||
rollbackUpdate := bson.M{
|
||||
"$inc": bson.M{"balance": -amount}, // 回滚
|
||||
"$set": bson.M{"update_time": time.Now()},
|
||||
}
|
||||
_ = o.coll.FindOneAndUpdate(ctx, bson.M{"user_id": userID}, rollbackUpdate, options.FindOneAndUpdate().SetReturnDocument(options.After))
|
||||
return beforeBalance, beforeBalance, errs.NewCodeError(errs.ErrArgs.Code(), "余额更新后不能为负数")
|
||||
}
|
||||
|
||||
return beforeBalance, afterBalance, nil
|
||||
}
|
||||
|
||||
func (o *Wallet) UpdatePaymentPassword(ctx context.Context, userID string, paymentPassword string) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"payment_password": paymentPassword, "update_time": time.Now()}}, true)
|
||||
}
|
||||
|
||||
func (o *Wallet) UpdateWithdrawAccount(ctx context.Context, userID string, withdrawAccount string) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"withdraw_account": withdrawAccount, "update_time": time.Now()}}, true)
|
||||
}
|
||||
|
||||
func (o *Wallet) UpdateWithdrawAccountWithType(ctx context.Context, userID string, withdrawAccount string, accountType int32) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"withdraw_account": withdrawAccount, "withdraw_account_type": accountType, "update_time": time.Now()}}, true)
|
||||
}
|
||||
|
||||
func (o *Wallet) UpdateRealNameAuth(ctx context.Context, userID string, realNameAuth chatdb.RealNameAuth) error {
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"user_id": userID}, bson.M{"$set": bson.M{"real_name_auth": realNameAuth, "update_time": time.Now()}}, true)
|
||||
}
|
||||
|
||||
func (o *Wallet) Delete(ctx context.Context, userIDs []string) error {
|
||||
return mongoutil.DeleteMany(ctx, o.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
|
||||
}
|
||||
|
||||
func (o *Wallet) Page(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) {
|
||||
return mongoutil.FindPage[*chatdb.Wallet](ctx, o.coll, bson.M{}, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
// PageByRealNameAuthAuditStatus 按实名认证审核状态分页查询钱包
|
||||
// auditStatus: 0-所有审核状态,1-审核通过,2-审核拒绝
|
||||
// userID: 用户ID搜索(可选,为空时不过滤)
|
||||
func (o *Wallet) PageByRealNameAuthAuditStatus(ctx context.Context, auditStatus int32, userID string, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) {
|
||||
filter := bson.M{
|
||||
"real_name_auth.id_card": bson.M{"$ne": ""}, // 过滤身份证号不为空的(已完成实名认证)
|
||||
"$expr": bson.M{ // 身份证长度至少 6,null/非字符串时按空字符串处理,避免 count 报错
|
||||
"$gte": []any{
|
||||
bson.M{"$strLenCP": bson.M{"$ifNull": []any{"$real_name_auth.id_card", ""}}},
|
||||
6,
|
||||
},
|
||||
},
|
||||
}
|
||||
// 支持按审核状态筛选:0-待审核,1-审核通过,2-审核拒绝;auditStatus < 0 表示不过滤状态
|
||||
if auditStatus >= 0 {
|
||||
filter["real_name_auth.audit_status"] = auditStatus
|
||||
}
|
||||
// 支持按用户ID搜索
|
||||
if userID != "" {
|
||||
filter["user_id"] = userID
|
||||
}
|
||||
return mongoutil.FindPage[*chatdb.Wallet](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "update_time", Value: -1}}))
|
||||
}
|
||||
|
||||
// SearchByRealNameAuth 按实名认证信息搜索钱包(返回userIDs)
|
||||
// realNameKeyword: 真实姓名搜索关键词(可选)
|
||||
// idCardKeyword: 身份证号搜索关键词(可选)
|
||||
func (o *Wallet) SearchByRealNameAuth(ctx context.Context, realNameKeyword string, idCardKeyword string) ([]string, error) {
|
||||
filter := bson.M{
|
||||
"real_name_auth.id_card": bson.M{"$ne": ""}, // 过滤身份证号不为空的(已完成实名认证)
|
||||
"$expr": bson.M{ // 身份证长度至少 6,null/非字符串时按空字符串处理,避免 count 报错
|
||||
"$gte": []any{
|
||||
bson.M{"$strLenCP": bson.M{"$ifNull": []any{"$real_name_auth.id_card", ""}}},
|
||||
6,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 构建搜索条件
|
||||
orConditions := []bson.M{}
|
||||
if realNameKeyword != "" {
|
||||
orConditions = append(orConditions, bson.M{"real_name_auth.name": bson.M{"$regex": realNameKeyword, "$options": "i"}})
|
||||
}
|
||||
if idCardKeyword != "" {
|
||||
orConditions = append(orConditions, bson.M{"real_name_auth.id_card": bson.M{"$regex": idCardKeyword, "$options": "i"}})
|
||||
}
|
||||
if len(orConditions) > 0 {
|
||||
filter["$or"] = orConditions
|
||||
}
|
||||
|
||||
// 只查询 user_id 字段
|
||||
opts := options.Find().SetProjection(bson.M{"user_id": 1})
|
||||
wallets, err := mongoutil.Find[*chatdb.Wallet](ctx, o.coll, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userIDs := make([]string, 0, len(wallets))
|
||||
for _, wallet := range wallets {
|
||||
userIDs = append(userIDs, wallet.UserID)
|
||||
}
|
||||
return userIDs, nil
|
||||
}
|
||||
123
pkg/common/db/model/chat/wallet_balance_record.go
Normal file
123
pkg/common/db/model/chat/wallet_balance_record.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewWalletBalanceRecord(db *mongo.Database) (chatdb.WalletBalanceRecordInterface, error) {
|
||||
coll := db.Collection("wallet_balance_records")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "type", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "order_id", Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "transaction_id", Value: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "red_packet_id", Value: 1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &WalletBalanceRecord{coll: coll}, nil
|
||||
}
|
||||
|
||||
type WalletBalanceRecord struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) Create(ctx context.Context, records ...*chatdb.WalletBalanceRecord) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, records)
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) Take(ctx context.Context, recordID string) (*chatdb.WalletBalanceRecord, error) {
|
||||
return mongoutil.FindOne[*chatdb.WalletBalanceRecord](ctx, o.coll, bson.M{"_id": recordID})
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) {
|
||||
filter := bson.M{"user_id": userID}
|
||||
return mongoutil.FindPage[*chatdb.WalletBalanceRecord](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) FindByUserIDAndType(ctx context.Context, userID string, recordType int32, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) {
|
||||
filter := bson.M{
|
||||
"user_id": userID,
|
||||
"type": recordType,
|
||||
}
|
||||
return mongoutil.FindPage[*chatdb.WalletBalanceRecord](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) FindByOrderID(ctx context.Context, orderID string) (*chatdb.WalletBalanceRecord, error) {
|
||||
return mongoutil.FindOne[*chatdb.WalletBalanceRecord](ctx, o.coll, bson.M{"order_id": orderID})
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) FindByTransactionID(ctx context.Context, transactionID string) (*chatdb.WalletBalanceRecord, error) {
|
||||
return mongoutil.FindOne[*chatdb.WalletBalanceRecord](ctx, o.coll, bson.M{"transaction_id": transactionID})
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) FindByRedPacketID(ctx context.Context, redPacketID string) ([]*chatdb.WalletBalanceRecord, error) {
|
||||
return mongoutil.Find[*chatdb.WalletBalanceRecord](ctx, o.coll, bson.M{"red_packet_id": redPacketID}, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) GetUserBalanceHistory(ctx context.Context, userID string, startTime, endTime *time.Time, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) {
|
||||
filter := bson.M{"user_id": userID}
|
||||
if startTime != nil || endTime != nil {
|
||||
timeFilter := bson.M{}
|
||||
if startTime != nil {
|
||||
timeFilter["$gte"] = *startTime
|
||||
}
|
||||
if endTime != nil {
|
||||
timeFilter["$lte"] = *endTime
|
||||
}
|
||||
filter["create_time"] = timeFilter
|
||||
}
|
||||
return mongoutil.FindPage[*chatdb.WalletBalanceRecord](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WalletBalanceRecord) CountByUserID(ctx context.Context, userID string) (int64, error) {
|
||||
return mongoutil.Count(ctx, o.coll, bson.M{"user_id": userID})
|
||||
}
|
||||
95
pkg/common/db/model/chat/withdraw.go
Normal file
95
pkg/common/db/model/chat/withdraw.go
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewWithdraw(db *mongo.Database) (chatdb.WithdrawInterface, error) {
|
||||
coll := db.Collection("withdraws")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "status", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &Withdraw{coll: coll}, nil
|
||||
}
|
||||
|
||||
type Withdraw struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *Withdraw) Create(ctx context.Context, withdraws ...*chatdb.Withdraw) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, withdraws)
|
||||
}
|
||||
|
||||
func (o *Withdraw) Take(ctx context.Context, withdrawID string) (*chatdb.Withdraw, error) {
|
||||
return mongoutil.FindOne[*chatdb.Withdraw](ctx, o.coll, bson.M{"_id": withdrawID})
|
||||
}
|
||||
|
||||
func (o *Withdraw) FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
filter := bson.M{"user_id": userID}
|
||||
return mongoutil.FindPage[*chatdb.Withdraw](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Withdraw) FindByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
filter := bson.M{"status": status}
|
||||
return mongoutil.FindPage[*chatdb.Withdraw](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *Withdraw) UpdateStatus(ctx context.Context, withdrawID string, status int32, auditorID string, auditRemark string) error {
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"status": status,
|
||||
"auditor_id": auditorID,
|
||||
"audit_time": time.Now(),
|
||||
"audit_remark": auditRemark,
|
||||
"update_time": time.Now(),
|
||||
},
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": withdrawID}, update, false)
|
||||
}
|
||||
|
||||
func (o *Withdraw) Page(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
return mongoutil.FindPage[*chatdb.Withdraw](ctx, o.coll, bson.M{}, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
103
pkg/common/db/model/chat/withdraw_application.go
Normal file
103
pkg/common/db/model/chat/withdraw_application.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright © 2023 OpenIM open source community. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
func NewWithdrawApplication(db *mongo.Database) (chatdb.WithdrawApplicationInterface, error) {
|
||||
coll := db.Collection("withdraw_applications")
|
||||
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "user_id", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "status", Value: 1},
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: "create_time", Value: -1},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
return &WithdrawApplication{coll: coll}, nil
|
||||
}
|
||||
|
||||
type WithdrawApplication struct {
|
||||
coll *mongo.Collection
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) Create(ctx context.Context, applications ...*chatdb.WithdrawApplication) error {
|
||||
return mongoutil.InsertMany(ctx, o.coll, applications)
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) Take(ctx context.Context, applicationID string) (*chatdb.WithdrawApplication, error) {
|
||||
return mongoutil.FindOne[*chatdb.WithdrawApplication](ctx, o.coll, bson.M{"_id": applicationID})
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
filter := bson.M{"user_id": userID}
|
||||
return mongoutil.FindPage[*chatdb.WithdrawApplication](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) FindByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
filter := bson.M{"status": status}
|
||||
return mongoutil.FindPage[*chatdb.WithdrawApplication](ctx, o.coll, filter, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) UpdateStatus(ctx context.Context, applicationID string, status int32, auditorID string, auditRemark string) error {
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"status": status,
|
||||
"auditor_id": auditorID,
|
||||
"audit_time": time.Now(),
|
||||
"audit_remark": auditRemark,
|
||||
"update_time": time.Now(),
|
||||
},
|
||||
}
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": applicationID}, update, false)
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) Page(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
return mongoutil.FindPage[*chatdb.WithdrawApplication](ctx, o.coll, bson.M{}, pagination, options.Find().SetSort(bson.D{{Key: "create_time", Value: -1}}))
|
||||
}
|
||||
|
||||
func (o *WithdrawApplication) Update(ctx context.Context, applicationID string, data map[string]any) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
data["update_time"] = time.Now()
|
||||
return mongoutil.UpdateOne(ctx, o.coll, bson.M{"_id": applicationID}, bson.M{"$set": data}, false)
|
||||
}
|
||||
Reference in New Issue
Block a user