复制项目
This commit is contained in:
50
pkg/common/db/cache/imtoken.go
vendored
Normal file
50
pkg/common/db/cache/imtoken.go
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
const (
|
||||
chatPrefix = "CHAT:"
|
||||
imToken = chatPrefix + "IM_TOKEN:"
|
||||
)
|
||||
|
||||
func getIMTokenKey(userID string) string {
|
||||
return imToken + userID
|
||||
}
|
||||
|
||||
type IMTokenInterface interface {
|
||||
GetToken(ctx context.Context, userID string) (string, error)
|
||||
SetToken(ctx context.Context, userID, token string) error
|
||||
}
|
||||
|
||||
type imTokenCacheRedis struct {
|
||||
rdb redis.UniversalClient
|
||||
expire time.Duration
|
||||
}
|
||||
|
||||
func NewIMTokenInterface(rdb redis.UniversalClient, expire int) IMTokenInterface {
|
||||
return &imTokenCacheRedis{rdb: rdb, expire: time.Duration(expire) * time.Minute}
|
||||
}
|
||||
|
||||
func (i *imTokenCacheRedis) GetToken(ctx context.Context, userID string) (string, error) {
|
||||
key := getIMTokenKey(userID)
|
||||
token, err := i.rdb.Get(ctx, key).Result()
|
||||
if err != nil {
|
||||
return "", errs.Wrap(err)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (i *imTokenCacheRedis) SetToken(ctx context.Context, userID, token string) error {
|
||||
key := getIMTokenKey(userID)
|
||||
err := i.rdb.Set(ctx, key, token, i.expire).Err()
|
||||
if err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
84
pkg/common/db/cache/token.go
vendored
Normal file
84
pkg/common/db/cache/token.go
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// 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 cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/utils/stringutil"
|
||||
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
const (
|
||||
chatToken = "CHAT_UID_TOKEN_STATUS:"
|
||||
)
|
||||
|
||||
type TokenInterface interface {
|
||||
AddTokenFlag(ctx context.Context, userID string, token string, flag int) error
|
||||
AddTokenFlagNXEx(ctx context.Context, userID string, token string, flag int, expire time.Duration) (bool, error)
|
||||
GetTokensWithoutError(ctx context.Context, userID string) (map[string]int32, error)
|
||||
DeleteTokenByUid(ctx context.Context, userID string) error
|
||||
}
|
||||
|
||||
type TokenCacheRedis struct {
|
||||
rdb redis.UniversalClient
|
||||
accessExpire int64
|
||||
}
|
||||
|
||||
func NewTokenInterface(rdb redis.UniversalClient) *TokenCacheRedis {
|
||||
return &TokenCacheRedis{rdb: rdb}
|
||||
}
|
||||
|
||||
func (t *TokenCacheRedis) AddTokenFlag(ctx context.Context, userID string, token string, flag int) error {
|
||||
key := chatToken + userID
|
||||
return errs.Wrap(t.rdb.HSet(ctx, key, token, flag).Err())
|
||||
}
|
||||
|
||||
func (t *TokenCacheRedis) AddTokenFlagNXEx(ctx context.Context, userID string, token string, flag int, expire time.Duration) (bool, error) {
|
||||
key := chatToken + userID
|
||||
isSet, err := t.rdb.HSetNX(ctx, key, token, flag).Result()
|
||||
if err != nil {
|
||||
return false, errs.Wrap(err)
|
||||
}
|
||||
if !isSet {
|
||||
// key already exists
|
||||
return false, nil
|
||||
}
|
||||
if err = t.rdb.Expire(ctx, key, expire).Err(); err != nil {
|
||||
return false, errs.Wrap(err)
|
||||
}
|
||||
return isSet, nil
|
||||
}
|
||||
|
||||
func (t *TokenCacheRedis) GetTokensWithoutError(ctx context.Context, userID string) (map[string]int32, error) {
|
||||
key := chatToken + userID
|
||||
m, err := t.rdb.HGetAll(ctx, key).Result()
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(err)
|
||||
}
|
||||
mm := make(map[string]int32)
|
||||
for k, v := range m {
|
||||
mm[k] = stringutil.StringToInt32(v)
|
||||
}
|
||||
return mm, nil
|
||||
}
|
||||
|
||||
func (t *TokenCacheRedis) DeleteTokenByUid(ctx context.Context, userID string) error {
|
||||
key := chatToken + userID
|
||||
return errs.Wrap(t.rdb.Del(ctx, key).Err())
|
||||
}
|
||||
86
pkg/common/db/cache/user_login_ip.go
vendored
Normal file
86
pkg/common/db/cache/user_login_ip.go
vendored
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 cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
const (
|
||||
userLoginIPPrefix = "CHAT:USER_LOGIN_IP:"
|
||||
// 缓存过期时间:7天(用户登录IP变化不频繁,可以设置较长的过期时间)
|
||||
userLoginIPExpire = 7 * 24 * time.Hour
|
||||
)
|
||||
|
||||
func getUserLoginIPKey(userID string) string {
|
||||
return userLoginIPPrefix + userID
|
||||
}
|
||||
|
||||
type UserLoginIPInterface interface {
|
||||
// GetLatestLoginIP 获取用户最新登录IP(从缓存)
|
||||
// 返回值:(ip, found, error)
|
||||
// - ip: 缓存的IP值(如果found为false,则ip为空字符串)
|
||||
// - found: 是否在缓存中找到(true表示缓存命中,false表示缓存未命中)
|
||||
// - error: 错误信息
|
||||
GetLatestLoginIP(ctx context.Context, userID string) (string, bool, error)
|
||||
// SetLatestLoginIP 设置用户最新登录IP到缓存
|
||||
SetLatestLoginIP(ctx context.Context, userID, ip string) error
|
||||
// DeleteLatestLoginIP 删除用户最新登录IP缓存(用于保证缓存一致性)
|
||||
DeleteLatestLoginIP(ctx context.Context, userID string) error
|
||||
}
|
||||
|
||||
type userLoginIPCacheRedis struct {
|
||||
rdb redis.UniversalClient
|
||||
}
|
||||
|
||||
func NewUserLoginIPInterface(rdb redis.UniversalClient) UserLoginIPInterface {
|
||||
return &userLoginIPCacheRedis{rdb: rdb}
|
||||
}
|
||||
|
||||
func (u *userLoginIPCacheRedis) GetLatestLoginIP(ctx context.Context, userID string) (string, bool, error) {
|
||||
key := getUserLoginIPKey(userID)
|
||||
ip, err := u.rdb.Get(ctx, key).Result()
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
// 缓存不存在,返回 false 表示缓存未命中
|
||||
return "", false, nil
|
||||
}
|
||||
return "", false, errs.Wrap(err)
|
||||
}
|
||||
// 缓存命中,返回 true
|
||||
return ip, true, nil
|
||||
}
|
||||
|
||||
func (u *userLoginIPCacheRedis) SetLatestLoginIP(ctx context.Context, userID, ip string) error {
|
||||
key := getUserLoginIPKey(userID)
|
||||
err := u.rdb.Set(ctx, key, ip, userLoginIPExpire).Err()
|
||||
if err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userLoginIPCacheRedis) DeleteLatestLoginIP(ctx context.Context, userID string) error {
|
||||
key := getUserLoginIPKey(userID)
|
||||
err := u.rdb.Del(ctx, key).Err()
|
||||
if err != nil {
|
||||
return errs.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
407
pkg/common/db/database/admin.go
Normal file
407
pkg/common/db/database/admin.go
Normal file
@@ -0,0 +1,407 @@
|
||||
// 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 database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/cache"
|
||||
"git.imall.cloud/openim/protocol/constant"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/db/tx"
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/model/admin"
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
)
|
||||
|
||||
type AdminDatabaseInterface interface {
|
||||
GetAdmin(ctx context.Context, account string) (*admindb.Admin, error)
|
||||
GetAdminUserID(ctx context.Context, userID string) (*admindb.Admin, error)
|
||||
UpdateAdmin(ctx context.Context, userID string, update map[string]any) error
|
||||
ChangePassword(ctx context.Context, userID string, newPassword string) error
|
||||
ChangeOperationPassword(ctx context.Context, userID string, newPassword string) error
|
||||
ClearGoogleAuthKey(ctx context.Context, userID string) error
|
||||
AddAdminAccount(ctx context.Context, admin []*admindb.Admin) error
|
||||
DelAdminAccount(ctx context.Context, userIDs []string) error
|
||||
SearchAdminAccount(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.Admin, error)
|
||||
CreateApplet(ctx context.Context, applets []*admindb.Applet) error
|
||||
DelApplet(ctx context.Context, appletIDs []string) error
|
||||
GetApplet(ctx context.Context, appletID string) (*admindb.Applet, error)
|
||||
FindApplet(ctx context.Context, appletIDs []string) ([]*admindb.Applet, error)
|
||||
SearchApplet(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.Applet, error)
|
||||
FindOnShelf(ctx context.Context) ([]*admindb.Applet, error)
|
||||
UpdateApplet(ctx context.Context, appletID string, update map[string]any) error
|
||||
GetConfig(ctx context.Context) (map[string]string, error)
|
||||
SetConfig(ctx context.Context, cs map[string]string) error
|
||||
DelConfig(ctx context.Context, keys []string) error
|
||||
FindInvitationRegister(ctx context.Context, codes []string) ([]*admindb.InvitationRegister, error)
|
||||
DelInvitationRegister(ctx context.Context, codes []string) error
|
||||
UpdateInvitationRegister(ctx context.Context, code string, fields map[string]any) error
|
||||
CreatInvitationRegister(ctx context.Context, invitationRegisters []*admindb.InvitationRegister) error
|
||||
SearchInvitationRegister(ctx context.Context, keyword string, state int32, userIDs []string, codes []string, pagination pagination.Pagination) (int64, []*admindb.InvitationRegister, error)
|
||||
SearchIPForbidden(ctx context.Context, keyword string, state int32, pagination pagination.Pagination) (int64, []*admindb.IPForbidden, error)
|
||||
AddIPForbidden(ctx context.Context, ms []*admindb.IPForbidden) error
|
||||
FindIPForbidden(ctx context.Context, ms []string) ([]*admindb.IPForbidden, error)
|
||||
DelIPForbidden(ctx context.Context, ips []string) error
|
||||
FindDefaultFriend(ctx context.Context, userIDs []string) ([]string, error)
|
||||
AddDefaultFriend(ctx context.Context, ms []*admindb.RegisterAddFriend) error
|
||||
DelDefaultFriend(ctx context.Context, userIDs []string) error
|
||||
SearchDefaultFriend(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.RegisterAddFriend, error)
|
||||
FindDefaultGroup(ctx context.Context, groupIDs []string) ([]string, error)
|
||||
AddDefaultGroup(ctx context.Context, ms []*admindb.RegisterAddGroup) error
|
||||
DelDefaultGroup(ctx context.Context, groupIDs []string) error
|
||||
SearchDefaultGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.RegisterAddGroup, error)
|
||||
CountTotalGroups(ctx context.Context) (int64, error) // 统计群组总数
|
||||
CountTodayNewGroups(ctx context.Context) (int64, error) // 统计今天新建的群组数
|
||||
CountTotalFriends(ctx context.Context) (int64, error) // 统计好友总数
|
||||
FindBlockInfo(ctx context.Context, userIDs []string) ([]*admindb.ForbiddenAccount, error)
|
||||
GetBlockInfo(ctx context.Context, userID string) (*admindb.ForbiddenAccount, error)
|
||||
BlockUser(ctx context.Context, f []*admindb.ForbiddenAccount) error
|
||||
DelBlockUser(ctx context.Context, userID []string) error
|
||||
SearchBlockUser(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.ForbiddenAccount, error)
|
||||
FindBlockUser(ctx context.Context, userIDs []string) ([]*admindb.ForbiddenAccount, error)
|
||||
SearchUserLimitLogin(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.LimitUserLoginIP, error)
|
||||
AddUserLimitLogin(ctx context.Context, ms []*admindb.LimitUserLoginIP) error
|
||||
DelUserLimitLogin(ctx context.Context, ms []*admindb.LimitUserLoginIP) error
|
||||
CountLimitUserLoginIP(ctx context.Context, userID string) (uint32, error)
|
||||
GetLimitUserLoginIP(ctx context.Context, userID string, ip string) (*admindb.LimitUserLoginIP, error)
|
||||
CacheToken(ctx context.Context, userID string, token string, expire time.Duration) error
|
||||
GetTokens(ctx context.Context, userID string) (map[string]int32, error)
|
||||
DeleteToken(ctx context.Context, userID string) error
|
||||
LatestVersion(ctx context.Context, platform string) (*admindb.Application, error)
|
||||
AddVersion(ctx context.Context, val *admindb.Application) error
|
||||
UpdateVersion(ctx context.Context, id primitive.ObjectID, update map[string]any) error
|
||||
DeleteVersion(ctx context.Context, id []primitive.ObjectID) error
|
||||
PageVersion(ctx context.Context, platforms []string, page pagination.Pagination) (int64, []*admindb.Application, error)
|
||||
}
|
||||
|
||||
func NewAdminDatabase(cli *mongoutil.Client, rdb redis.UniversalClient) (AdminDatabaseInterface, error) {
|
||||
a, err := admin.NewAdmin(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forbidden, err := admin.NewIPForbidden(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forbiddenAccount, err := admin.NewForbiddenAccount(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
limitUserLoginIP, err := admin.NewLimitUserLoginIP(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
invitationRegister, err := admin.NewInvitationRegister(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registerAddFriend, err := admin.NewRegisterAddFriend(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
registerAddGroup, err := admin.NewRegisterAddGroup(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
applet, err := admin.NewApplet(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientConfig, err := admin.NewClientConfig(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
application, err := admin.NewApplication(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &AdminDatabase{
|
||||
tx: cli.GetTx(),
|
||||
admin: a,
|
||||
ipForbidden: forbidden,
|
||||
forbiddenAccount: forbiddenAccount,
|
||||
limitUserLoginIP: limitUserLoginIP,
|
||||
invitationRegister: invitationRegister,
|
||||
registerAddFriend: registerAddFriend,
|
||||
registerAddGroup: registerAddGroup,
|
||||
applet: applet,
|
||||
clientConfig: clientConfig,
|
||||
application: application,
|
||||
cache: cache.NewTokenInterface(rdb),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type AdminDatabase struct {
|
||||
tx tx.Tx
|
||||
admin admindb.AdminInterface
|
||||
ipForbidden admindb.IPForbiddenInterface
|
||||
forbiddenAccount admindb.ForbiddenAccountInterface
|
||||
limitUserLoginIP admindb.LimitUserLoginIPInterface
|
||||
invitationRegister admindb.InvitationRegisterInterface
|
||||
registerAddFriend admindb.RegisterAddFriendInterface
|
||||
registerAddGroup admindb.RegisterAddGroupInterface
|
||||
applet admindb.AppletInterface
|
||||
clientConfig admindb.ClientConfigInterface
|
||||
application admindb.ApplicationInterface
|
||||
cache cache.TokenInterface
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetAdmin(ctx context.Context, account string) (*admindb.Admin, error) {
|
||||
return o.admin.Take(ctx, account)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetAdminUserID(ctx context.Context, userID string) (*admindb.Admin, error) {
|
||||
return o.admin.TakeUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) UpdateAdmin(ctx context.Context, userID string, update map[string]any) error {
|
||||
return o.admin.Update(ctx, userID, update)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) ChangePassword(ctx context.Context, userID string, newPassword string) error {
|
||||
return o.admin.ChangePassword(ctx, userID, newPassword)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) ChangeOperationPassword(ctx context.Context, userID string, newPassword string) error {
|
||||
return o.admin.ChangeOperationPassword(ctx, userID, newPassword)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) ClearGoogleAuthKey(ctx context.Context, userID string) error {
|
||||
return o.admin.ClearGoogleAuthKey(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddAdminAccount(ctx context.Context, admins []*admindb.Admin) error {
|
||||
return o.admin.Create(ctx, admins)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelAdminAccount(ctx context.Context, userIDs []string) error {
|
||||
return o.admin.Delete(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchAdminAccount(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.Admin, error) {
|
||||
return o.admin.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CreateApplet(ctx context.Context, applets []*admindb.Applet) error {
|
||||
return o.applet.Create(ctx, applets)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelApplet(ctx context.Context, appletIDs []string) error {
|
||||
return o.applet.Del(ctx, appletIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetApplet(ctx context.Context, appletID string) (*admindb.Applet, error) {
|
||||
return o.applet.Take(ctx, appletID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindApplet(ctx context.Context, appletIDs []string) ([]*admindb.Applet, error) {
|
||||
return o.applet.FindID(ctx, appletIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchApplet(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.Applet, error) {
|
||||
return o.applet.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindOnShelf(ctx context.Context) ([]*admindb.Applet, error) {
|
||||
return o.applet.FindOnShelf(ctx)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) UpdateApplet(ctx context.Context, appletID string, update map[string]any) error {
|
||||
return o.applet.Update(ctx, appletID, update)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetConfig(ctx context.Context) (map[string]string, error) {
|
||||
return o.clientConfig.Get(ctx)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SetConfig(ctx context.Context, cs map[string]string) error {
|
||||
return o.clientConfig.Set(ctx, cs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelConfig(ctx context.Context, keys []string) error {
|
||||
return o.clientConfig.Del(ctx, keys)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindInvitationRegister(ctx context.Context, codes []string) ([]*admindb.InvitationRegister, error) {
|
||||
return o.invitationRegister.Find(ctx, codes)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelInvitationRegister(ctx context.Context, codes []string) error {
|
||||
return o.invitationRegister.Del(ctx, codes)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) UpdateInvitationRegister(ctx context.Context, code string, fields map[string]any) error {
|
||||
return o.invitationRegister.Update(ctx, code, fields)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CreatInvitationRegister(ctx context.Context, invitationRegisters []*admindb.InvitationRegister) error {
|
||||
return o.invitationRegister.Create(ctx, invitationRegisters)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchInvitationRegister(ctx context.Context, keyword string, state int32, userIDs []string, codes []string, pagination pagination.Pagination) (int64, []*admindb.InvitationRegister, error) {
|
||||
return o.invitationRegister.Search(ctx, keyword, state, userIDs, codes, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchIPForbidden(ctx context.Context, keyword string, state int32, pagination pagination.Pagination) (int64, []*admindb.IPForbidden, error) {
|
||||
return o.ipForbidden.Search(ctx, keyword, state, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddIPForbidden(ctx context.Context, ms []*admindb.IPForbidden) error {
|
||||
return o.ipForbidden.Create(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindIPForbidden(ctx context.Context, ms []string) ([]*admindb.IPForbidden, error) {
|
||||
return o.ipForbidden.Find(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelIPForbidden(ctx context.Context, ips []string) error {
|
||||
return o.ipForbidden.Delete(ctx, ips)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindDefaultFriend(ctx context.Context, userIDs []string) ([]string, error) {
|
||||
return o.registerAddFriend.FindUserID(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddDefaultFriend(ctx context.Context, ms []*admindb.RegisterAddFriend) error {
|
||||
return o.registerAddFriend.Add(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelDefaultFriend(ctx context.Context, userIDs []string) error {
|
||||
return o.registerAddFriend.Del(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchDefaultFriend(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.RegisterAddFriend, error) {
|
||||
return o.registerAddFriend.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindDefaultGroup(ctx context.Context, groupIDs []string) ([]string, error) {
|
||||
return o.registerAddGroup.FindGroupID(ctx, groupIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddDefaultGroup(ctx context.Context, ms []*admindb.RegisterAddGroup) error {
|
||||
return o.registerAddGroup.Add(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelDefaultGroup(ctx context.Context, groupIDs []string) error {
|
||||
return o.registerAddGroup.Del(ctx, groupIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchDefaultGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.RegisterAddGroup, error) {
|
||||
return o.registerAddGroup.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CountTotalGroups(ctx context.Context) (int64, error) {
|
||||
return o.registerAddGroup.CountTotal(ctx)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CountTodayNewGroups(ctx context.Context) (int64, error) {
|
||||
return o.registerAddGroup.CountToday(ctx)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CountTotalFriends(ctx context.Context) (int64, error) {
|
||||
return o.registerAddFriend.CountTotal(ctx)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindBlockInfo(ctx context.Context, userIDs []string) ([]*admindb.ForbiddenAccount, error) {
|
||||
return o.forbiddenAccount.Find(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetBlockInfo(ctx context.Context, userID string) (*admindb.ForbiddenAccount, error) {
|
||||
return o.forbiddenAccount.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) BlockUser(ctx context.Context, f []*admindb.ForbiddenAccount) error {
|
||||
return o.forbiddenAccount.Create(ctx, f)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelBlockUser(ctx context.Context, userID []string) error {
|
||||
return o.forbiddenAccount.Delete(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchBlockUser(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.ForbiddenAccount, error) {
|
||||
return o.forbiddenAccount.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) FindBlockUser(ctx context.Context, userIDs []string) ([]*admindb.ForbiddenAccount, error) {
|
||||
return o.forbiddenAccount.Find(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) SearchUserLimitLogin(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*admindb.LimitUserLoginIP, error) {
|
||||
return o.limitUserLoginIP.Search(ctx, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddUserLimitLogin(ctx context.Context, ms []*admindb.LimitUserLoginIP) error {
|
||||
return o.limitUserLoginIP.Create(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DelUserLimitLogin(ctx context.Context, ms []*admindb.LimitUserLoginIP) error {
|
||||
return o.limitUserLoginIP.Delete(ctx, ms)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CountLimitUserLoginIP(ctx context.Context, userID string) (uint32, error) {
|
||||
return o.limitUserLoginIP.Count(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetLimitUserLoginIP(ctx context.Context, userID string, ip string) (*admindb.LimitUserLoginIP, error) {
|
||||
return o.limitUserLoginIP.Take(ctx, userID, ip)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) CacheToken(ctx context.Context, userID string, token string, expire time.Duration) error {
|
||||
isSet, err := o.cache.AddTokenFlagNXEx(ctx, userID, token, constant.NormalToken, expire)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isSet {
|
||||
// already exists, update
|
||||
if err = o.cache.AddTokenFlag(ctx, userID, token, constant.NormalToken); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) GetTokens(ctx context.Context, userID string) (map[string]int32, error) {
|
||||
return o.cache.GetTokensWithoutError(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DeleteToken(ctx context.Context, userID string) error {
|
||||
return o.cache.DeleteTokenByUid(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) LatestVersion(ctx context.Context, platform string) (*admindb.Application, error) {
|
||||
return o.application.LatestVersion(ctx, platform)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) AddVersion(ctx context.Context, val *admindb.Application) error {
|
||||
return o.application.AddVersion(ctx, val)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) UpdateVersion(ctx context.Context, id primitive.ObjectID, update map[string]any) error {
|
||||
return o.application.UpdateVersion(ctx, id, update)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) DeleteVersion(ctx context.Context, id []primitive.ObjectID) error {
|
||||
return o.application.DeleteVersion(ctx, id)
|
||||
}
|
||||
|
||||
func (o *AdminDatabase) PageVersion(ctx context.Context, platforms []string, page pagination.Pagination) (int64, []*admindb.Application, error) {
|
||||
return o.application.PageVersion(ctx, platforms, page)
|
||||
}
|
||||
77
pkg/common/db/database/bot.go
Normal file
77
pkg/common/db/database/bot.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/model/bot"
|
||||
tablebot "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/db/tx"
|
||||
)
|
||||
|
||||
type BotDatabase interface {
|
||||
CreateAgent(ctx context.Context, jobs ...*tablebot.Agent) error
|
||||
TakeAgent(ctx context.Context, userID string) (*tablebot.Agent, error)
|
||||
FindAgents(ctx context.Context, userIDs []string) ([]*tablebot.Agent, error)
|
||||
UpdateAgent(ctx context.Context, userID string, data map[string]any) error
|
||||
DeleteAgents(ctx context.Context, userIDs []string) error
|
||||
PageAgents(ctx context.Context, userIDs []string, pagination pagination.Pagination) (int64, []*tablebot.Agent, error)
|
||||
|
||||
TakeConversationRespID(ctx context.Context, convID, agentID string) (*tablebot.ConversationRespID, error)
|
||||
UpdateConversationRespID(ctx context.Context, convID, agentID string, data map[string]any) error
|
||||
}
|
||||
|
||||
type botDatabase struct {
|
||||
tx tx.Tx
|
||||
agent tablebot.AgentInterface
|
||||
convRespID tablebot.ConversationRespIDInterface
|
||||
}
|
||||
|
||||
func NewBotDatabase(cli *mongoutil.Client) (BotDatabase, error) {
|
||||
agent, err := bot.NewAgent(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
convRespID, err := bot.NewConversationRespID(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &botDatabase{
|
||||
tx: cli.GetTx(),
|
||||
agent: agent,
|
||||
convRespID: convRespID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *botDatabase) CreateAgent(ctx context.Context, agents ...*tablebot.Agent) error {
|
||||
return a.agent.Create(ctx, agents...)
|
||||
}
|
||||
|
||||
func (a *botDatabase) TakeAgent(ctx context.Context, userID string) (*tablebot.Agent, error) {
|
||||
return a.agent.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (a *botDatabase) FindAgents(ctx context.Context, userIDs []string) ([]*tablebot.Agent, error) {
|
||||
return a.agent.Find(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (a *botDatabase) UpdateAgent(ctx context.Context, userID string, data map[string]any) error {
|
||||
return a.agent.Update(ctx, userID, data)
|
||||
}
|
||||
|
||||
func (a *botDatabase) DeleteAgents(ctx context.Context, userIDs []string) error {
|
||||
return a.agent.Delete(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (a *botDatabase) PageAgents(ctx context.Context, userIDs []string, pagination pagination.Pagination) (int64, []*tablebot.Agent, error) {
|
||||
return a.agent.Page(ctx, userIDs, pagination)
|
||||
}
|
||||
|
||||
func (a *botDatabase) UpdateConversationRespID(ctx context.Context, convID, agentID string, data map[string]any) error {
|
||||
return a.convRespID.Update(ctx, convID, agentID, data)
|
||||
}
|
||||
|
||||
func (a *botDatabase) TakeConversationRespID(ctx context.Context, convID, agentID string) (*tablebot.ConversationRespID, error) {
|
||||
return a.convRespID.Take(ctx, convID, agentID)
|
||||
}
|
||||
867
pkg/common/db/database/chat.go
Normal file
867
pkg/common/db/database/chat.go
Normal file
@@ -0,0 +1,867 @@
|
||||
// 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 database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"github.com/openimsdk/tools/db/tx"
|
||||
"github.com/redis/go-redis/v9"
|
||||
|
||||
"git.imall.cloud/openim/chat/pkg/common/constant"
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/cache"
|
||||
admindb "git.imall.cloud/openim/chat/pkg/common/db/model/admin"
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/model/chat"
|
||||
"git.imall.cloud/openim/chat/pkg/common/db/table/admin"
|
||||
chatdb "git.imall.cloud/openim/chat/pkg/common/db/table/chat"
|
||||
)
|
||||
|
||||
type ChatDatabaseInterface interface {
|
||||
GetUser(ctx context.Context, userID string) (account *chatdb.Account, err error)
|
||||
UpdateUseInfo(ctx context.Context, userID string, attribute map[string]any, updateCred, delCred []*chatdb.Credential) (err error)
|
||||
FindAttribute(ctx context.Context, userIDs []string) ([]*chatdb.Attribute, error)
|
||||
FindAttributeByAccount(ctx context.Context, accounts []string) ([]*chatdb.Attribute, error)
|
||||
TakeAttributeByPhone(ctx context.Context, areaCode string, phoneNumber string) (*chatdb.Attribute, error)
|
||||
TakeAttributeByEmail(ctx context.Context, Email string) (*chatdb.Attribute, error)
|
||||
TakeAttributeByAccount(ctx context.Context, account string) (*chatdb.Attribute, error)
|
||||
TakeAttributeByUserID(ctx context.Context, userID string) (*chatdb.Attribute, error)
|
||||
TakeAccount(ctx context.Context, userID string) (*chatdb.Account, error)
|
||||
TakeCredentialByAccount(ctx context.Context, account string) (*chatdb.Credential, error)
|
||||
TakeCredentialsByUserID(ctx context.Context, userID string) ([]*chatdb.Credential, error)
|
||||
TakeLastVerifyCode(ctx context.Context, account string) (*chatdb.VerifyCode, error)
|
||||
Search(ctx context.Context, normalUser int32, keyword string, genders int32, startTime, endTime *time.Time, pagination pagination.Pagination) (int64, []*chatdb.Attribute, error)
|
||||
SearchWithRealNameAuth(ctx context.Context, normalUser int32, keyword string, genders int32, startTime, endTime *time.Time, realNameKeyword string, idCardKeyword string, pagination pagination.Pagination) (total int64, attributes []*chatdb.Attribute, err error) // 搜索用户(支持实名信息搜索)
|
||||
SearchUser(ctx context.Context, keyword string, userIDs []string, genders []int32, pagination pagination.Pagination) (int64, []*chatdb.Attribute, error)
|
||||
CountVerifyCodeRange(ctx context.Context, account string, start time.Time, end time.Time) (int64, error)
|
||||
AddVerifyCode(ctx context.Context, verifyCode *chatdb.VerifyCode, fn func() error) error
|
||||
UpdateVerifyCodeIncrCount(ctx context.Context, id string) error
|
||||
DelVerifyCode(ctx context.Context, id string) error
|
||||
RegisterUser(ctx context.Context, register *chatdb.Register, account *chatdb.Account, attribute *chatdb.Attribute, credentials []*chatdb.Credential) error
|
||||
LoginRecord(ctx context.Context, record *chatdb.UserLoginRecord, verifyCodeID *string) error
|
||||
UpdatePassword(ctx context.Context, userID string, password string) error
|
||||
UpdatePasswordAndDeleteVerifyCode(ctx context.Context, userID string, password string, codeID string) error
|
||||
NewUserCountTotal(ctx context.Context, before *time.Time) (int64, error)
|
||||
UserLoginCountTotal(ctx context.Context, before *time.Time) (int64, error)
|
||||
UserLoginCountRangeEverydayTotal(ctx context.Context, start *time.Time, end *time.Time) (map[string]int64, int64, error)
|
||||
CountTodayRegisteredUsers(ctx context.Context) (int64, error)
|
||||
CountTodayActiveUsers(ctx context.Context) (int64, error)
|
||||
GetLatestLoginIP(ctx context.Context, userID string) (string, error) // 获取用户最新登录IP
|
||||
SearchUserLoginRecords(ctx context.Context, userID, ip string, pagination pagination.Pagination) (int64, []*chatdb.UserLoginRecord, error) // 查询用户登录记录(支持按用户ID或IP查询)
|
||||
DelUserAccount(ctx context.Context, userIDs []string) error
|
||||
|
||||
// 敏感词相关方法
|
||||
GetSensitiveWords(ctx context.Context) ([]*chatdb.SensitiveWord, error)
|
||||
CheckSensitiveWords(ctx context.Context, content string) ([]*chatdb.SensitiveWord, bool, error)
|
||||
FilterContent(ctx context.Context, content string) (string, []*chatdb.SensitiveWord, bool, error)
|
||||
GetSensitiveWordConfig(ctx context.Context) (*chatdb.SensitiveWordConfig, error)
|
||||
|
||||
// 敏感词管理相关方法
|
||||
CreateSensitiveWord(ctx context.Context, word *chatdb.SensitiveWord) error
|
||||
UpdateSensitiveWord(ctx context.Context, id string, data map[string]any) error
|
||||
DeleteSensitiveWord(ctx context.Context, ids []string) error
|
||||
GetSensitiveWord(ctx context.Context, id string) (*chatdb.SensitiveWord, error)
|
||||
SearchSensitiveWords(ctx context.Context, keyword string, action int32, status int32, pagination pagination.Pagination) (int64, []*chatdb.SensitiveWord, error)
|
||||
BatchAddSensitiveWords(ctx context.Context, words []*chatdb.SensitiveWord) error
|
||||
BatchUpdateSensitiveWords(ctx context.Context, updates map[string]map[string]any) error
|
||||
BatchDeleteSensitiveWords(ctx context.Context, ids []string) error
|
||||
|
||||
// 敏感词分组管理
|
||||
CreateSensitiveWordGroup(ctx context.Context, group *chatdb.SensitiveWordGroup) error
|
||||
UpdateSensitiveWordGroup(ctx context.Context, id string, data map[string]any) error
|
||||
DeleteSensitiveWordGroup(ctx context.Context, ids []string) error
|
||||
GetSensitiveWordGroup(ctx context.Context, id string) (*chatdb.SensitiveWordGroup, error)
|
||||
GetAllSensitiveWordGroups(ctx context.Context) ([]*chatdb.SensitiveWordGroup, error)
|
||||
|
||||
// 敏感词配置管理
|
||||
UpdateSensitiveWordConfig(ctx context.Context, config *chatdb.SensitiveWordConfig) error
|
||||
|
||||
// 敏感词日志管理
|
||||
GetSensitiveWordLogs(ctx context.Context, userID, groupID string, pagination pagination.Pagination) (int64, []*chatdb.SensitiveWordLog, error)
|
||||
DeleteSensitiveWordLogs(ctx context.Context, ids []string) error
|
||||
|
||||
// 敏感词统计
|
||||
GetSensitiveWordStats(ctx context.Context) (map[string]int64, error)
|
||||
GetSensitiveWordLogStats(ctx context.Context, startTime, endTime time.Time) (map[string]int64, error)
|
||||
|
||||
// 收藏相关方法
|
||||
CreateFavorite(ctx context.Context, favorite *chatdb.Favorite) error
|
||||
GetFavorite(ctx context.Context, favoriteID string) (*chatdb.Favorite, error)
|
||||
GetFavoritesByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error)
|
||||
GetFavoritesByUserIDAndType(ctx context.Context, userID string, favoriteType int32, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error)
|
||||
SearchFavoritesByKeyword(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error)
|
||||
UpdateFavorite(ctx context.Context, favoriteID string, data map[string]any) error
|
||||
DeleteFavorite(ctx context.Context, favoriteIDs []string) error
|
||||
DeleteFavoritesByUserID(ctx context.Context, userID string) error
|
||||
CountFavoritesByUserID(ctx context.Context, userID string) (int64, error)
|
||||
GetFavoritesByTags(ctx context.Context, userID string, tags []string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error)
|
||||
|
||||
// 定时任务相关方法
|
||||
CreateScheduledTask(ctx context.Context, task *chatdb.ScheduledTask) error
|
||||
GetScheduledTask(ctx context.Context, taskID string) (*chatdb.ScheduledTask, error)
|
||||
GetScheduledTasksByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.ScheduledTask, error)
|
||||
GetAllScheduledTasks(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.ScheduledTask, error)
|
||||
UpdateScheduledTask(ctx context.Context, taskID string, data map[string]any) error
|
||||
DeleteScheduledTask(ctx context.Context, taskIDs []string) error
|
||||
|
||||
// 系统配置相关方法
|
||||
CreateSystemConfig(ctx context.Context, config *chatdb.SystemConfig) error
|
||||
GetSystemConfig(ctx context.Context, key string) (*chatdb.SystemConfig, error)
|
||||
GetSystemConfigsByKeys(ctx context.Context, keys []string) ([]*chatdb.SystemConfig, error)
|
||||
GetAllSystemConfigs(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.SystemConfig, error)
|
||||
UpdateSystemConfig(ctx context.Context, key string, data map[string]any) error
|
||||
UpdateSystemConfigValue(ctx context.Context, key string, value string) error
|
||||
UpdateSystemConfigEnabled(ctx context.Context, key string, enabled bool) error
|
||||
DeleteSystemConfig(ctx context.Context, keys []string) error
|
||||
GetEnabledSystemConfigs(ctx context.Context) ([]*chatdb.SystemConfig, error)
|
||||
GetAppSystemConfigs(ctx context.Context) ([]*chatdb.SystemConfig, error) // 获取所有 show_in_app=true 且 enabled=true 的配置
|
||||
|
||||
// 钱包相关方法
|
||||
GetWallet(ctx context.Context, userID string) (*chatdb.Wallet, error) // 获取钱包信息
|
||||
GetWalletsByUserIDs(ctx context.Context, userIDs []string) ([]*chatdb.Wallet, error) // 根据用户ID列表批量获取钱包
|
||||
GetWalletsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) // 分页获取钱包列表
|
||||
GetWalletsPageByRealNameAuthAuditStatus(ctx context.Context, auditStatus int32, userID string, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) // 按实名认证审核状态分页查询钱包(支持用户ID搜索)
|
||||
CreateWallet(ctx context.Context, wallet *chatdb.Wallet) error // 创建钱包
|
||||
UpdateWalletBalance(ctx context.Context, userID string, balance int64) error // 更新钱包余额
|
||||
IncrementWalletBalance(ctx context.Context, userID string, amount int64) (beforeBalance int64, afterBalance int64, err error) // 原子更新余额,返回更新前后的余额
|
||||
UpdateWalletPaymentPassword(ctx context.Context, userID string, paymentPassword string) error // 更新支付密码
|
||||
UpdateWalletWithdrawAccount(ctx context.Context, userID string, withdrawAccount string) error // 更新提款账号(兼容旧接口)
|
||||
UpdateWalletWithdrawAccountWithType(ctx context.Context, userID string, withdrawAccount string, accountType int32) error // 更新提款账号(带类型)
|
||||
UpdateWalletRealNameAuth(ctx context.Context, userID string, realNameAuth chatdb.RealNameAuth) error // 更新实名认证信息
|
||||
GetWalletBalanceRecords(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) // 获取钱包余额变动记录
|
||||
GetWalletBalanceRecordsByUserIDAndType(ctx context.Context, userID string, recordType int32, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) // 根据类型获取钱包余额变动记录
|
||||
CreateWalletBalanceRecord(ctx context.Context, record *chatdb.WalletBalanceRecord) error // 创建余额变动记录
|
||||
|
||||
// 提现相关方法
|
||||
CreateWithdraw(ctx context.Context, withdraw *chatdb.Withdraw) error // 创建提现记录
|
||||
GetWithdraw(ctx context.Context, withdrawID string) (*chatdb.Withdraw, error) // 获取提现记录
|
||||
GetWithdrawsByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) // 获取用户的提现记录列表
|
||||
GetWithdrawsByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) // 根据状态获取提现记录列表
|
||||
UpdateWithdrawStatus(ctx context.Context, withdrawID string, status int32, auditorID string, auditRemark string) error // 更新提现状态(审核)
|
||||
GetWithdrawsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) // 获取提现记录列表(分页)
|
||||
|
||||
// 提现申请相关方法
|
||||
CreateWithdrawApplication(ctx context.Context, application *chatdb.WithdrawApplication) error // 创建提现申请
|
||||
GetWithdrawApplication(ctx context.Context, applicationID string) (*chatdb.WithdrawApplication, error) // 获取提现申请
|
||||
GetWithdrawApplicationsByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) // 获取用户的提现申请列表
|
||||
GetWithdrawApplicationsByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) // 根据状态获取提现申请列表
|
||||
UpdateWithdrawApplicationStatus(ctx context.Context, applicationID string, status int32, auditorID string, auditRemark string) error // 更新提现申请状态(审核)
|
||||
GetWithdrawApplicationsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) // 获取提现申请列表(分页)
|
||||
UpdateWithdrawApplication(ctx context.Context, applicationID string, data map[string]any) error // 更新提现申请
|
||||
}
|
||||
|
||||
func NewChatDatabase(cli *mongoutil.Client, rdb redis.UniversalClient) (ChatDatabaseInterface, error) {
|
||||
register, err := chat.NewRegister(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
account, err := chat.NewAccount(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
attribute, err := chat.NewAttribute(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credential, err := chat.NewCredential(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userLoginRecord, err := chat.NewUserLoginRecord(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
verifyCode, err := chat.NewVerifyCode(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forbiddenAccount, err := admindb.NewForbiddenAccount(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sensitiveWord, err := chat.NewSensitiveWord(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
favorite, err := chat.NewFavorite(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scheduledTask, err := chat.NewScheduledTask(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
systemConfig, err := chat.NewSystemConfig(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wallet, err := chat.NewWallet(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
walletBalanceRecord, err := chat.NewWalletBalanceRecord(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
withdraw, err := chat.NewWithdraw(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
withdrawApplication, err := chat.NewWithdrawApplication(cli.GetDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userLoginIPCache cache.UserLoginIPInterface
|
||||
if rdb != nil {
|
||||
userLoginIPCache = cache.NewUserLoginIPInterface(rdb)
|
||||
}
|
||||
|
||||
return &ChatDatabase{
|
||||
tx: cli.GetTx(),
|
||||
register: register,
|
||||
account: account,
|
||||
attribute: attribute,
|
||||
credential: credential,
|
||||
userLoginRecord: userLoginRecord,
|
||||
verifyCode: verifyCode,
|
||||
forbiddenAccount: forbiddenAccount,
|
||||
sensitiveWord: sensitiveWord,
|
||||
favorite: favorite,
|
||||
scheduledTask: scheduledTask,
|
||||
systemConfig: systemConfig,
|
||||
wallet: wallet,
|
||||
walletBalanceRecord: walletBalanceRecord,
|
||||
withdraw: withdraw,
|
||||
withdrawApplication: withdrawApplication,
|
||||
userLoginIPCache: userLoginIPCache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ChatDatabase struct {
|
||||
tx tx.Tx
|
||||
register chatdb.RegisterInterface
|
||||
account chatdb.AccountInterface
|
||||
attribute chatdb.AttributeInterface
|
||||
credential chatdb.CredentialInterface
|
||||
userLoginRecord chatdb.UserLoginRecordInterface
|
||||
verifyCode chatdb.VerifyCodeInterface
|
||||
forbiddenAccount admin.ForbiddenAccountInterface
|
||||
sensitiveWord chatdb.SensitiveWordInterface
|
||||
favorite chatdb.FavoriteInterface
|
||||
scheduledTask chatdb.ScheduledTaskInterface
|
||||
systemConfig chatdb.SystemConfigInterface
|
||||
wallet chatdb.WalletInterface
|
||||
walletBalanceRecord chatdb.WalletBalanceRecordInterface
|
||||
withdraw chatdb.WithdrawInterface
|
||||
withdrawApplication chatdb.WithdrawApplicationInterface
|
||||
userLoginIPCache cache.UserLoginIPInterface // 用户登录IP缓存(可选,如果为nil则不使用缓存)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetUser(ctx context.Context, userID string) (account *chatdb.Account, err error) {
|
||||
return o.account.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateUseInfo(ctx context.Context, userID string, attribute map[string]any, updateCred, delCred []*chatdb.Credential) (err error) {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err = o.attribute.Update(ctx, userID, attribute); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, credential := range updateCred {
|
||||
if err = o.credential.CreateOrUpdateAccount(ctx, credential); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = o.credential.DeleteByUserIDType(ctx, delCred...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) FindAttribute(ctx context.Context, userIDs []string) ([]*chatdb.Attribute, error) {
|
||||
return o.attribute.Find(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) FindAttributeByAccount(ctx context.Context, accounts []string) ([]*chatdb.Attribute, error) {
|
||||
return o.attribute.FindAccount(ctx, accounts)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeAttributeByPhone(ctx context.Context, areaCode string, phoneNumber string) (*chatdb.Attribute, error) {
|
||||
return o.attribute.TakePhone(ctx, areaCode, phoneNumber)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeAttributeByEmail(ctx context.Context, email string) (*chatdb.Attribute, error) {
|
||||
return o.attribute.TakeEmail(ctx, email)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeAttributeByAccount(ctx context.Context, account string) (*chatdb.Attribute, error) {
|
||||
return o.attribute.TakeAccount(ctx, account)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeAttributeByUserID(ctx context.Context, userID string) (*chatdb.Attribute, error) {
|
||||
return o.attribute.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeLastVerifyCode(ctx context.Context, account string) (*chatdb.VerifyCode, error) {
|
||||
return o.verifyCode.TakeLast(ctx, account)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeAccount(ctx context.Context, userID string) (*chatdb.Account, error) {
|
||||
return o.account.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeCredentialByAccount(ctx context.Context, account string) (*chatdb.Credential, error) {
|
||||
return o.credential.TakeAccount(ctx, account)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) TakeCredentialsByUserID(ctx context.Context, userID string) ([]*chatdb.Credential, error) {
|
||||
return o.credential.Find(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) Search(ctx context.Context, normalUser int32, keyword string, genders int32, startTime, endTime *time.Time, pagination pagination.Pagination) (total int64, attributes []*chatdb.Attribute, err error) {
|
||||
var forbiddenIDs []string
|
||||
if int(normalUser) == constant.NormalUser {
|
||||
forbiddenIDs, err = o.forbiddenAccount.FindAllIDs(ctx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
total, totalUser, err := o.attribute.SearchNormalUser(ctx, keyword, forbiddenIDs, genders, startTime, endTime, pagination)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, totalUser, nil
|
||||
}
|
||||
|
||||
// SearchWithRealNameAuth 搜索用户(支持实名信息搜索)
|
||||
func (o *ChatDatabase) SearchWithRealNameAuth(ctx context.Context, normalUser int32, keyword string, genders int32, startTime, endTime *time.Time, realNameKeyword string, idCardKeyword string, pagination pagination.Pagination) (total int64, attributes []*chatdb.Attribute, err error) {
|
||||
// 如果提供了实名信息搜索关键词,先查询钱包获取userIDs
|
||||
var realNameAuthUserIDs []string
|
||||
if realNameKeyword != "" || idCardKeyword != "" {
|
||||
realNameAuthUserIDs, err = o.wallet.SearchByRealNameAuth(ctx, realNameKeyword, idCardKeyword)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
// 如果没有找到匹配的用户,直接返回空结果
|
||||
if len(realNameAuthUserIDs) == 0 {
|
||||
return 0, []*chatdb.Attribute{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
var forbiddenIDs []string
|
||||
if int(normalUser) == constant.NormalUser {
|
||||
forbiddenIDs, err = o.forbiddenAccount.FindAllIDs(ctx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 如果提供了实名信息搜索,需要在用户ID列表中过滤
|
||||
if len(realNameAuthUserIDs) > 0 {
|
||||
// 修改 SearchNormalUser 方法,支持传入额外的 userIDs 过滤条件
|
||||
// 或者创建一个新的方法
|
||||
// 这里我们修改 SearchNormalUser 来支持这个功能
|
||||
total, totalUser, err := o.attribute.SearchNormalUserWithUserIDs(ctx, keyword, forbiddenIDs, genders, startTime, endTime, realNameAuthUserIDs, pagination)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return total, totalUser, nil
|
||||
}
|
||||
|
||||
// 没有实名信息搜索,使用原来的方法
|
||||
return o.Search(ctx, normalUser, keyword, genders, startTime, endTime, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) SearchUser(ctx context.Context, keyword string, userIDs []string, genders []int32, pagination pagination.Pagination) (int64, []*chatdb.Attribute, error) {
|
||||
return o.attribute.SearchUser(ctx, keyword, userIDs, genders, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CountVerifyCodeRange(ctx context.Context, account string, start time.Time, end time.Time) (int64, error) {
|
||||
return o.verifyCode.RangeNum(ctx, account, start, end)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) AddVerifyCode(ctx context.Context, verifyCode *chatdb.VerifyCode, fn func() error) error {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err := o.verifyCode.Add(ctx, []*chatdb.VerifyCode{verifyCode}); err != nil {
|
||||
return err
|
||||
}
|
||||
if fn != nil {
|
||||
return fn()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateVerifyCodeIncrCount(ctx context.Context, id string) error {
|
||||
return o.verifyCode.Incr(ctx, id)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DelVerifyCode(ctx context.Context, id string) error {
|
||||
return o.verifyCode.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) RegisterUser(ctx context.Context, register *chatdb.Register, account *chatdb.Account, attribute *chatdb.Attribute, credentials []*chatdb.Credential) error {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err := o.register.Create(ctx, register); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.account.Create(ctx, account); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.attribute.Create(ctx, attribute); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.credential.Create(ctx, credentials...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) LoginRecord(ctx context.Context, record *chatdb.UserLoginRecord, verifyCodeID *string) error {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err := o.userLoginRecord.Create(ctx, record); err != nil {
|
||||
return err
|
||||
}
|
||||
// 创建登录记录后,更新缓存(保证缓存一致性)
|
||||
if o.userLoginIPCache != nil && record.UserID != "" {
|
||||
// 先删除旧缓存,然后设置新缓存
|
||||
// 使用新IP更新缓存,这样下次查询时可以直接从缓存获取
|
||||
_ = o.userLoginIPCache.SetLatestLoginIP(ctx, record.UserID, record.IP)
|
||||
}
|
||||
if verifyCodeID != nil {
|
||||
if err := o.verifyCode.Delete(ctx, *verifyCodeID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdatePassword(ctx context.Context, userID string, password string) error {
|
||||
return o.account.UpdatePassword(ctx, userID, password)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdatePasswordAndDeleteVerifyCode(ctx context.Context, userID string, password string, codeID string) error {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err := o.account.UpdatePassword(ctx, userID, password); err != nil {
|
||||
return err
|
||||
}
|
||||
if codeID == "" {
|
||||
return nil
|
||||
}
|
||||
if err := o.verifyCode.Delete(ctx, codeID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) NewUserCountTotal(ctx context.Context, before *time.Time) (int64, error) {
|
||||
return o.register.CountTotal(ctx, before)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UserLoginCountTotal(ctx context.Context, before *time.Time) (int64, error) {
|
||||
return o.userLoginRecord.CountTotal(ctx, before)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UserLoginCountRangeEverydayTotal(ctx context.Context, start *time.Time, end *time.Time) (map[string]int64, int64, error) {
|
||||
return o.userLoginRecord.CountRangeEverydayTotal(ctx, start, end)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CountTodayRegisteredUsers(ctx context.Context) (int64, error) {
|
||||
return o.register.CountToday(ctx)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CountTodayActiveUsers(ctx context.Context) (int64, error) {
|
||||
return o.userLoginRecord.CountTodayActiveUsers(ctx)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetLatestLoginIP(ctx context.Context, userID string) (string, error) {
|
||||
// 如果启用了缓存,先尝试从缓存获取
|
||||
if o.userLoginIPCache != nil {
|
||||
ip, found, err := o.userLoginIPCache.GetLatestLoginIP(ctx, userID)
|
||||
if err != nil {
|
||||
// 缓存查询出错,降级到数据库查询
|
||||
return o.userLoginRecord.GetLatestLoginIP(ctx, userID)
|
||||
}
|
||||
// 如果缓存命中,直接返回(即使IP为空字符串,也表示用户确实没有IP)
|
||||
if found {
|
||||
return ip, nil
|
||||
}
|
||||
// 缓存未命中,从数据库查询
|
||||
ip, err = o.userLoginRecord.GetLatestLoginIP(ctx, userID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 将查询结果写入缓存(即使为空也缓存,避免频繁查询数据库)
|
||||
_ = o.userLoginIPCache.SetLatestLoginIP(ctx, userID, ip)
|
||||
return ip, nil
|
||||
}
|
||||
// 未启用缓存,直接从数据库查询
|
||||
return o.userLoginRecord.GetLatestLoginIP(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) SearchUserLoginRecords(ctx context.Context, userID, ip string, pagination pagination.Pagination) (int64, []*chatdb.UserLoginRecord, error) {
|
||||
return o.userLoginRecord.Search(ctx, userID, ip, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DelUserAccount(ctx context.Context, userIDs []string) error {
|
||||
return o.tx.Transaction(ctx, func(ctx context.Context) error {
|
||||
if err := o.register.Delete(ctx, userIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.account.Delete(ctx, userIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.attribute.Delete(ctx, userIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 敏感词相关方法实现 ====================
|
||||
|
||||
// GetSensitiveWords 获取所有启用的敏感词
|
||||
func (o *ChatDatabase) GetSensitiveWords(ctx context.Context) ([]*chatdb.SensitiveWord, error) {
|
||||
return o.sensitiveWord.GetEnabledSensitiveWords(ctx)
|
||||
}
|
||||
|
||||
// CheckSensitiveWords 检测敏感词
|
||||
func (o *ChatDatabase) CheckSensitiveWords(ctx context.Context, content string) ([]*chatdb.SensitiveWord, bool, error) {
|
||||
words, err := o.sensitiveWord.CheckSensitiveWords(ctx, content)
|
||||
hasSensitive := len(words) > 0
|
||||
return words, hasSensitive, err
|
||||
}
|
||||
|
||||
// FilterContent 过滤内容
|
||||
func (o *ChatDatabase) FilterContent(ctx context.Context, content string) (string, []*chatdb.SensitiveWord, bool, error) {
|
||||
filteredContent, words, err := o.sensitiveWord.FilterContent(ctx, content)
|
||||
hasSensitive := len(words) > 0
|
||||
return filteredContent, words, hasSensitive, err
|
||||
}
|
||||
|
||||
// GetSensitiveWordConfig 获取敏感词配置
|
||||
func (o *ChatDatabase) GetSensitiveWordConfig(ctx context.Context) (*chatdb.SensitiveWordConfig, error) {
|
||||
return o.sensitiveWord.GetSensitiveWordConfig(ctx)
|
||||
}
|
||||
|
||||
// ==================== 敏感词管理相关方法实现 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateSensitiveWord(ctx context.Context, word *chatdb.SensitiveWord) error {
|
||||
return o.sensitiveWord.CreateSensitiveWord(ctx, word)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateSensitiveWord(ctx context.Context, id string, data map[string]any) error {
|
||||
return o.sensitiveWord.UpdateSensitiveWord(ctx, id, data)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteSensitiveWord(ctx context.Context, ids []string) error {
|
||||
return o.sensitiveWord.DeleteSensitiveWord(ctx, ids)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetSensitiveWord(ctx context.Context, id string) (*chatdb.SensitiveWord, error) {
|
||||
return o.sensitiveWord.GetSensitiveWord(ctx, id)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) SearchSensitiveWords(ctx context.Context, keyword string, action int32, status int32, pagination pagination.Pagination) (int64, []*chatdb.SensitiveWord, error) {
|
||||
return o.sensitiveWord.SearchSensitiveWords(ctx, keyword, action, status, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) BatchAddSensitiveWords(ctx context.Context, words []*chatdb.SensitiveWord) error {
|
||||
return o.sensitiveWord.BatchCreateSensitiveWords(ctx, words)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) BatchUpdateSensitiveWords(ctx context.Context, updates map[string]map[string]any) error {
|
||||
return o.sensitiveWord.BatchUpdateSensitiveWords(ctx, updates)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) BatchDeleteSensitiveWords(ctx context.Context, ids []string) error {
|
||||
return o.sensitiveWord.BatchDeleteSensitiveWords(ctx, ids)
|
||||
}
|
||||
|
||||
// ==================== 敏感词分组管理实现 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateSensitiveWordGroup(ctx context.Context, group *chatdb.SensitiveWordGroup) error {
|
||||
return o.sensitiveWord.CreateSensitiveWordGroup(ctx, group)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateSensitiveWordGroup(ctx context.Context, id string, data map[string]any) error {
|
||||
return o.sensitiveWord.UpdateSensitiveWordGroup(ctx, id, data)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteSensitiveWordGroup(ctx context.Context, ids []string) error {
|
||||
return o.sensitiveWord.DeleteSensitiveWordGroup(ctx, ids)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetSensitiveWordGroup(ctx context.Context, id string) (*chatdb.SensitiveWordGroup, error) {
|
||||
return o.sensitiveWord.GetSensitiveWordGroup(ctx, id)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetAllSensitiveWordGroups(ctx context.Context) ([]*chatdb.SensitiveWordGroup, error) {
|
||||
return o.sensitiveWord.GetAllSensitiveWordGroups(ctx)
|
||||
}
|
||||
|
||||
// ==================== 敏感词配置管理实现 ====================
|
||||
|
||||
func (o *ChatDatabase) UpdateSensitiveWordConfig(ctx context.Context, config *chatdb.SensitiveWordConfig) error {
|
||||
return o.sensitiveWord.UpdateSensitiveWordConfig(ctx, config)
|
||||
}
|
||||
|
||||
// ==================== 敏感词日志管理实现 ====================
|
||||
|
||||
func (o *ChatDatabase) GetSensitiveWordLogs(ctx context.Context, userID, groupID string, pagination pagination.Pagination) (int64, []*chatdb.SensitiveWordLog, error) {
|
||||
return o.sensitiveWord.GetSensitiveWordLogs(ctx, userID, groupID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteSensitiveWordLogs(ctx context.Context, ids []string) error {
|
||||
return o.sensitiveWord.DeleteSensitiveWordLogs(ctx, ids)
|
||||
}
|
||||
|
||||
// ==================== 敏感词统计实现 ====================
|
||||
|
||||
func (o *ChatDatabase) GetSensitiveWordStats(ctx context.Context) (map[string]int64, error) {
|
||||
return o.sensitiveWord.GetSensitiveWordStats(ctx)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetSensitiveWordLogStats(ctx context.Context, startTime, endTime time.Time) (map[string]int64, error) {
|
||||
return o.sensitiveWord.GetSensitiveWordLogStats(ctx, startTime, endTime)
|
||||
}
|
||||
|
||||
// ==================== 收藏相关方法实现 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateFavorite(ctx context.Context, favorite *chatdb.Favorite) error {
|
||||
return o.favorite.Create(ctx, favorite)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetFavorite(ctx context.Context, favoriteID string) (*chatdb.Favorite, error) {
|
||||
return o.favorite.Take(ctx, favoriteID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetFavoritesByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error) {
|
||||
return o.favorite.FindByUserID(ctx, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetFavoritesByUserIDAndType(ctx context.Context, userID string, favoriteType int32, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error) {
|
||||
return o.favorite.FindByUserIDAndType(ctx, userID, favoriteType, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) SearchFavoritesByKeyword(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error) {
|
||||
return o.favorite.SearchByKeyword(ctx, userID, keyword, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateFavorite(ctx context.Context, favoriteID string, data map[string]any) error {
|
||||
return o.favorite.Update(ctx, favoriteID, data)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteFavorite(ctx context.Context, favoriteIDs []string) error {
|
||||
return o.favorite.Delete(ctx, favoriteIDs)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteFavoritesByUserID(ctx context.Context, userID string) error {
|
||||
return o.favorite.DeleteByUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CountFavoritesByUserID(ctx context.Context, userID string) (int64, error) {
|
||||
return o.favorite.CountByUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetFavoritesByTags(ctx context.Context, userID string, tags []string, pagination pagination.Pagination) (int64, []*chatdb.Favorite, error) {
|
||||
return o.favorite.FindByTags(ctx, userID, tags, pagination)
|
||||
}
|
||||
|
||||
// ==================== 定时任务相关方法实现 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateScheduledTask(ctx context.Context, task *chatdb.ScheduledTask) error {
|
||||
return o.scheduledTask.Create(ctx, task)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetScheduledTask(ctx context.Context, taskID string) (*chatdb.ScheduledTask, error) {
|
||||
return o.scheduledTask.Take(ctx, taskID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetScheduledTasksByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.ScheduledTask, error) {
|
||||
return o.scheduledTask.FindByUserID(ctx, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetAllScheduledTasks(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.ScheduledTask, error) {
|
||||
return o.scheduledTask.FindAll(ctx, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateScheduledTask(ctx context.Context, taskID string, data map[string]any) error {
|
||||
return o.scheduledTask.Update(ctx, taskID, data)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteScheduledTask(ctx context.Context, taskIDs []string) error {
|
||||
return o.scheduledTask.Delete(ctx, taskIDs)
|
||||
}
|
||||
|
||||
// ==================== 系统配置相关方法实现 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateSystemConfig(ctx context.Context, config *chatdb.SystemConfig) error {
|
||||
return o.systemConfig.Create(ctx, config)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetSystemConfig(ctx context.Context, key string) (*chatdb.SystemConfig, error) {
|
||||
return o.systemConfig.Take(ctx, key)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetSystemConfigsByKeys(ctx context.Context, keys []string) ([]*chatdb.SystemConfig, error) {
|
||||
return o.systemConfig.FindByKeys(ctx, keys)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetAllSystemConfigs(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.SystemConfig, error) {
|
||||
return o.systemConfig.FindAll(ctx, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateSystemConfig(ctx context.Context, key string, data map[string]any) error {
|
||||
return o.systemConfig.Update(ctx, key, data)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateSystemConfigValue(ctx context.Context, key string, value string) error {
|
||||
return o.systemConfig.UpdateValue(ctx, key, value)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateSystemConfigEnabled(ctx context.Context, key string, enabled bool) error {
|
||||
return o.systemConfig.UpdateEnabled(ctx, key, enabled)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) DeleteSystemConfig(ctx context.Context, keys []string) error {
|
||||
return o.systemConfig.Delete(ctx, keys)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetEnabledSystemConfigs(ctx context.Context) ([]*chatdb.SystemConfig, error) {
|
||||
return o.systemConfig.GetEnabledConfigs(ctx)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetAppSystemConfigs(ctx context.Context) ([]*chatdb.SystemConfig, error) {
|
||||
return o.systemConfig.GetAppConfigs(ctx)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWallet(ctx context.Context, userID string) (*chatdb.Wallet, error) {
|
||||
return o.wallet.Take(ctx, userID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWalletsByUserIDs(ctx context.Context, userIDs []string) ([]*chatdb.Wallet, error) {
|
||||
return o.wallet.Find(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWalletsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) {
|
||||
return o.wallet.Page(ctx, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWalletsPageByRealNameAuthAuditStatus(ctx context.Context, auditStatus int32, userID string, pagination pagination.Pagination) (int64, []*chatdb.Wallet, error) {
|
||||
return o.wallet.PageByRealNameAuthAuditStatus(ctx, auditStatus, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWalletBalance(ctx context.Context, userID string, balance int64) error {
|
||||
return o.wallet.UpdateBalance(ctx, userID, balance)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) IncrementWalletBalance(ctx context.Context, userID string, amount int64) (beforeBalance int64, afterBalance int64, err error) {
|
||||
return o.wallet.IncrementBalance(ctx, userID, amount)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWalletPaymentPassword(ctx context.Context, userID string, paymentPassword string) error {
|
||||
return o.wallet.UpdatePaymentPassword(ctx, userID, paymentPassword)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWalletWithdrawAccount(ctx context.Context, userID string, withdrawAccount string) error {
|
||||
return o.wallet.UpdateWithdrawAccount(ctx, userID, withdrawAccount)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWalletWithdrawAccountWithType(ctx context.Context, userID string, withdrawAccount string, accountType int32) error {
|
||||
return o.wallet.UpdateWithdrawAccountWithType(ctx, userID, withdrawAccount, accountType)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWalletRealNameAuth(ctx context.Context, userID string, realNameAuth chatdb.RealNameAuth) error {
|
||||
return o.wallet.UpdateRealNameAuth(ctx, userID, realNameAuth)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CreateWallet(ctx context.Context, wallet *chatdb.Wallet) error {
|
||||
return o.wallet.Create(ctx, wallet)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWalletBalanceRecords(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) {
|
||||
return o.walletBalanceRecord.FindByUserID(ctx, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWalletBalanceRecordsByUserIDAndType(ctx context.Context, userID string, recordType int32, pagination pagination.Pagination) (int64, []*chatdb.WalletBalanceRecord, error) {
|
||||
return o.walletBalanceRecord.FindByUserIDAndType(ctx, userID, recordType, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) CreateWalletBalanceRecord(ctx context.Context, record *chatdb.WalletBalanceRecord) error {
|
||||
return o.walletBalanceRecord.Create(ctx, record)
|
||||
}
|
||||
|
||||
// ==================== 提现相关方法 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateWithdraw(ctx context.Context, withdraw *chatdb.Withdraw) error {
|
||||
return o.withdraw.Create(ctx, withdraw)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdraw(ctx context.Context, withdrawID string) (*chatdb.Withdraw, error) {
|
||||
return o.withdraw.Take(ctx, withdrawID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawsByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
return o.withdraw.FindByUserID(ctx, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawsByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
return o.withdraw.FindByStatus(ctx, status, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWithdrawStatus(ctx context.Context, withdrawID string, status int32, auditorID string, auditRemark string) error {
|
||||
return o.withdraw.UpdateStatus(ctx, withdrawID, status, auditorID, auditRemark)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.Withdraw, error) {
|
||||
return o.withdraw.Page(ctx, pagination)
|
||||
}
|
||||
|
||||
// ==================== 提现申请相关方法 ====================
|
||||
|
||||
func (o *ChatDatabase) CreateWithdrawApplication(ctx context.Context, application *chatdb.WithdrawApplication) error {
|
||||
return o.withdrawApplication.Create(ctx, application)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawApplication(ctx context.Context, applicationID string) (*chatdb.WithdrawApplication, error) {
|
||||
return o.withdrawApplication.Take(ctx, applicationID)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawApplicationsByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
return o.withdrawApplication.FindByUserID(ctx, userID, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawApplicationsByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
return o.withdrawApplication.FindByStatus(ctx, status, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWithdrawApplicationStatus(ctx context.Context, applicationID string, status int32, auditorID string, auditRemark string) error {
|
||||
return o.withdrawApplication.UpdateStatus(ctx, applicationID, status, auditorID, auditRemark)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) GetWithdrawApplicationsPage(ctx context.Context, pagination pagination.Pagination) (int64, []*chatdb.WithdrawApplication, error) {
|
||||
return o.withdrawApplication.Page(ctx, pagination)
|
||||
}
|
||||
|
||||
func (o *ChatDatabase) UpdateWithdrawApplication(ctx context.Context, applicationID string, data map[string]any) error {
|
||||
return o.withdrawApplication.Update(ctx, applicationID, data)
|
||||
}
|
||||
24
pkg/common/db/dbutil/gorm.go
Normal file
24
pkg/common/db/dbutil/gorm.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// 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 dbutil
|
||||
|
||||
import (
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
func IsDBNotFound(err error) bool {
|
||||
return errs.Unwrap(err) == mongo.ErrNoDocuments
|
||||
}
|
||||
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)
|
||||
}
|
||||
51
pkg/common/db/table/admin/admin.go
Normal file
51
pkg/common/db/table/admin/admin.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// Admin user
|
||||
type Admin struct {
|
||||
Account string `bson:"account"`
|
||||
Password string `bson:"password"`
|
||||
OperationPassword string `bson:"operation_password"`
|
||||
FaceURL string `bson:"face_url"`
|
||||
Nickname string `bson:"nickname"`
|
||||
UserID string `bson:"user_id"`
|
||||
Level int32 `bson:"level"`
|
||||
GoogleAuthKey string `bson:"google_auth_key"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (Admin) TableName() string {
|
||||
return "admins"
|
||||
}
|
||||
|
||||
type AdminInterface interface {
|
||||
Create(ctx context.Context, admins []*Admin) error
|
||||
Take(ctx context.Context, account string) (*Admin, error)
|
||||
TakeUserID(ctx context.Context, userID string) (*Admin, error)
|
||||
Update(ctx context.Context, account string, update map[string]any) error
|
||||
ChangePassword(ctx context.Context, userID string, newPassword string) error
|
||||
ChangeOperationPassword(ctx context.Context, userID string, newPassword string) error
|
||||
ClearGoogleAuthKey(ctx context.Context, userID string) error
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*Admin, error)
|
||||
}
|
||||
49
pkg/common/db/table/admin/applet.go
Normal file
49
pkg/common/db/table/admin/applet.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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/pagination"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Applet struct {
|
||||
ID string `bson:"id"`
|
||||
Name string `bson:"name"`
|
||||
AppID string `bson:"app_id"`
|
||||
Icon string `bson:"icon"`
|
||||
URL string `bson:"url"`
|
||||
MD5 string `bson:"md5"`
|
||||
Size int64 `bson:"size"`
|
||||
Version string `bson:"version"`
|
||||
Priority uint32 `bson:"priority"`
|
||||
Status uint8 `bson:"status"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (Applet) TableName() string {
|
||||
return "applets"
|
||||
}
|
||||
|
||||
type AppletInterface interface {
|
||||
Create(ctx context.Context, applets []*Applet) error
|
||||
Del(ctx context.Context, ids []string) error
|
||||
Update(ctx context.Context, id string, data map[string]any) error
|
||||
Take(ctx context.Context, id string) (*Applet, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*Applet, error)
|
||||
FindOnShelf(ctx context.Context) ([]*Applet, error)
|
||||
FindID(ctx context.Context, ids []string) ([]*Applet, error)
|
||||
}
|
||||
29
pkg/common/db/table/admin/application.go
Normal file
29
pkg/common/db/table/admin/application.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
Platform string `bson:"platform"`
|
||||
Hot bool `bson:"hot"`
|
||||
Version string `bson:"version"`
|
||||
Url string `bson:"url"`
|
||||
Text string `bson:"text"`
|
||||
Force bool `bson:"force"`
|
||||
Latest bool `bson:"latest"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
type ApplicationInterface interface {
|
||||
LatestVersion(ctx context.Context, platform string) (*Application, error)
|
||||
AddVersion(ctx context.Context, val *Application) error
|
||||
UpdateVersion(ctx context.Context, id primitive.ObjectID, update map[string]any) error
|
||||
DeleteVersion(ctx context.Context, id []primitive.ObjectID) error
|
||||
PageVersion(ctx context.Context, platforms []string, page pagination.Pagination) (int64, []*Application, error)
|
||||
FindPlatform(ctx context.Context, id []primitive.ObjectID) ([]string, error)
|
||||
}
|
||||
33
pkg/common/db/table/admin/client_config.go
Normal file
33
pkg/common/db/table/admin/client_config.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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"
|
||||
|
||||
// ClientConfig config
|
||||
type ClientConfig struct {
|
||||
Key string `bson:"key"`
|
||||
Value string `bson:"value"`
|
||||
}
|
||||
|
||||
func (ClientConfig) TableName() string {
|
||||
return "client_config"
|
||||
}
|
||||
|
||||
type ClientConfigInterface interface {
|
||||
Set(ctx context.Context, config map[string]string) error
|
||||
Get(ctx context.Context) (map[string]string, error)
|
||||
Del(ctx context.Context, keys []string) error
|
||||
}
|
||||
42
pkg/common/db/table/admin/forbidden_account.go
Normal file
42
pkg/common/db/table/admin/forbidden_account.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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/pagination"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ForbiddenAccount table
|
||||
type ForbiddenAccount struct {
|
||||
UserID string `bson:"user_id"`
|
||||
Reason string `bson:"reason"`
|
||||
OperatorUserID string `bson:"operator_user_id"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (ForbiddenAccount) TableName() string {
|
||||
return "forbidden_accounts"
|
||||
}
|
||||
|
||||
type ForbiddenAccountInterface interface {
|
||||
Create(ctx context.Context, ms []*ForbiddenAccount) error
|
||||
Take(ctx context.Context, userID string) (*ForbiddenAccount, error)
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
Find(ctx context.Context, userIDs []string) ([]*ForbiddenAccount, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*ForbiddenAccount, error)
|
||||
FindAllIDs(ctx context.Context) ([]string, error)
|
||||
}
|
||||
40
pkg/common/db/table/admin/invitation_register.go
Normal file
40
pkg/common/db/table/admin/invitation_register.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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/pagination"
|
||||
"time"
|
||||
)
|
||||
|
||||
type InvitationRegister struct {
|
||||
InvitationCode string `bson:"invitation_code"`
|
||||
UsedByUserID string `bson:"used_by_user_id"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (InvitationRegister) TableName() string {
|
||||
return "invitation_registers"
|
||||
}
|
||||
|
||||
type InvitationRegisterInterface interface {
|
||||
Find(ctx context.Context, codes []string) ([]*InvitationRegister, error)
|
||||
Del(ctx context.Context, codes []string) error
|
||||
Create(ctx context.Context, v []*InvitationRegister) error
|
||||
Take(ctx context.Context, code string) (*InvitationRegister, error)
|
||||
Update(ctx context.Context, code string, data map[string]any) error
|
||||
Search(ctx context.Context, keyword string, state int32, userIDs []string, codes []string, pagination pagination.Pagination) (int64, []*InvitationRegister, error)
|
||||
}
|
||||
40
pkg/common/db/table/admin/ip_forbidden.go
Normal file
40
pkg/common/db/table/admin/ip_forbidden.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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/pagination"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IPForbidden struct {
|
||||
IP string `bson:"ip"`
|
||||
LimitRegister bool `bson:"limit_register"`
|
||||
LimitLogin bool `bson:"limit_login"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (IPForbidden) IPForbidden() string {
|
||||
return "ip_forbiddens"
|
||||
}
|
||||
|
||||
type IPForbiddenInterface interface {
|
||||
Take(ctx context.Context, ip string) (*IPForbidden, error)
|
||||
Find(ctx context.Context, ips []string) ([]*IPForbidden, error)
|
||||
Search(ctx context.Context, keyword string, state int32, pagination pagination.Pagination) (int64, []*IPForbidden, error)
|
||||
Create(ctx context.Context, ms []*IPForbidden) error
|
||||
Delete(ctx context.Context, ips []string) error
|
||||
}
|
||||
39
pkg/common/db/table/admin/limit_user_login_ip.go
Normal file
39
pkg/common/db/table/admin/limit_user_login_ip.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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/pagination"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LimitUserLoginIP struct {
|
||||
UserID string `bson:"user_id"`
|
||||
IP string `bson:"ip"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (LimitUserLoginIP) TableName() string {
|
||||
return "limit_user_login_ips"
|
||||
}
|
||||
|
||||
type LimitUserLoginIPInterface interface {
|
||||
Create(ctx context.Context, ms []*LimitUserLoginIP) error
|
||||
Delete(ctx context.Context, ms []*LimitUserLoginIP) error
|
||||
Count(ctx context.Context, userID string) (uint32, error)
|
||||
Take(ctx context.Context, userID string, ip string) (*LimitUserLoginIP, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*LimitUserLoginIP, error)
|
||||
}
|
||||
39
pkg/common/db/table/admin/register_add_friend.go
Normal file
39
pkg/common/db/table/admin/register_add_friend.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
type RegisterAddFriend struct {
|
||||
UserID string `bson:"user_id"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (RegisterAddFriend) TableName() string {
|
||||
return "register_add_friends"
|
||||
}
|
||||
|
||||
type RegisterAddFriendInterface interface {
|
||||
Add(ctx context.Context, registerAddFriends []*RegisterAddFriend) error
|
||||
Del(ctx context.Context, userIDs []string) error
|
||||
FindUserID(ctx context.Context, userIDs []string) ([]string, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*RegisterAddFriend, error)
|
||||
CountTotal(ctx context.Context) (int64, error) // 统计好友总数
|
||||
}
|
||||
40
pkg/common/db/table/admin/register_add_group.go
Normal file
40
pkg/common/db/table/admin/register_add_group.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
type RegisterAddGroup struct {
|
||||
GroupID string `bson:"group_id"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (RegisterAddGroup) TableName() string {
|
||||
return "register_add_groups"
|
||||
}
|
||||
|
||||
type RegisterAddGroupInterface interface {
|
||||
Add(ctx context.Context, registerAddGroups []*RegisterAddGroup) error
|
||||
Del(ctx context.Context, groupIDs []string) error
|
||||
FindGroupID(ctx context.Context, groupIDs []string) ([]string, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*RegisterAddGroup, error)
|
||||
CountTotal(ctx context.Context) (int64, error) // 统计群组总数
|
||||
CountToday(ctx context.Context) (int64, error) // 统计今天新建的群组数
|
||||
}
|
||||
33
pkg/common/db/table/bot/agent.go
Normal file
33
pkg/common/db/table/bot/agent.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
UserID string `bson:"user_id"`
|
||||
NickName string `bson:"nick_name"`
|
||||
FaceURL string `bson:"face_url"`
|
||||
Key string `bson:"key"`
|
||||
Url string `bson:"url"`
|
||||
Identity string `bson:"identity"`
|
||||
Model string `bson:"model"`
|
||||
Prompts string `bson:"prompts"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (Agent) TableName() string {
|
||||
return "agent"
|
||||
}
|
||||
|
||||
type AgentInterface interface {
|
||||
Create(ctx context.Context, elems ...*Agent) error
|
||||
Take(ctx context.Context, userID string) (*Agent, error)
|
||||
Find(ctx context.Context, userIDs []string) ([]*Agent, error)
|
||||
Update(ctx context.Context, userID string, data map[string]any) error
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
Page(ctx context.Context, userIDs []string, pagination pagination.Pagination) (int64, []*Agent, error)
|
||||
}
|
||||
22
pkg/common/db/table/bot/conversation_resp_id.go
Normal file
22
pkg/common/db/table/bot/conversation_resp_id.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package bot
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ConversationRespID struct {
|
||||
ConversationID string `bson:"conversation_id"`
|
||||
AgentID string `bson:"agent_id"`
|
||||
PreviousResponseID string `bson:"previous_response_id"`
|
||||
}
|
||||
|
||||
func (ConversationRespID) TableName() string {
|
||||
return "conversation_resp_id"
|
||||
}
|
||||
|
||||
type ConversationRespIDInterface interface {
|
||||
Create(ctx context.Context, elems ...*ConversationRespID) error
|
||||
Take(ctx context.Context, convID, agentID string) (*ConversationRespID, error)
|
||||
Update(ctx context.Context, convID, agentID string, data map[string]any) error
|
||||
Delete(ctx context.Context, convID, agentID string) error
|
||||
}
|
||||
40
pkg/common/db/table/chat/account.go
Normal file
40
pkg/common/db/table/chat/account.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
UserID string `bson:"user_id"`
|
||||
Password string `bson:"password"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
ChangeTime time.Time `bson:"change_time"`
|
||||
OperatorUserID string `bson:"operator_user_id"`
|
||||
}
|
||||
|
||||
func (Account) TableName() string {
|
||||
return "accounts"
|
||||
}
|
||||
|
||||
type AccountInterface interface {
|
||||
Create(ctx context.Context, accounts ...*Account) error
|
||||
Take(ctx context.Context, userId string) (*Account, error)
|
||||
Update(ctx context.Context, userID string, data map[string]any) error
|
||||
UpdatePassword(ctx context.Context, userId string, password string) error
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
}
|
||||
51
pkg/common/db/table/chat/attribute.go
Normal file
51
pkg/common/db/table/chat/attribute.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
)
|
||||
|
||||
type Attribute struct {
|
||||
UserID string `bson:"user_id"`
|
||||
Account string `bson:"account"`
|
||||
PhoneNumber string `bson:"phone_number"`
|
||||
AreaCode string `bson:"area_code"`
|
||||
Email string `bson:"email"`
|
||||
Nickname string `bson:"nickname"`
|
||||
FaceURL string `bson:"face_url"`
|
||||
Gender int32 `bson:"gender"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
ChangeTime time.Time `bson:"change_time"`
|
||||
BirthTime time.Time `bson:"birth_time"`
|
||||
Level int32 `bson:"level"`
|
||||
UserType int32 `bson:"user_type"` // 用户类型: 0=普通用户, 1=企业用户, 2=机器人, 3=管理员
|
||||
UserFlag string `bson:"user_flag"` // 用户标签/标识,类似UserType的字符串版本
|
||||
AllowVibration int32 `bson:"allow_vibration"`
|
||||
AllowBeep int32 `bson:"allow_beep"`
|
||||
AllowAddFriend int32 `bson:"allow_add_friend"`
|
||||
GlobalRecvMsgOpt int32 `bson:"global_recv_msg_opt"`
|
||||
RegisterType int32 `bson:"register_type"`
|
||||
}
|
||||
|
||||
func (Attribute) TableName() string {
|
||||
return "attributes"
|
||||
}
|
||||
|
||||
type AttributeInterface interface {
|
||||
// NewTx(tx any) AttributeInterface
|
||||
Create(ctx context.Context, attribute ...*Attribute) error
|
||||
Update(ctx context.Context, userID string, data map[string]any) error
|
||||
Find(ctx context.Context, userIds []string) ([]*Attribute, error)
|
||||
FindAccount(ctx context.Context, accounts []string) ([]*Attribute, error)
|
||||
Search(ctx context.Context, keyword string, genders []int32, pagination pagination.Pagination) (int64, []*Attribute, error)
|
||||
TakePhone(ctx context.Context, areaCode string, phoneNumber string) (*Attribute, error)
|
||||
TakeEmail(ctx context.Context, email string) (*Attribute, error)
|
||||
TakeAccount(ctx context.Context, account string) (*Attribute, error)
|
||||
Take(ctx context.Context, userID string) (*Attribute, error)
|
||||
SearchNormalUser(ctx context.Context, keyword string, forbiddenID []string, gender int32, startTime, endTime *time.Time, pagination pagination.Pagination) (int64, []*Attribute, error)
|
||||
SearchNormalUserWithUserIDs(ctx context.Context, keyword string, forbiddenID []string, gender int32, startTime, endTime *time.Time, userIDs []string, pagination pagination.Pagination) (int64, []*Attribute, error) // 按条件搜索用户(支持额外的userIDs过滤)
|
||||
SearchUser(ctx context.Context, keyword string, userIDs []string, genders []int32, pagination pagination.Pagination) (int64, []*Attribute, error)
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
}
|
||||
32
pkg/common/db/table/chat/credential.go
Normal file
32
pkg/common/db/table/chat/credential.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
)
|
||||
|
||||
type Credential struct {
|
||||
UserID string `bson:"user_id"`
|
||||
Account string `bson:"account"`
|
||||
Type int `bson:"type"` // 1:phone;2:email
|
||||
AllowChange bool `bson:"allow_change"`
|
||||
}
|
||||
|
||||
func (Credential) TableName() string {
|
||||
return "credentials"
|
||||
}
|
||||
|
||||
type CredentialInterface interface {
|
||||
Create(ctx context.Context, credential ...*Credential) error
|
||||
CreateOrUpdateAccount(ctx context.Context, credential *Credential) error
|
||||
Update(ctx context.Context, userID string, data map[string]any) error
|
||||
Find(ctx context.Context, userID string) ([]*Credential, error)
|
||||
FindAccount(ctx context.Context, accounts []string) ([]*Credential, error)
|
||||
Search(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*Credential, error)
|
||||
TakeAccount(ctx context.Context, account string) (*Credential, error)
|
||||
Take(ctx context.Context, userID string) (*Credential, error)
|
||||
SearchNormalUser(ctx context.Context, keyword string, forbiddenID []string, pagination pagination.Pagination) (int64, []*Credential, error)
|
||||
SearchUser(ctx context.Context, keyword string, userIDs []string, pagination pagination.Pagination) (int64, []*Credential, error)
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
DeleteByUserIDType(ctx context.Context, credentials ...*Credential) error
|
||||
}
|
||||
69
pkg/common/db/table/chat/favorite.go
Normal file
69
pkg/common/db/table/chat/favorite.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// FavoriteType 收藏类型
|
||||
const (
|
||||
FavoriteTypeText = 1 // 文本
|
||||
FavoriteTypeImage = 2 // 图片
|
||||
FavoriteTypeLink = 3 // 链接
|
||||
FavoriteTypeFile = 4 // 文件
|
||||
FavoriteTypeVoice = 5 // 语音
|
||||
FavoriteTypeVideo = 6 // 视频
|
||||
FavoriteTypeLocation = 7 // 位置
|
||||
)
|
||||
|
||||
type Favorite struct {
|
||||
ID string `bson:"_id"` // 收藏ID(MongoDB ObjectID)
|
||||
UserID string `bson:"user_id"` // 用户ID(收藏者)
|
||||
Type int32 `bson:"type"` // 收藏类型:1-文本,2-图片,3-链接,4-文件,5-语音,6-视频,7-位置
|
||||
Title string `bson:"title"` // 标题(可选)
|
||||
Content string `bson:"content"` // 内容(根据类型不同,可能是文本、图片URL、链接URL、文件路径等)
|
||||
Description string `bson:"description"` // 摘要/描述(可选)
|
||||
Thumbnail string `bson:"thumbnail"` // 缩略图URL(用于图片、视频、链接等)
|
||||
LinkURL string `bson:"link_url"` // 链接URL(用于链接类型)
|
||||
FileSize int64 `bson:"file_size"` // 文件大小(字节,用于文件、语音、视频等)
|
||||
Duration int32 `bson:"duration"` // 时长(秒,用于语音、视频等)
|
||||
Location string `bson:"location"` // 位置信息(JSON格式,用于位置类型)
|
||||
Tags []string `bson:"tags"` // 标签列表
|
||||
Remark string `bson:"remark"` // 备注(可选)
|
||||
Status int32 `bson:"status"` // 状态:0-已删除,1-正常
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (Favorite) TableName() string {
|
||||
return "favorites"
|
||||
}
|
||||
|
||||
type FavoriteInterface interface {
|
||||
Create(ctx context.Context, favorites ...*Favorite) error
|
||||
Take(ctx context.Context, favoriteID string) (*Favorite, error)
|
||||
FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*Favorite, error)
|
||||
FindByUserIDAndType(ctx context.Context, userID string, favoriteType int32, pagination pagination.Pagination) (int64, []*Favorite, error)
|
||||
SearchByKeyword(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*Favorite, error)
|
||||
Update(ctx context.Context, favoriteID string, data map[string]any) error
|
||||
Delete(ctx context.Context, favoriteIDs []string) error
|
||||
DeleteByUserID(ctx context.Context, userID string) error
|
||||
CountByUserID(ctx context.Context, userID string) (int64, error)
|
||||
FindByTags(ctx context.Context, userID string, tags []string, pagination pagination.Pagination) (int64, []*Favorite, error)
|
||||
}
|
||||
67
pkg/common/db/table/chat/livekit.go
Normal file
67
pkg/common/db/table/chat/livekit.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LiveKit 表示一台LiveKit服务器配置
|
||||
type LiveKit struct {
|
||||
ID string `bson:"_id" json:"id"` // 服务器唯一标识
|
||||
Name string `bson:"name" json:"name"` // 服务器名称
|
||||
URL string `bson:"url" json:"url"` // LiveKit服务器地址
|
||||
Key string `bson:"key" json:"key"` // API Key
|
||||
Secret string `bson:"secret" json:"secret"` // API Secret
|
||||
Region string `bson:"region" json:"region"` // 服务器区域
|
||||
Status int `bson:"status" json:"status"` // 状态:0-禁用,1-启用
|
||||
Priority int `bson:"priority" json:"priority"` // 优先级,数字越小优先级越高
|
||||
MaxRooms int `bson:"max_rooms" json:"max_rooms"` // 最大房间数
|
||||
MaxUsers int `bson:"max_users" json:"max_users"` // 最大用户数
|
||||
Description string `bson:"description" json:"description"` // 描述信息
|
||||
CreateTime time.Time `bson:"create_time" json:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time" json:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
// TableName 返回表名
|
||||
func (LiveKit) TableName() string {
|
||||
return "livekits"
|
||||
}
|
||||
|
||||
// LiveKitInterface 定义LiveKit数据库操作接口
|
||||
type LiveKitInterface interface {
|
||||
// Create 创建LiveKit服务器配置
|
||||
Create(ctx context.Context, livekits ...*LiveKit) error
|
||||
// Delete 删除LiveKit服务器配置
|
||||
Delete(ctx context.Context, ids []string) error
|
||||
// Update 更新LiveKit服务器配置
|
||||
Update(ctx context.Context, livekit *LiveKit) error
|
||||
// FindByID 根据ID查找LiveKit配置
|
||||
FindByID(ctx context.Context, id string) (*LiveKit, error)
|
||||
// FindByStatus 根据状态查找LiveKit配置列表
|
||||
FindByStatus(ctx context.Context, status int) ([]*LiveKit, error)
|
||||
// FindAll 查找所有LiveKit配置
|
||||
FindAll(ctx context.Context) ([]*LiveKit, error)
|
||||
// FindAvailable 查找可用的LiveKit服务器(按优先级排序)
|
||||
FindAvailable(ctx context.Context) ([]*LiveKit, error)
|
||||
// FindByRegion 根据区域查找LiveKit配置
|
||||
FindByRegion(ctx context.Context, region string) ([]*LiveKit, error)
|
||||
// UpdateStatus 更新服务器状态
|
||||
UpdateStatus(ctx context.Context, id string, status int) error
|
||||
// UpdatePriority 更新服务器优先级
|
||||
UpdatePriority(ctx context.Context, id string, priority int) error
|
||||
// GetNextAvailable 获取下一个可用的LiveKit服务器(负载均衡)
|
||||
GetNextAvailable(ctx context.Context) (*LiveKit, error)
|
||||
}
|
||||
|
||||
// 状态常量
|
||||
const (
|
||||
LiveKitStatusDisabled = 0 // 禁用
|
||||
LiveKitStatusEnabled = 1 // 启用
|
||||
)
|
||||
|
||||
// 默认值
|
||||
const (
|
||||
DefaultMaxRooms = 1000 // 默认最大房间数
|
||||
DefaultMaxUsers = 100 // 默认最大用户数
|
||||
DefaultPriority = 100 // 默认优先级
|
||||
)
|
||||
42
pkg/common/db/table/chat/register.go
Normal file
42
pkg/common/db/table/chat/register.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type Register struct {
|
||||
UserID string `bson:"user_id"`
|
||||
DeviceID string `bson:"device_id"`
|
||||
IP string `bson:"ip"`
|
||||
Platform string `bson:"platform"`
|
||||
AccountType string `bson:"account_type"`
|
||||
Mode string `bson:"mode"`
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (Register) TableName() string {
|
||||
return "registers"
|
||||
}
|
||||
|
||||
type RegisterInterface interface {
|
||||
// NewTx(tx any) RegisterInterface
|
||||
Create(ctx context.Context, registers ...*Register) error
|
||||
CountTotal(ctx context.Context, before *time.Time) (int64, error)
|
||||
CountToday(ctx context.Context) (int64, error) // 统计今天注册的用户数
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
}
|
||||
78
pkg/common/db/table/chat/scheduled_task.go
Normal file
78
pkg/common/db/table/chat/scheduled_task.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// ScheduledTaskStatus 定时任务状态
|
||||
const (
|
||||
ScheduledTaskStatusDisabled = 0 // 已禁用
|
||||
ScheduledTaskStatusEnabled = 1 // 已启用
|
||||
)
|
||||
|
||||
// MessageType 消息类型
|
||||
const (
|
||||
MessageTypeText = 1 // 文本消息
|
||||
MessageTypeImage = 2 // 图片消息
|
||||
MessageTypeVideo = 3 // 视频消息
|
||||
)
|
||||
|
||||
// ScheduledTask 定时任务配置
|
||||
// CronExpression格式:分 时 日 月 周
|
||||
// 例如:"0 9 * * *" 表示每天9点执行
|
||||
//
|
||||
// "*/5 * * * *" 表示每5分钟执行
|
||||
// "0 0 * * 1" 表示每周一0点执行
|
||||
type ScheduledTask struct {
|
||||
ID string `bson:"_id"` // 任务ID
|
||||
UserID string `bson:"user_id"` // 用户ID
|
||||
Name string `bson:"name"` // 任务名称
|
||||
CronExpression string `bson:"cron_expression"` // Crontab表达式:分 时 日 月 周(例如:"0 9 * * *")
|
||||
Messages []Message `bson:"messages"` // 消息列表(支持多条消息一起发送)
|
||||
RecvIDs []string `bson:"recv_ids"` // 接收者ID列表(单聊,可以多个)
|
||||
GroupIDs []string `bson:"group_ids"` // 群组ID列表(群聊,可以多个)
|
||||
Status int32 `bson:"status"` // 状态:0-已禁用,1-已启用
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
// Message 消息内容
|
||||
type Message struct {
|
||||
Type int32 `bson:"type"` // 消息类型:1-文本,2-图片,3-视频
|
||||
Content string `bson:"content"` // 消息内容(文本内容、图片URL、视频URL等)
|
||||
Thumbnail string `bson:"thumbnail"` // 缩略图URL(用于图片和视频)
|
||||
Duration int32 `bson:"duration"` // 时长(秒,用于视频)
|
||||
FileSize int64 `bson:"file_size"` // 文件大小(字节,用于图片和视频)
|
||||
Width int32 `bson:"width"` // 宽度(像素,用于图片和视频)
|
||||
Height int32 `bson:"height"` // 高度(像素,用于图片和视频)
|
||||
}
|
||||
|
||||
func (ScheduledTask) TableName() string {
|
||||
return "scheduled_tasks"
|
||||
}
|
||||
|
||||
type ScheduledTaskInterface interface {
|
||||
Create(ctx context.Context, tasks ...*ScheduledTask) error
|
||||
Take(ctx context.Context, taskID string) (*ScheduledTask, error)
|
||||
FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*ScheduledTask, error)
|
||||
FindAll(ctx context.Context, pagination pagination.Pagination) (int64, []*ScheduledTask, error)
|
||||
Update(ctx context.Context, taskID string, data map[string]any) error
|
||||
Delete(ctx context.Context, taskIDs []string) error
|
||||
}
|
||||
144
pkg/common/db/table/chat/sensitive_word.go
Normal file
144
pkg/common/db/table/chat/sensitive_word.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/tools/db/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 敏感词相关结构体定义
|
||||
type SensitiveWord struct {
|
||||
ID string `bson:"_id" json:"id"` // 主键ID
|
||||
Word string `bson:"word" json:"word"` // 敏感词内容
|
||||
Level int32 `bson:"level" json:"level"` // 敏感词级别 1:低 2:中 3:高
|
||||
Type int32 `bson:"type" json:"type"` // 敏感词类型 1:政治 2:色情 3:暴力 4:广告 5:其他
|
||||
Action int32 `bson:"action" json:"action"` // 处理动作 1:替换为*** 2:拦截不发
|
||||
Status int32 `bson:"status" json:"status"` // 状态 1:启用 0:禁用
|
||||
Creator string `bson:"creator" json:"creator"` // 创建者
|
||||
Updater string `bson:"updater" json:"updater"` // 更新者
|
||||
CreateTime time.Time `bson:"create_time" json:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time" json:"update_time"` // 更新时间
|
||||
Remark string `bson:"remark" json:"remark"` // 备注
|
||||
}
|
||||
|
||||
func (SensitiveWord) TableName() string {
|
||||
return "sensitive_words"
|
||||
}
|
||||
|
||||
type SensitiveWordLog struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
UserID string `bson:"user_id"` // 触发用户ID
|
||||
GroupID string `bson:"group_id"` // 触发群组ID (如果是在群聊中)
|
||||
Content string `bson:"content"` // 原始消息内容
|
||||
MatchedWords []string `bson:"matched_words"` // 匹配到的敏感词
|
||||
Action int32 `bson:"action"` // 采取的动作
|
||||
ProcessedText string `bson:"processed_text"` // 处理后的文本 (如果被替换)
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
}
|
||||
|
||||
func (SensitiveWordLog) TableName() string {
|
||||
return "sensitive_word_logs"
|
||||
}
|
||||
|
||||
type SensitiveWordGroup struct {
|
||||
ID primitive.ObjectID `bson:"_id,omitempty"`
|
||||
Name string `bson:"name"` // 分组名称
|
||||
Remark string `bson:"remark"` // 备注
|
||||
CreateTime time.Time `bson:"create_time"`
|
||||
UpdateTime time.Time `bson:"update_time"`
|
||||
}
|
||||
|
||||
func (SensitiveWordGroup) TableName() string {
|
||||
return "sensitive_word_groups"
|
||||
}
|
||||
|
||||
type SensitiveWordConfig struct {
|
||||
ID string `bson:"_id" json:"id"` // 主键ID
|
||||
EnableFilter bool `bson:"enable_filter" json:"enable_filter"` // 是否启用过滤
|
||||
FilterMode int32 `bson:"filter_mode" json:"filter_mode"` // 过滤模式
|
||||
ReplaceChar string `bson:"replace_char" json:"replace_char"` // 替换字符,默认***
|
||||
WhitelistUsers []string `bson:"whitelist_users" json:"whitelist_users"` // 白名单用户
|
||||
WhitelistGroups []string `bson:"whitelist_groups" json:"whitelist_groups"` // 白名单群组
|
||||
LogEnabled bool `bson:"log_enabled" json:"log_enabled"` // 是否记录日志
|
||||
AutoApprove bool `bson:"auto_approve" json:"auto_approve"` // 是否自动审核
|
||||
UpdateTime time.Time `bson:"update_time" json:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (SensitiveWordConfig) TableName() string {
|
||||
return "sensitive_word_configs"
|
||||
}
|
||||
|
||||
// 敏感词级别常量
|
||||
const (
|
||||
SensitiveLevelLow = 1 // 低级别
|
||||
SensitiveLevelMedium = 2 // 中级别
|
||||
SensitiveLevelHigh = 3 // 高级别
|
||||
)
|
||||
|
||||
// 敏感词类型常量
|
||||
const (
|
||||
SensitiveTypePolitical = 1 // 政治
|
||||
SensitiveTypePorn = 2 // 色情
|
||||
SensitiveTypeViolence = 3 // 暴力
|
||||
SensitiveTypeAd = 4 // 广告
|
||||
SensitiveTypeOther = 5 // 其他
|
||||
)
|
||||
|
||||
// 处理动作常量
|
||||
const (
|
||||
SensitiveActionReplace = 1 // 替换为***
|
||||
SensitiveActionBlock = 2 // 拦截不发
|
||||
)
|
||||
|
||||
// 状态常量
|
||||
const (
|
||||
SensitiveStatusDisabled = 0 // 禁用
|
||||
SensitiveStatusEnabled = 1 // 启用
|
||||
)
|
||||
|
||||
type SensitiveWordInterface interface {
|
||||
// 敏感词管理
|
||||
CreateSensitiveWord(ctx context.Context, word *SensitiveWord) error
|
||||
UpdateSensitiveWord(ctx context.Context, id string, data map[string]any) error
|
||||
DeleteSensitiveWord(ctx context.Context, ids []string) error
|
||||
GetSensitiveWord(ctx context.Context, id string) (*SensitiveWord, error)
|
||||
SearchSensitiveWords(ctx context.Context, keyword string, action int32, status int32, pagination pagination.Pagination) (int64, []*SensitiveWord, error)
|
||||
GetAllSensitiveWords(ctx context.Context) ([]*SensitiveWord, error)
|
||||
GetEnabledSensitiveWords(ctx context.Context) ([]*SensitiveWord, error)
|
||||
|
||||
// 敏感词检测
|
||||
CheckSensitiveWords(ctx context.Context, content string) ([]*SensitiveWord, error)
|
||||
FilterContent(ctx context.Context, content string) (string, []*SensitiveWord, error)
|
||||
|
||||
// 敏感词日志
|
||||
CreateSensitiveWordLog(ctx context.Context, log *SensitiveWordLog) error
|
||||
GetSensitiveWordLogs(ctx context.Context, userID string, groupID string, pagination pagination.Pagination) (int64, []*SensitiveWordLog, error)
|
||||
DeleteSensitiveWordLogs(ctx context.Context, ids []string) error
|
||||
|
||||
// 敏感词分组管理
|
||||
CreateSensitiveWordGroup(ctx context.Context, group *SensitiveWordGroup) error
|
||||
UpdateSensitiveWordGroup(ctx context.Context, id string, data map[string]any) error
|
||||
DeleteSensitiveWordGroup(ctx context.Context, ids []string) error
|
||||
GetSensitiveWordGroup(ctx context.Context, id string) (*SensitiveWordGroup, error)
|
||||
GetAllSensitiveWordGroups(ctx context.Context) ([]*SensitiveWordGroup, error)
|
||||
|
||||
// 敏感词配置管理
|
||||
GetSensitiveWordConfig(ctx context.Context) (*SensitiveWordConfig, error)
|
||||
UpdateSensitiveWordConfig(ctx context.Context, config *SensitiveWordConfig) error
|
||||
IsFilterEnabled(ctx context.Context) (bool, error)
|
||||
GetFilterMode(ctx context.Context) (int32, error)
|
||||
GetReplaceChar(ctx context.Context) (string, error)
|
||||
IsUserInWhitelist(ctx context.Context, userID string) (bool, error)
|
||||
IsGroupInWhitelist(ctx context.Context, groupID string) (bool, error)
|
||||
|
||||
// 批量操作
|
||||
BatchCreateSensitiveWords(ctx context.Context, words []*SensitiveWord) error
|
||||
BatchUpdateSensitiveWords(ctx context.Context, updates map[string]map[string]any) error
|
||||
BatchDeleteSensitiveWords(ctx context.Context, ids []string) error
|
||||
|
||||
// 统计信息
|
||||
GetSensitiveWordStats(ctx context.Context) (map[string]int64, error)
|
||||
GetSensitiveWordLogStats(ctx context.Context, startTime, endTime time.Time) (map[string]int64, error)
|
||||
}
|
||||
69
pkg/common/db/table/chat/system_config.go
Normal file
69
pkg/common/db/table/chat/system_config.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// ConfigValueType 配置值类型
|
||||
const (
|
||||
ConfigValueTypeString = 1 // 字符串类型
|
||||
ConfigValueTypeNumber = 2 // 数字类型
|
||||
ConfigValueTypeBool = 3 // 布尔类型
|
||||
ConfigValueTypeJSON = 4 // JSON类型
|
||||
)
|
||||
|
||||
// ConfigKey 常用配置键
|
||||
const (
|
||||
// 钱包相关配置
|
||||
ConfigKeyWalletEnabled = "wallet.enabled" // 是否开启钱包功能
|
||||
|
||||
// 注册相关配置
|
||||
ConfigKeyPhoneRegisterVerifyCodeEnabled = "register.phone.verify_code.enabled" // 手机号注册验证码功能是否开启
|
||||
)
|
||||
|
||||
// SystemConfig 系统配置模型
|
||||
type SystemConfig struct {
|
||||
Key string `bson:"key"` // 配置键(唯一标识)
|
||||
Title string `bson:"title"` // 配置标题
|
||||
Value string `bson:"value"` // 配置值(字符串形式存储,根据ValueType解析)
|
||||
ValueType int32 `bson:"value_type"` // 配置值类型:1-字符串,2-数字,3-布尔,4-JSON
|
||||
Description string `bson:"description"` // 配置描述
|
||||
Enabled bool `bson:"enabled"` // 是否启用(用于开关类配置)
|
||||
ShowInApp bool `bson:"show_in_app"` // 是否在APP端展示
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (SystemConfig) TableName() string {
|
||||
return "system_configs"
|
||||
}
|
||||
|
||||
type SystemConfigInterface interface {
|
||||
Create(ctx context.Context, configs ...*SystemConfig) error
|
||||
Take(ctx context.Context, key string) (*SystemConfig, error)
|
||||
FindByKeys(ctx context.Context, keys []string) ([]*SystemConfig, error)
|
||||
FindAll(ctx context.Context, pagination pagination.Pagination) (int64, []*SystemConfig, error)
|
||||
Update(ctx context.Context, key string, data map[string]any) error
|
||||
UpdateValue(ctx context.Context, key string, value string) error
|
||||
UpdateEnabled(ctx context.Context, key string, enabled bool) error
|
||||
Delete(ctx context.Context, keys []string) error
|
||||
GetEnabledConfigs(ctx context.Context) ([]*SystemConfig, error)
|
||||
GetAppConfigs(ctx context.Context) ([]*SystemConfig, error) // 获取所有 show_in_app=true 的配置
|
||||
}
|
||||
43
pkg/common/db/table/chat/user_login_record.go
Normal file
43
pkg/common/db/table/chat/user_login_record.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
type UserLoginRecord struct {
|
||||
UserID string `bson:"user_id"`
|
||||
LoginTime time.Time `bson:"login_time"`
|
||||
IP string `bson:"ip"`
|
||||
DeviceID string `bson:"device_id"`
|
||||
Platform string `bson:"platform"`
|
||||
}
|
||||
|
||||
func (UserLoginRecord) TableName() string {
|
||||
return "user_login_records"
|
||||
}
|
||||
|
||||
type UserLoginRecordInterface interface {
|
||||
Create(ctx context.Context, records ...*UserLoginRecord) error
|
||||
CountTotal(ctx context.Context, before *time.Time) (int64, error)
|
||||
CountRangeEverydayTotal(ctx context.Context, start *time.Time, end *time.Time) (map[string]int64, int64, error)
|
||||
CountTodayActiveUsers(ctx context.Context) (int64, error) // 统计今天活跃用户数(今天登录的不同用户数)
|
||||
GetLatestLoginIP(ctx context.Context, userID string) (string, error) // 获取用户最新登录IP
|
||||
Search(ctx context.Context, userID, ip string, pagination pagination.Pagination) (int64, []*UserLoginRecord, error) // 查询登录记录(支持按用户ID或IP查询)
|
||||
}
|
||||
43
pkg/common/db/table/chat/verify_code.go
Normal file
43
pkg/common/db/table/chat/verify_code.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
type VerifyCode struct {
|
||||
ID string `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 (VerifyCode) TableName() string {
|
||||
return "verify_codes"
|
||||
}
|
||||
|
||||
type VerifyCodeInterface interface {
|
||||
Add(ctx context.Context, ms []*VerifyCode) error
|
||||
RangeNum(ctx context.Context, account string, start time.Time, end time.Time) (int64, error)
|
||||
TakeLast(ctx context.Context, account string) (*VerifyCode, error)
|
||||
Incr(ctx context.Context, id string) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
116
pkg/common/db/table/chat/wallet.go
Normal file
116
pkg/common/db/table/chat/wallet.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// BalanceRecordType 余额变动类型
|
||||
const (
|
||||
BalanceRecordTypeRecharge = 1 // 充值
|
||||
BalanceRecordTypeWithdraw = 2 // 提现/提款
|
||||
BalanceRecordTypeConsume = 3 // 消费
|
||||
BalanceRecordTypeRefund = 4 // 退款
|
||||
BalanceRecordTypeReward = 5 // 奖励
|
||||
BalanceRecordTypeAdminRecharge = 6 // 后台充值
|
||||
BalanceRecordTypeSendRedPacket = 7 // 发红包(减少余额)
|
||||
BalanceRecordTypeGrabRedPacket = 8 // 抢红包(增加余额)
|
||||
BalanceRecordTypeOther = 99 // 其他
|
||||
)
|
||||
|
||||
// WithdrawAccountType 提现账号类型
|
||||
const (
|
||||
WithdrawAccountTypeAlipay = 1 // 支付宝
|
||||
WithdrawAccountTypeWeChat = 2 // 微信
|
||||
WithdrawAccountTypeBankCard = 3 // 银行卡
|
||||
)
|
||||
|
||||
// RealNameAuth 实名认证信息
|
||||
type RealNameAuth struct {
|
||||
IDCard string `bson:"id_card"` // 身份证号
|
||||
IDCardPhotoFront string `bson:"id_card_photo_front"` // 身份证正面照片URL
|
||||
IDCardPhotoBack string `bson:"id_card_photo_back"` // 身份证反面照片URL
|
||||
Name string `bson:"name"` // 真实姓名
|
||||
AuditStatus int32 `bson:"audit_status"` // 审核状态:0-未审核,1-审核通过,2-审核拒绝
|
||||
}
|
||||
|
||||
// Wallet 钱包模型
|
||||
type Wallet struct {
|
||||
UserID string `bson:"user_id"` // 用户ID
|
||||
Balance int64 `bson:"balance"` // 用户余额(单位:分)
|
||||
PaymentPassword string `bson:"payment_password"` // 支付密码(加密存储)
|
||||
WithdrawAccount string `bson:"withdraw_account"` // 提现账号
|
||||
WithdrawAccountType int32 `bson:"withdraw_account_type"` // 提现账号类型:1-支付宝,2-微信,3-银行卡
|
||||
RealNameAuth RealNameAuth `bson:"real_name_auth"` // 实名认证信息
|
||||
WithdrawReceiveAccount string `bson:"withdraw_receive_account"` // 提现收款账号
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (Wallet) TableName() string {
|
||||
return "wallets"
|
||||
}
|
||||
|
||||
type WalletInterface interface {
|
||||
Create(ctx context.Context, wallets ...*Wallet) error
|
||||
Take(ctx context.Context, userID string) (*Wallet, error)
|
||||
Find(ctx context.Context, userIDs []string) ([]*Wallet, error)
|
||||
Update(ctx context.Context, userID string, data map[string]any) error
|
||||
UpdateBalance(ctx context.Context, userID string, balance int64) error
|
||||
IncrementBalance(ctx context.Context, userID string, amount int64) (beforeBalance int64, afterBalance int64, err error) // 原子更新余额,返回更新前后的余额
|
||||
UpdatePaymentPassword(ctx context.Context, userID string, paymentPassword string) error
|
||||
UpdateWithdrawAccount(ctx context.Context, userID string, withdrawAccount string) error // 更新提款账号(兼容旧接口)
|
||||
UpdateWithdrawAccountWithType(ctx context.Context, userID string, withdrawAccount string, accountType int32) error // 更新提款账号(带类型)
|
||||
UpdateRealNameAuth(ctx context.Context, userID string, realNameAuth RealNameAuth) error // 更新实名认证信息
|
||||
Delete(ctx context.Context, userIDs []string) error
|
||||
Page(ctx context.Context, pagination pagination.Pagination) (int64, []*Wallet, error)
|
||||
PageByRealNameAuthAuditStatus(ctx context.Context, auditStatus int32, userID string, pagination pagination.Pagination) (int64, []*Wallet, error) // 按实名认证审核状态分页查询(支持用户ID搜索)
|
||||
SearchByRealNameAuth(ctx context.Context, realNameKeyword string, idCardKeyword string) ([]string, error) // 按实名认证信息搜索钱包(返回userIDs)
|
||||
}
|
||||
|
||||
// WalletBalanceRecord 钱包余额记录
|
||||
type WalletBalanceRecord struct {
|
||||
ID string `bson:"_id"` // 记录ID
|
||||
UserID string `bson:"user_id"` // 用户ID
|
||||
Amount int64 `bson:"amount"` // 变动金额(单位:分,正数表示增加,负数表示减少)
|
||||
Type int32 `bson:"type"` // 变动类型:1-充值,2-提现/提款,3-消费,4-退款,5-奖励,6-后台充值,7-发红包,8-抢红包,99-其他
|
||||
BeforeBalance int64 `bson:"before_balance"` // 变动前余额(单位:分)
|
||||
AfterBalance int64 `bson:"after_balance"` // 变动后余额(单位:分)
|
||||
OrderID string `bson:"order_id"` // 关联订单ID(可选)
|
||||
TransactionID string `bson:"transaction_id"` // 交易ID(可选)
|
||||
RedPacketID string `bson:"red_packet_id"` // 红包ID(用于发红包和抢红包记录关联,可选)
|
||||
Remark string `bson:"remark"` // 备注
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
}
|
||||
|
||||
func (WalletBalanceRecord) TableName() string {
|
||||
return "wallet_balance_records"
|
||||
}
|
||||
|
||||
type WalletBalanceRecordInterface interface {
|
||||
Create(ctx context.Context, records ...*WalletBalanceRecord) error
|
||||
Take(ctx context.Context, recordID string) (*WalletBalanceRecord, error)
|
||||
FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*WalletBalanceRecord, error)
|
||||
FindByUserIDAndType(ctx context.Context, userID string, recordType int32, pagination pagination.Pagination) (int64, []*WalletBalanceRecord, error)
|
||||
FindByOrderID(ctx context.Context, orderID string) (*WalletBalanceRecord, error)
|
||||
FindByTransactionID(ctx context.Context, transactionID string) (*WalletBalanceRecord, error)
|
||||
FindByRedPacketID(ctx context.Context, redPacketID string) ([]*WalletBalanceRecord, error)
|
||||
GetUserBalanceHistory(ctx context.Context, userID string, startTime, endTime *time.Time, pagination pagination.Pagination) (int64, []*WalletBalanceRecord, error)
|
||||
CountByUserID(ctx context.Context, userID string) (int64, error)
|
||||
}
|
||||
63
pkg/common/db/table/chat/withdraw.go
Normal file
63
pkg/common/db/table/chat/withdraw.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// WithdrawStatus 提现状态
|
||||
const (
|
||||
WithdrawStatusPending = 1 // 待审核
|
||||
WithdrawStatusApproved = 2 // 已通过
|
||||
WithdrawStatusRejected = 3 // 已拒绝
|
||||
)
|
||||
|
||||
// Withdraw 提现记录
|
||||
type Withdraw struct {
|
||||
ID string `bson:"_id"` // 提现ID
|
||||
UserID string `bson:"user_id"` // 用户ID
|
||||
Amount int64 `bson:"amount"` // 提现金额(单位:分)
|
||||
WithdrawAccount string `bson:"withdraw_account"` // 提现账号
|
||||
Status int32 `bson:"status"` // 审核状态:1-待审核,2-已通过,3-已拒绝
|
||||
AuditorID string `bson:"auditor_id"` // 审核人ID(管理员ID)
|
||||
AuditTime time.Time `bson:"audit_time"` // 审核时间
|
||||
AuditRemark string `bson:"audit_remark"` // 审核备注
|
||||
IP string `bson:"ip"` // 提现IP
|
||||
DeviceID string `bson:"device_id"` // 设备ID
|
||||
Platform string `bson:"platform"` // 平台(iOS、Android、Web等)
|
||||
DeviceModel string `bson:"device_model"` // 设备型号(如:iPhone 14 Pro、Samsung Galaxy S23等)
|
||||
DeviceBrand string `bson:"device_brand"` // 设备品牌(如:Apple、Samsung、Huawei等)
|
||||
OSVersion string `bson:"os_version"` // 操作系统版本(如:iOS 17.0、Android 13等)
|
||||
AppVersion string `bson:"app_version"` // 应用版本
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (Withdraw) TableName() string {
|
||||
return "withdraws"
|
||||
}
|
||||
|
||||
type WithdrawInterface interface {
|
||||
Create(ctx context.Context, withdraws ...*Withdraw) error
|
||||
Take(ctx context.Context, withdrawID string) (*Withdraw, error)
|
||||
FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*Withdraw, error)
|
||||
FindByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*Withdraw, error)
|
||||
UpdateStatus(ctx context.Context, withdrawID string, status int32, auditorID string, auditRemark string) error
|
||||
Page(ctx context.Context, pagination pagination.Pagination) (int64, []*Withdraw, error)
|
||||
}
|
||||
68
pkg/common/db/table/chat/withdraw_application.go
Normal file
68
pkg/common/db/table/chat/withdraw_application.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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/pagination"
|
||||
)
|
||||
|
||||
// WithdrawApplicationStatus 提现申请状态
|
||||
const (
|
||||
WithdrawApplicationStatusPending = 1 // 待审核
|
||||
WithdrawApplicationStatusApproved = 2 // 已通过
|
||||
WithdrawApplicationStatusRejected = 3 // 已拒绝
|
||||
WithdrawApplicationStatusProcessing = 4 // 处理中
|
||||
WithdrawApplicationStatusCompleted = 5 // 已完成
|
||||
)
|
||||
|
||||
// WithdrawApplication 提现申请
|
||||
type WithdrawApplication struct {
|
||||
ID string `bson:"_id"` // 申请ID
|
||||
UserID string `bson:"user_id"` // 用户ID
|
||||
Amount int64 `bson:"amount"` // 提现金额(单位:分)
|
||||
WithdrawAccount string `bson:"withdraw_account"` // 提现账号
|
||||
WithdrawAccountType int32 `bson:"withdraw_account_type"` // 提现账号类型:1-支付宝,2-微信,3-银行卡
|
||||
Status int32 `bson:"status"` // 申请状态:1-待审核,2-已通过,3-已拒绝,4-处理中,5-已完成
|
||||
AuditorID string `bson:"auditor_id"` // 审核人ID(管理员ID)
|
||||
AuditTime time.Time `bson:"audit_time"` // 审核时间
|
||||
AuditRemark string `bson:"audit_remark"` // 审核备注
|
||||
IP string `bson:"ip"` // 申请IP
|
||||
DeviceID string `bson:"device_id"` // 设备ID
|
||||
Platform string `bson:"platform"` // 平台(iOS、Android、Web等)
|
||||
DeviceModel string `bson:"device_model"` // 设备型号(如:iPhone 14 Pro、Samsung Galaxy S23等)
|
||||
DeviceBrand string `bson:"device_brand"` // 设备品牌(如:Apple、Samsung、Huawei等)
|
||||
OSVersion string `bson:"os_version"` // 操作系统版本(如:iOS 17.0、Android 13等)
|
||||
AppVersion string `bson:"app_version"` // 应用版本
|
||||
Remark string `bson:"remark"` // 申请备注
|
||||
CreateTime time.Time `bson:"create_time"` // 创建时间
|
||||
UpdateTime time.Time `bson:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
func (WithdrawApplication) TableName() string {
|
||||
return "withdraw_applications"
|
||||
}
|
||||
|
||||
type WithdrawApplicationInterface interface {
|
||||
Create(ctx context.Context, applications ...*WithdrawApplication) error
|
||||
Take(ctx context.Context, applicationID string) (*WithdrawApplication, error)
|
||||
FindByUserID(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*WithdrawApplication, error)
|
||||
FindByStatus(ctx context.Context, status int32, pagination pagination.Pagination) (int64, []*WithdrawApplication, error)
|
||||
UpdateStatus(ctx context.Context, applicationID string, status int32, auditorID string, auditRemark string) error
|
||||
Page(ctx context.Context, pagination pagination.Pagination) (int64, []*WithdrawApplication, error)
|
||||
Update(ctx context.Context, applicationID string, data map[string]any) error
|
||||
}
|
||||
Reference in New Issue
Block a user