Files
trbot/database/redis_db/redis.go
Hubert Chen f4e904ef4d refactor yaml database logger
plugin_sticker:
    add sticker collect to channel feature
    allow detected `addsticker` link and show download sticker set button
database:
    remove `IsInitialized` and `InitializedErr` in `DatabaseBackend` struct
    add `context.Context` params in `DatabaseBackend.Initializer`
yaml_db:
    using `yaml.LoadYAML()` and `yaml.SaveYAML()` to save database file
    using `zerolog` logger replace `log`
    fix database file protection logic
    remove `addToYamlDB()` func
    update `Database.UpdateTimestamp` when change some flag
handlers:
    fix `CustomSymbolCommand` trigger: use `strings.HasPrefix()` to replace `utils.CommandMaybeWithSuffixUsername()`, custom symbol command will not include robot username suffix
consts:
    rename `YAMLDataBasePath` to `YAMLDataBaseDir`
mess:
    remove `PrintLogAndSave()` func
2025-07-04 00:54:31 +08:00

185 lines
4.8 KiB
Go

package redis_db
import (
"context"
"fmt"
"reflect"
"strconv"
"time"
"trbot/database/db_struct"
"trbot/utils"
"trbot/utils/configs"
"github.com/go-telegram/bot/models"
"github.com/redis/go-redis/v9"
)
var UserDB *redis.Client // 用户数据
func InitializeDB(ctx context.Context) error {
if configs.BotConfig.RedisURL != "" {
if configs.BotConfig.RedisDatabaseID != -1 {
UserDB = redis.NewClient(&redis.Options{
Addr: configs.BotConfig.RedisURL,
Password: configs.BotConfig.RedisPassword,
DB: configs.BotConfig.RedisDatabaseID,
})
err := UserDB.Ping(ctx).Err()
if err != nil {
return fmt.Errorf("failed to ping Redis [%d] database: %w", configs.BotConfig.RedisDatabaseID, err)
}
}
return nil
} else {
return fmt.Errorf("RedisURL is empty")
}
}
// 保存用户信息
func SaveChatInfo(ctx context.Context, chatInfo *db_struct.ChatInfo) error {
if chatInfo == nil {
return fmt.Errorf("failed to save chat info: chatInfo is nil")
}
key := strconv.FormatInt(chatInfo.ID, 10)
v := reflect.ValueOf(*chatInfo)
t := reflect.TypeOf(*chatInfo)
data := make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
data[field.Name] = fmt.Sprintf("%v", value.Interface())
}
return UserDB.HSet(ctx, key, data).Err()
}
// 获取用户信息
func GetChatInfo(ctx context.Context, chatID int64) (*db_struct.ChatInfo, error) {
key := strconv.FormatInt(chatID, 10)
data, err := UserDB.HGetAll(ctx, key).Result()
if err != nil {
return nil, fmt.Errorf("failed to get chat info: %w", err)
}
if len(data) == 0 {
return nil, nil
}
user := &db_struct.ChatInfo{}
v := reflect.ValueOf(user).Elem()
for i := 0; i < v.NumField(); i++ {
field := v.Type().Field(i)
valueStr, exists := data[field.Name]
if !exists {
continue
}
fieldValue := v.Field(i)
if fieldValue.CanSet() {
switch fieldValue.Kind() {
case reflect.String:
fieldValue.SetString(valueStr)
case reflect.Int, reflect.Int64:
intValue, _ := strconv.Atoi(valueStr)
fieldValue.SetInt(int64(intValue))
}
}
}
return user, nil
}
func InitUser(ctx context.Context, user *models.User) error {
chatData, err := GetChatInfo(ctx, user.ID)
if err != nil {
return fmt.Errorf("failed to get chat info: %w", err)
}
if chatData == nil {
var newUser = db_struct.ChatInfo{
ID: user.ID,
ChatName: utils.ShowUserName(user),
ChatType: models.ChatTypePrivate,
AddTime: time.Now().Format(time.RFC3339),
}
err = SaveChatInfo(ctx, &newUser)
if err != nil {
return fmt.Errorf("failed to init new user: %w", err)
}
}
return nil
}
func InitChat(ctx context.Context, chat *models.Chat) error {
chatData, err := GetChatInfo(ctx, chat.ID)
if err != nil {
return fmt.Errorf("failed to get chat info: %w", err)
}
if chatData == nil {
var newChat = db_struct.ChatInfo{
ID: chat.ID,
ChatName: utils.ShowChatName(chat),
ChatType: chat.Type,
AddTime: time.Now().Format(time.RFC3339),
}
err = SaveChatInfo(ctx, &newChat)
if err != nil {
return fmt.Errorf("failed to init new chat: %w", err)
}
}
return nil
}
func IncrementalUsageCount(ctx context.Context, chatID int64, fieldName db_struct.ChatInfoField_UsageCount) error {
count, err := UserDB.HGet(ctx, strconv.FormatInt(chatID, 10), string(fieldName)).Int()
if err != nil {
if err == redis.Nil {
err = UserDB.HSet(ctx, strconv.FormatInt(chatID, 10), string(fieldName), 0).Err()
if err != nil {
return fmt.Errorf("failed to create empty [%s] key: %w", string(fieldName), err)
}
} else {
return fmt.Errorf("failed to get [%s] usage count: %w", string(fieldName), err)
}
}
err = UserDB.HSet(ctx, strconv.FormatInt(chatID, 10), string(fieldName), count + 1).Err()
if err != nil {
return fmt.Errorf("failed to incrementing [%s] usage count: %w", string(fieldName), err)
}
return nil
}
func RecordLatestData(ctx context.Context, chatID int64, fieldName db_struct.ChatInfoField_LatestData, value string) error {
err := UserDB.HSet(ctx, strconv.FormatInt(chatID, 10), string(fieldName), value).Err()
if err != nil {
return fmt.Errorf("failed to record latest [%s] data: %w", string(fieldName), err)
}
return nil
}
func UpdateOperationStatus(ctx context.Context, chatID int64, fieldName db_struct.ChatInfoField_Status, value bool) error {
err := UserDB.HSet(ctx, strconv.FormatInt(chatID, 10), string(fieldName), value).Err()
if err != nil {
return fmt.Errorf("failed to update operation [%s] status: %w", string(fieldName), err)
}
return nil
}
func SetCustomFlag(ctx context.Context, chatID int64, fieldName db_struct.ChatInfoField_CustomFlag, value string) error {
err := UserDB.HSet(ctx, strconv.FormatInt(chatID, 10), string(fieldName), value).Err()
if err != nil {
return fmt.Errorf("failed to set custom [%s] flag: %w", string(fieldName), err)
}
return nil
}