🎨 添加图库和客服插件(有问题-待修改)

This commit is contained in:
2025-05-14 16:51:31 +08:00
parent 5faff4afa0
commit a5ae680f94
41 changed files with 2592 additions and 12 deletions

View File

@@ -0,0 +1,54 @@
package tools
import (
"errors"
"github.com/golang-jwt/jwt/v4"
"time"
)
var jwtKey = []byte("your-256-bit-secret")
// CustomClaims 结构体可以根据需要添加自定义的声明
type CustomClaims struct {
ServiceId int64 `json:"service_id"`
jwt.RegisteredClaims
}
func GenerateToken(serviceId int64) (int64, string, error) {
// 设置JWT的声明
claims := CustomClaims{
ServiceId: serviceId,
RegisteredClaims: jwt.RegisteredClaims{
Audience: jwt.ClaimStrings{"GVA"}, // 受众
NotBefore: jwt.NewNumericDate(time.Now().Add(-1000)), // 签名生效时间
Issuer: "gva",
ExpiresAt: jwt.NewNumericDate(time.Now().Add(72 * time.Hour)), // token 72小时后过期
},
}
// 生成JWT token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenStr, err := token.SignedString(jwtKey)
return time.Now().Add(72 * time.Hour).Unix(), tokenStr, err
}
func ValidateToken(tokenString string) (*CustomClaims, error) {
claims := &CustomClaims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
// 验证签名方法
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("unexpected signing method")
}
return jwtKey, nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, errors.New("invalid token")
}
return claims, nil
}

View File

@@ -0,0 +1,77 @@
package tools
import (
"log"
"sync"
"time"
)
type LimitQueeMap struct {
sync.RWMutex
LimitQueue map[string][]int64
}
func (l *LimitQueeMap) readMap(key string) ([]int64, bool) {
l.RLock()
value, ok := l.LimitQueue[key]
l.RUnlock()
return value, ok
}
func (l *LimitQueeMap) writeMap(key string, value []int64) {
l.Lock()
l.LimitQueue[key] = value
l.Unlock()
}
var LimitQueue = &LimitQueeMap{
LimitQueue: make(map[string][]int64),
}
var ok bool
func NewLimitQueue() {
cleanLimitQueue()
}
func cleanLimitQueue() {
go func() {
for {
log.Println("cleanLimitQueue start...")
LimitQueue.LimitQueue = nil
now := time.Now()
// 计算下一个零点
next := now.Add(time.Hour * 24)
next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location())
t := time.NewTimer(next.Sub(now))
<-t.C
}
}()
}
//单机时间滑动窗口限流法
func LimitFreqSingle(queueName string, count uint, timeWindow int64) bool {
currTime := time.Now().Unix()
if LimitQueue.LimitQueue == nil {
LimitQueue.LimitQueue = make(map[string][]int64)
}
if _, ok = LimitQueue.readMap(queueName); !ok {
LimitQueue.writeMap(queueName, make([]int64, 0))
return true
}
q, _ := LimitQueue.readMap(queueName)
//队列未满
if uint(len(q)) < count {
LimitQueue.writeMap(queueName, append(q, currTime))
return true
}
//队列满了,取出最早访问的时间
earlyTime := q[0]
//说明最早期的时间还在时间窗口内,还没过期,所以不允许通过
if currTime-earlyTime <= timeWindow {
return false
} else {
//说明最早期的访问应该过期了,去掉最早期的
q = q[1:]
LimitQueue.writeMap(queueName, append(q, currTime))
}
return true
}

View File

@@ -0,0 +1,20 @@
package tools
import "time"
func FormatTimestamp(timestamp int64) string {
t := time.Unix(timestamp, 0)
now := time.Now()
// 格式化时间
if t.Year() == now.Year() && t.YearDay() == now.YearDay() {
// 当天,返回 24 小时制的时和分
return t.Format("15:04")
} else if t.Year() == now.Year() && t.YearDay() == now.YearDay()-1 {
// 昨天,返回 "昨天"
return "昨天"
} else {
// 其他时间,返回月和日
return t.Format("01-02")
}
}