:toda:
This commit is contained in:
42
utils/avatar.go
Normal file
42
utils/avatar.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"math/rand"
|
||||
"time"
|
||||
"wireguard-ui/global/client"
|
||||
)
|
||||
|
||||
type avatar struct{}
|
||||
|
||||
func Avatar() avatar {
|
||||
return avatar{}
|
||||
}
|
||||
|
||||
// GenerateAvatar
|
||||
// @description: 生成随机头像 - 默认头像
|
||||
// @receiver avatar
|
||||
// @return path
|
||||
// @return err
|
||||
func (avatar) GenerateAvatar(isUpload bool) (path string, err error) {
|
||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
r := client.HttpClient.R()
|
||||
result, err := r.Get(fmt.Sprintf("https://api.dicebear.com/7.x/croodles/png?seed=%d&scale=120&size=200&clip=true&randomizeIds=true&beard=variant01,variant02,variant03&"+
|
||||
"eyes=variant01,variant02,variant03,variant04,variant05,variant06,variant07,variant08,variant09,variant10,variant11,variant12&mustache=variant01,variant02,variant03&"+
|
||||
"topColor=000000,0fa958,699bf7", rand.Uint32()))
|
||||
if err != nil {
|
||||
log.Errorf("请求头像API失败: %v", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
if isUpload {
|
||||
path, err = FileSystem().UploadFile(result.Body(), ".png")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
return string(result.Body()), nil
|
||||
}
|
47
utils/file_system.go
Normal file
47
utils/file_system.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"os"
|
||||
"time"
|
||||
"wireguard-ui/config"
|
||||
"wireguard-ui/global/client"
|
||||
)
|
||||
|
||||
type fileSystem struct{}
|
||||
|
||||
func FileSystem() fileSystem {
|
||||
return fileSystem{}
|
||||
}
|
||||
|
||||
// UploadFile
|
||||
// @description: 上传文件
|
||||
// @receiver fileSystem
|
||||
// @param file
|
||||
// @return filePath
|
||||
// @return err
|
||||
func (fileSystem) UploadFile(file []byte, suffix string) (filePath string, err error) {
|
||||
switch config.Config.File.Type {
|
||||
case "oss":
|
||||
ossObj, err := client.OSS.Put(config.Config.File.Path, file, suffix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ossObj.LongPath, nil
|
||||
case "local":
|
||||
filePath = fmt.Sprintf("%v/%d-avatar%s", config.Config.File.Path, time.Now().Unix(), suffix)
|
||||
// 创建目录
|
||||
if err = os.MkdirAll(filePath, os.FileMode(0777)); err != nil {
|
||||
log.Errorf("本地存储目录创建失败: %v", err)
|
||||
return "", err
|
||||
}
|
||||
if err = os.WriteFile(filePath, file, os.FileMode(0777)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filePath, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
82
utils/mail.go
Normal file
82
utils/mail.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/jordan-wright/email"
|
||||
"mime"
|
||||
"net/smtp"
|
||||
"net/textproto"
|
||||
"path/filepath"
|
||||
"wireguard-ui/config"
|
||||
)
|
||||
|
||||
type mail struct {
|
||||
*email.Email
|
||||
addr string
|
||||
auth smtp.Auth
|
||||
}
|
||||
|
||||
func Mail() *mail {
|
||||
var m mail
|
||||
em := email.NewEmail()
|
||||
m.Email = em
|
||||
m.auth = smtp.PlainAuth("", config.Config.Mail.User, config.Config.Mail.Password, config.Config.Mail.Host)
|
||||
m.addr = fmt.Sprintf("%s:%d", config.Config.Mail.Host, config.Config.Mail.Port)
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m *mail) VerifyConfig() (err error) {
|
||||
if m == nil {
|
||||
return errors.New("邮件客户端初始化失败")
|
||||
}
|
||||
|
||||
if m.auth == nil || m.addr == "" {
|
||||
return errors.New("邮件客户端未完成初始化")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendMail
|
||||
// @description: 发送附件
|
||||
// @receiver m
|
||||
// @param to
|
||||
// @param subject
|
||||
// @param attacheFilePath
|
||||
// @return err
|
||||
func (m *mail) SendMail(to, subject, content, attacheFilePath string) (err error) {
|
||||
m.From = fmt.Sprintf("wg-dashboard <%s>", config.Config.Mail.User)
|
||||
m.To = []string{to}
|
||||
m.Subject = subject
|
||||
m.Text = []byte(content)
|
||||
if attacheFilePath != "" {
|
||||
atch, err := m.AttachFile(attacheFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取附件文件失败: %v", err.Error())
|
||||
}
|
||||
emHeader := textproto.MIMEHeader{}
|
||||
emHeader.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, mime.BEncoding.Encode("UTF-8", m.getFileName(attacheFilePath))))
|
||||
atch.Header = emHeader
|
||||
}
|
||||
|
||||
if config.Config.Mail.SkipTls {
|
||||
return m.Send(m.addr, m.auth)
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{}
|
||||
tlsConfig.InsecureSkipVerify = config.Config.Mail.SkipTls
|
||||
tlsConfig.ServerName = config.Config.Mail.Host
|
||||
|
||||
return m.SendWithTLS(m.addr, m.auth, tlsConfig)
|
||||
}
|
||||
|
||||
// getFileName
|
||||
// @description: 获取文件名
|
||||
// @receiver m
|
||||
// @param filePath
|
||||
// @return string
|
||||
func (m *mail) getFileName(filePath string) string {
|
||||
return filepath.Base(filePath)
|
||||
}
|
128
utils/network.go
Normal file
128
utils/network.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"github.com/spf13/cast"
|
||||
"net"
|
||||
"strings"
|
||||
"wireguard-ui/global/client"
|
||||
)
|
||||
|
||||
type network struct{}
|
||||
|
||||
func Network() network {
|
||||
return network{}
|
||||
}
|
||||
|
||||
// GetHostPublicIP
|
||||
// @description: 获取本机公网地址
|
||||
// @receiver network
|
||||
// @return string
|
||||
func (network) GetHostPublicIP() string {
|
||||
var response = map[string]string{}
|
||||
_, err := client.HttpClient.R().SetResult(&response).Get("https://httpbin.org/ip")
|
||||
if err != nil {
|
||||
log.Errorf("获取本机公网IP失败: %v", err.Error())
|
||||
return ""
|
||||
}
|
||||
|
||||
return response["origin"]
|
||||
}
|
||||
|
||||
// IPContains
|
||||
// @description: 校验ip是否在指定IP段中
|
||||
// @receiver network
|
||||
// @param specIp
|
||||
// @param checkIP
|
||||
func (network) IPContains(specIp []string, checkIP string) bool {
|
||||
var isContains bool
|
||||
for _, sip := range specIp {
|
||||
ip, _, _ := net.ParseCIDR(checkIP)
|
||||
sipNet, _, _ := net.ParseCIDR(sip)
|
||||
ipNet := net.IPNet{IP: sipNet, Mask: net.CIDRMask(24, 32)}
|
||||
|
||||
if ipNet.Contains(ip) {
|
||||
isContains = true
|
||||
}
|
||||
}
|
||||
|
||||
return isContains
|
||||
}
|
||||
|
||||
// IPContainsByIP
|
||||
// @description: 校验ip是否在指定IP段中
|
||||
// @receiver network
|
||||
// @param specIp
|
||||
// @param checkIP
|
||||
func (network) IPContainsByIP(specIp string, checkIP string) bool {
|
||||
ip, _, _ := net.ParseCIDR(checkIP)
|
||||
sipNet, _, _ := net.ParseCIDR(specIp)
|
||||
ipNet := net.IPNet{IP: sipNet, Mask: net.CIDRMask(24, 32)}
|
||||
|
||||
if ipNet.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseIP
|
||||
// @description: 将带有mark的ip解析
|
||||
// @receiver network
|
||||
// @param ip
|
||||
// @return string
|
||||
func (network) ParseIP(ip string) string {
|
||||
ipn, _, _ := net.ParseCIDR(ip)
|
||||
return ipn.String()
|
||||
}
|
||||
|
||||
// GetIPSuffix
|
||||
// @description: 获取IP后缀 [10.10.10.23] 这里只获取23
|
||||
// @receiver network
|
||||
// @param ip
|
||||
// @return string
|
||||
func (network) GetIPSuffix(ip string) string {
|
||||
if strings.Contains(ip, "/") {
|
||||
ip = strings.Split(ip, "/")[0]
|
||||
}
|
||||
|
||||
// 再次拆分,只取最后一段
|
||||
return strings.Split(ip, ".")[3]
|
||||
}
|
||||
|
||||
// GetIPPrefix
|
||||
// @description: 获取IP前缀[10.10.10.23] 这里只获取 10.10.10
|
||||
// @receiver network
|
||||
// @param ip
|
||||
// @return string
|
||||
func (network) GetIPPrefix(ip string) string {
|
||||
if strings.Contains(ip, "/") {
|
||||
ip = strings.Split(ip, "/")[0]
|
||||
}
|
||||
|
||||
return strings.Join(strings.Split(ip, ".")[:3], ".")
|
||||
}
|
||||
|
||||
// GenerateIPByIPS
|
||||
// @description: 根据指定IP段分配IP
|
||||
// @receiver n
|
||||
// @param ips
|
||||
// @param assignedIPS
|
||||
// @return string
|
||||
func (n network) GenerateIPByIPS(ips []string, assignedIPS ...string) []string {
|
||||
var oips []string
|
||||
for _, sip := range ips {
|
||||
// 再次拆分,只取最后一段
|
||||
suffix := n.GetIPSuffix(sip)
|
||||
prefix := n.GetIPPrefix(sip)
|
||||
for _, cip := range assignedIPS {
|
||||
if n.IPContainsByIP(sip, cip) {
|
||||
suffix = n.GetIPSuffix(cip)
|
||||
}
|
||||
}
|
||||
suffix = cast.ToString(cast.ToInt64(suffix) + 1)
|
||||
oips = append(oips, fmt.Sprintf("%s.%s", prefix, suffix))
|
||||
}
|
||||
|
||||
return oips
|
||||
}
|
19
utils/paginate.go
Normal file
19
utils/paginate.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package utils
|
||||
|
||||
type paginate struct{}
|
||||
|
||||
func Paginate() paginate {
|
||||
return paginate{}
|
||||
}
|
||||
|
||||
func (paginate) Generate(count int64, size int) int {
|
||||
totalPage := 0
|
||||
if count > 0 {
|
||||
upPage := 0
|
||||
if int(count)%size > 0 {
|
||||
upPage = 1
|
||||
}
|
||||
totalPage = (int(count) / size) + upPage
|
||||
}
|
||||
return totalPage
|
||||
}
|
38
utils/password.go
Normal file
38
utils/password.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type password struct{}
|
||||
|
||||
func Password() password {
|
||||
return password{}
|
||||
}
|
||||
|
||||
// GenerateHashPassword
|
||||
// @description: 生成hash密码
|
||||
// @receiver password
|
||||
// @param pass
|
||||
// @return string
|
||||
func (password) GenerateHashPassword(pass string) string {
|
||||
bytePass := []byte(pass)
|
||||
hPass, _ := bcrypt.GenerateFromPassword(bytePass, bcrypt.DefaultCost)
|
||||
return string(hPass)
|
||||
}
|
||||
|
||||
// ComparePassword
|
||||
// @description: 密码比对
|
||||
// @receiver password
|
||||
// @param dbPass
|
||||
// @param pass
|
||||
// @return bool
|
||||
func (password) ComparePassword(dbPass, pass string) bool {
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(dbPass), []byte(pass)); err != nil {
|
||||
log.Errorf("密码错误: %v", err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
38
utils/qr_code.go
Normal file
38
utils/qr_code.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"gitee.ltd/lxh/logger/log"
|
||||
"github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
type qrCode struct{}
|
||||
|
||||
func QRCode() qrCode {
|
||||
return qrCode{}
|
||||
}
|
||||
|
||||
// GenerateQrCodeBase64
|
||||
// @description: 生成二维码
|
||||
// @receiver qr
|
||||
// @param content
|
||||
// @param size
|
||||
// @return imgStr
|
||||
// @return err
|
||||
func (qr qrCode) GenerateQrCodeBase64(content []byte, size int) (imgStr string, err error) {
|
||||
q, err := qrcode.New(string(content), qrcode.Highest)
|
||||
if err != nil {
|
||||
log.Errorf("初始化二维码对象失败: %v", err.Error())
|
||||
return
|
||||
}
|
||||
q.DisableBorder = false
|
||||
|
||||
png, err := q.PNG(size)
|
||||
if err != nil {
|
||||
log.Errorf("生成二维码失败: %v", err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
imgStr = "data:image/png;base64," + base64.StdEncoding.EncodeToString(png)
|
||||
return
|
||||
}
|
26
utils/rand.go
Normal file
26
utils/rand.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type random struct{}
|
||||
|
||||
func Random() random {
|
||||
return random{}
|
||||
}
|
||||
|
||||
func (random) RandStr(len int) string {
|
||||
var container string
|
||||
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||
b := bytes.NewBufferString(str)
|
||||
length := b.Len()
|
||||
bigInt := big.NewInt(int64(length))
|
||||
for i := 0; i < len; i++ {
|
||||
randomInt, _ := rand.Int(rand.Reader, bigInt)
|
||||
container += string(str[randomInt.Int64()])
|
||||
}
|
||||
return container
|
||||
}
|
17
utils/website.go
Normal file
17
utils/website.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package utils
|
||||
|
||||
import "net/url"
|
||||
|
||||
type website struct{}
|
||||
|
||||
func WebSite() website {
|
||||
return website{}
|
||||
}
|
||||
func (website) GetHost(addr string) string {
|
||||
uu, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return uu.Host
|
||||
}
|
Reference in New Issue
Block a user