go-bot/tools/redisClient.go

129 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tools
import (
"context"
"fmt"
"go-bot/config"
"log"
"sync"
"time"
"github.com/go-redis/redis/v8"
)
var (
rdb *redis.Client
once sync.Once
ctx = context.Background()
)
// InitRedis 初始化 Redis 客户端(懒加载模式,确保只初始化一次)
func InitRedis() *redis.Client {
// 使用 sync.Once 确保客户端只初始化一次
once.Do(func() {
redisConfig := config.GetConfig()["REDIS"].(map[string]interface{})
rdb = redis.NewClient(&redis.Options{
Addr: redisConfig["REDIS_URL"].(string), // Redis 地址
Password: redisConfig["REDIS_PASSWORD"].(string), // Redis 密码,如果有设置
DB: int(redisConfig["REDIS_DB"].(int64)), // 使用的 Redis 数据库
PoolSize: 20, // 连接池大小
MinIdleConns: 10, // 最小空闲连接数
})
// 测试连接是否成功
_, err := rdb.Ping(ctx).Result()
if err != nil {
log.Println("Redis 连接失败:", err)
} else {
log.Println("Redis 连接成功")
}
})
return rdb
}
// GetRedisClient 获取 Redis 客户端实例
func GetRedisClient() *redis.Client {
if rdb == nil {
return InitRedis()
}
return rdb
}
// 添加对话到上下文超过5条则删除所有上下文
func AddToContext(key string, message []byte, contextlenth int64) {
// key := fmt.Sprintf("context:%s:%s:%s", worker, groupID, qqID)
// 检查上下文持续时间,如果大于一小时就删除所有列表
lastRequestKey := fmt.Sprintf("last_request:%s", key)
now := time.Now().Unix()
exists, err := CheckKeyExists(lastRequestKey)
if err != nil || !exists {
log.Println("检查键是否存在时出错:", err)
rdb.Del(ctx, key)
rdb.Set(ctx, lastRequestKey, fmt.Sprintf("%d", now), 60*time.Minute)
}
// 如果上下文超过5条删除所有上下文
listLength := GetListLength(key)
// log.Println("listLength:", listLength)
if contextlenth > 0 && listLength >= contextlenth*2 {
rdb.Del(ctx, key) // 删除该用户的所有上下文
}
rdb.RPush(ctx, key, message) // 添加新消息到列表
}
// 检查请求频率10秒内只能请求一次
func CheckRequestFrequency(GID string, UID string, interval int64) bool {
key := fmt.Sprintf("time_interval:%s:%s", GID, UID)
// lastRequest, err := rdb.Get(ctx, key).Int64()
exists, err := CheckKeyExists(key)
if err != nil || !exists {
// log.Println("检查键是否存在时出错:", err)
rdb.Set(ctx, key, fmt.Sprintf("%d", time.Now().Unix()), time.Duration(interval)*time.Second)
return true
}
return false // 频率超限,拒绝请求
}
// getListLength 获取列表长度
func GetListLength(key string) int64 {
return rdb.LLen(ctx, key).Val()
}
func GetListValue(key string, index int64) (string, error) {
return rdb.LIndex(ctx, key, index).Result()
}
// 删除列表最后一个元素
func RemoveLastValueFromList(key string) (string, error) {
// RPOP 命令会移除并返回列表的最后一个元素
value, err := rdb.RPop(ctx, key).Result()
if err != nil {
if err == redis.Nil {
return "", fmt.Errorf("列表为空或不存在")
}
return "", fmt.Errorf("删除最后一个值时出错: %v", err)
}
return value, nil
}
// SetValue 设置键值对
func SetValue(key string, value string) error {
return rdb.Set(ctx, key, value, 0).Err()
}
// GetValue 获取键对应的值
func GetValue(key string) (string, error) {
return rdb.Get(ctx, key).Result()
}
// CheckKeyExists 检查键是否存在
func CheckKeyExists(key string) (bool, error) {
val, err := rdb.Exists(ctx, key).Result()
if err != nil {
return false, err
}
return val > 0, nil
}