mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-06 17:23:42 +08:00
fix: fixed conflicts
This commit is contained in:
111
api/utils/common.go
Normal file
111
api/utils/common.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
|
||||
)
|
||||
|
||||
// CopyObject 拷贝对象
|
||||
func CopyObject(src interface{}, dst interface{}) error {
|
||||
|
||||
srcType := reflect.TypeOf(src)
|
||||
srcValue := reflect.ValueOf(src)
|
||||
dstValue := reflect.ValueOf(dst).Elem()
|
||||
reflect.TypeOf(dst)
|
||||
for i := 0; i < srcType.NumField(); i++ {
|
||||
field := srcType.Field(i)
|
||||
value := dstValue.FieldByName(field.Name)
|
||||
if !value.IsValid() {
|
||||
continue
|
||||
}
|
||||
// 数据类型相同,直接赋值
|
||||
v := srcValue.FieldByName(field.Name)
|
||||
if value.Type() == field.Type {
|
||||
value.Set(v)
|
||||
} else {
|
||||
// src data type is string,dst data type is slice, map, struct
|
||||
// use json decode the data
|
||||
if field.Type.Kind() == reflect.String && (value.Type().Kind() == reflect.Struct ||
|
||||
value.Type().Kind() == reflect.Map ||
|
||||
value.Type().Kind() == reflect.Slice) {
|
||||
pType := reflect.New(value.Type())
|
||||
v2 := pType.Interface()
|
||||
err := json.Unmarshal([]byte(v.String()), &v2)
|
||||
if err == nil {
|
||||
value.Set(reflect.ValueOf(v2).Elem())
|
||||
}
|
||||
// map, struct, slice to string
|
||||
} else if (field.Type.Kind() == reflect.Struct ||
|
||||
field.Type.Kind() == reflect.Map ||
|
||||
field.Type.Kind() == reflect.Slice) && value.Type().Kind() == reflect.String {
|
||||
ba, err := json.Marshal(v.Interface())
|
||||
if err == nil {
|
||||
val := string(ba)
|
||||
if strings.Contains(val, "{") {
|
||||
value.Set(reflect.ValueOf(string(ba)))
|
||||
} else {
|
||||
value.Set(reflect.ValueOf(""))
|
||||
}
|
||||
}
|
||||
} else { // 简单数据类型的强制类型转换
|
||||
switch value.Kind() {
|
||||
case reflect.Int:
|
||||
case reflect.Int8:
|
||||
case reflect.Int16:
|
||||
case reflect.Int32:
|
||||
case reflect.Int64:
|
||||
value.SetInt(v.Int())
|
||||
break
|
||||
case reflect.Float32:
|
||||
case reflect.Float64:
|
||||
value.SetFloat(v.Float())
|
||||
break
|
||||
case reflect.Bool:
|
||||
value.SetBool(v.Bool())
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Ip2Region(searcher *xdb.Searcher, ip string) string {
|
||||
str, err := searcher.SearchByStr(ip)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
arr := strings.Split(str, "|")
|
||||
if len(arr) < 3 {
|
||||
return arr[0]
|
||||
}
|
||||
return fmt.Sprintf("%s-%s-%s", arr[0], arr[2], arr[3])
|
||||
}
|
||||
|
||||
func IsEmptyValue(obj interface{}) bool {
|
||||
v := reflect.ValueOf(obj)
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return v.IsNil()
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return v.Complex() == 0
|
||||
default:
|
||||
return reflect.DeepEqual(obj, reflect.Zero(reflect.TypeOf(obj)).Interface())
|
||||
}
|
||||
}
|
||||
70
api/utils/crypto.go
Normal file
70
api/utils/crypto.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// AesEncrypt 加密
|
||||
func AesEncrypt(keyStr string, data []byte) (string, error) {
|
||||
//创建加密实例
|
||||
key := []byte(keyStr)
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
blockSize := block.BlockSize()
|
||||
encryptBytes := pkcs7Padding(data, blockSize)
|
||||
result := make([]byte, len(encryptBytes))
|
||||
//使用cbc加密模式
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
//执行加密
|
||||
blockMode.CryptBlocks(result, encryptBytes)
|
||||
return base64.StdEncoding.EncodeToString(result), nil
|
||||
}
|
||||
|
||||
// AesDecrypt 解密
|
||||
func AesDecrypt(keyStr string, dataStr string) ([]byte, error) {
|
||||
//创建实例
|
||||
key := []byte(keyStr)
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := base64.StdEncoding.DecodeString(dataStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
result := make([]byte, len(data))
|
||||
//执行解密
|
||||
blockMode.CryptBlocks(result, data)
|
||||
//去除填充
|
||||
result, err = pkcs7UnPadding(result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func pkcs7Padding(data []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(data)%blockSize
|
||||
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(data, padText...)
|
||||
}
|
||||
|
||||
func pkcs7UnPadding(data []byte) ([]byte, error) {
|
||||
length := len(data)
|
||||
if length == 0 {
|
||||
return nil, errors.New("empty encrypt data")
|
||||
}
|
||||
unPadding := int(data[length-1])
|
||||
return data[:(length - unPadding)], nil
|
||||
}
|
||||
20
api/utils/openai.go
Normal file
20
api/utils/openai.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkoukk/tiktoken-go"
|
||||
)
|
||||
|
||||
func CalcTokens(text string, model string) (int, error) {
|
||||
encoding, ok := tiktoken.MODEL_TO_ENCODING[model]
|
||||
if !ok {
|
||||
encoding = "cl100k_base"
|
||||
}
|
||||
tke, err := tiktoken.GetEncoding(encoding)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("getEncoding: %v", err)
|
||||
}
|
||||
|
||||
token := tke.Encode(text, nil, nil)
|
||||
return len(token), nil
|
||||
}
|
||||
32
api/utils/resp/response.go
Normal file
32
api/utils/resp/response.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package resp
|
||||
|
||||
import (
|
||||
"chatplus/core/types"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func SUCCESS(c *gin.Context, values ...interface{}) {
|
||||
if values != nil {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Data: values[0]})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Success})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ERROR(c *gin.Context, messages ...string) {
|
||||
if messages != nil {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: messages[0]})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed})
|
||||
}
|
||||
}
|
||||
|
||||
func HACKER(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Hacker attempt!!!"})
|
||||
}
|
||||
|
||||
func NotAuth(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, types.BizVo{Code: types.NotAuthorized, Message: "Not Authorized"})
|
||||
}
|
||||
83
api/utils/strings.go
Normal file
83
api/utils/strings.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// RandString generate rand string with specified length
|
||||
func RandString(length int) string {
|
||||
str := "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
data := []byte(str)
|
||||
var result []byte
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < length; i++ {
|
||||
result = append(result, data[r.Intn(len(data))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
func RandomNumber(bit int) int {
|
||||
min := intPow(10, bit-1)
|
||||
max := intPow(10, bit) - 1
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return rand.Intn(max-min+1) + min
|
||||
}
|
||||
|
||||
func intPow(x, y int) int {
|
||||
result := 1
|
||||
for i := 0; i < y; i++ {
|
||||
result *= x
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func ContainsStr(slice []string, item string) bool {
|
||||
for _, e := range slice {
|
||||
if e == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Stamp2str 时间戳转字符串
|
||||
func Stamp2str(timestamp int64) string {
|
||||
if timestamp == 0 {
|
||||
return ""
|
||||
}
|
||||
return time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// Str2stamp 字符串转时间戳
|
||||
func Str2stamp(str string) int64 {
|
||||
layout := "2006-01-02 15:04:05"
|
||||
t, err := time.Parse(layout, str)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
func GenPassword(pass string, salt string) string {
|
||||
data := []byte(pass + salt)
|
||||
hash := sha3.Sum256(data)
|
||||
return fmt.Sprintf("%x", hash)
|
||||
}
|
||||
|
||||
func JsonEncode(value interface{}) string {
|
||||
bytes, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func JsonDecode(src string, dest interface{}) error {
|
||||
return json.Unmarshal([]byte(src), dest)
|
||||
}
|
||||
45
api/utils/user.go
Normal file
45
api/utils/user.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"chatplus/core/types"
|
||||
"chatplus/store/model"
|
||||
"errors"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func SetLoginUser(c *gin.Context, user model.User) error {
|
||||
session := sessions.Default(c)
|
||||
session.Set(types.SessionUser, user.Id)
|
||||
// TODO: 后期用户数量增加,考虑将用户数据存储到 leveldb,避免每次查询数据库
|
||||
return session.Save()
|
||||
}
|
||||
|
||||
func SetLoginAdmin(c *gin.Context, admin types.Manager) error {
|
||||
session := sessions.Default(c)
|
||||
session.Set(types.SessionAdmin, admin.Username)
|
||||
return session.Save()
|
||||
}
|
||||
|
||||
func GetLoginUser(c *gin.Context, db *gorm.DB) (model.User, error) {
|
||||
value, exists := c.Get(types.LoginUserCache)
|
||||
if exists {
|
||||
return value.(model.User), nil
|
||||
}
|
||||
|
||||
session := sessions.Default(c)
|
||||
userId := session.Get(types.SessionUser)
|
||||
if userId == nil {
|
||||
return model.User{}, errors.New("user not login")
|
||||
}
|
||||
|
||||
var user model.User
|
||||
res := db.First(&user, userId)
|
||||
// 更新缓存
|
||||
if res.Error == nil {
|
||||
c.Set(types.LoginUserCache, user)
|
||||
}
|
||||
return user, res.Error
|
||||
}
|
||||
Reference in New Issue
Block a user