Files
Sillyv2/utils/init.go
T
cdle cf310e5ef7 x
2023-06-13 15:17:55 +08:00

447 lines
8.9 KiB
Go
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"time"
// "github.com/cdle/sillyplus/core/logs"
"github.com/cdle/sillyplus/core/logs"
"github.com/google/uuid"
)
var SlaveMode bool
func GenUUID() string {
u2, _ := uuid.NewUUID()
return u2.String()
}
func Float64(str interface{}) float64 {
f, _ := strconv.ParseFloat(fmt.Sprint(str), 64)
return f
}
func TrimHiddenCharacter(originStr string) string {
srcRunes := []rune(originStr)
dstRunes := make([]rune, 0, len(srcRunes))
for _, c := range srcRunes {
if c >= 0 && c <= 31 && c != 10 {
continue
}
if c == 127 {
continue
}
dstRunes = append(dstRunes, c)
}
return strings.ReplaceAll(string(dstRunes), "", "")
}
func Md5(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}
func Itob(i uint64) []byte {
return []byte(fmt.Sprint(i))
}
var Int = func(s interface{}) int {
i, _ := strconv.Atoi(fmt.Sprint(s))
return i
}
var Int64 = func(s interface{}) int64 {
i, _ := strconv.Atoi(fmt.Sprint(s))
return int64(i)
}
func init() {
err := KillPeer()
if err != nil {
logs.Warn("结束进程失败:", err)
}
err = os.WriteFile(GetPidFile(), []byte(fmt.Sprintf("%d", os.Getpid())), 0o644)
if err != nil {
logs.Warn("写入进程ID失败:", err)
}
for _, arg := range os.Args {
if arg == "-d" {
Daemon()
}
}
}
var GetDataHome = func() string {
if runtime.GOOS == "windows" {
if _, err := os.Stat(`C:\ProgramData\sillyplus\`); err != nil {
os.MkdirAll(`C:\ProgramData\sillyplus\`, os.ModePerm)
}
return `C:\ProgramData\sillyplus\`
} else if runtime.GOOS == "darwin" {
i := ExecPath + "/.sillyplus/"
if _, err := os.Stat(i); err != nil {
os.MkdirAll(i, os.ModePerm)
}
return i
} else {
if _, err := os.Stat(`/etc/sillyplus/`); err != nil {
os.MkdirAll(`/etc/sillyplus/`, os.ModePerm)
}
return `/etc/sillyplus/`
}
}
func KillProcess(pid int) error {
var cmd *exec.Cmd
switch runtime.GOOS {
case "linux", "darwin":
cmd = exec.Command("kill", "-TERM", strconv.Itoa(pid))
case "windows":
cmd = exec.Command("taskkill", "/F", "/PID", strconv.Itoa(pid))
default:
return fmt.Errorf("unsupported operating system: %v", runtime.GOOS)
}
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
err := cmd.Run()
if _, ok := err.(*exec.ExitError); ok {
return nil
}
if err != nil {
return fmt.Errorf("failed to kill process %d: %v", pid, err)
}
return nil
}
func KillPeer() error {
id, err := GetPidFromFile(GetPidFile())
if err != nil {
return err
}
if id != 0 {
return KillProcess(id)
}
return nil
}
var ProcessName = getProcessName()
var ExecPath, _ = filepath.Abs(filepath.Dir(os.Args[0]))
var getProcessName = func() string {
if runtime.GOOS == "windows" {
return regexp.MustCompile(`([\w\.-]*)\.exe$`).FindStringSubmatch(os.Args[0])[0]
}
return regexp.MustCompile(`/([^/\s]+)$`).FindStringSubmatch(os.Args[0])[1]
}
var GetPidFile = func() string {
return GetDataHome() + "sillyplus.pid"
}
func GetPidFromFile(pidFile string) (int, error) {
if _, err := os.Stat(pidFile); err != nil {
return 0, nil
}
data, err := ioutil.ReadFile(pidFile)
if err != nil {
return 0, err
}
pidStr := strings.TrimSpace(string(data))
pid, err := strconv.Atoi(pidStr)
if err != nil {
return 0, err
}
return pid, nil
}
func CopyFile(src string, dst string) error {
// 打开源文件
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
// 创建目标文件,如果目标文件已存在则覆盖
dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return err
}
defer dstFile.Close()
// 将源文件内容复制到目标文件
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return err
}
return nil
}
func Daemon(str ...string) {
first := ""
if len(str) > 0 {
first = str[0]
}
args := os.Args[1:]
if first == "ready" { //原->准备
os.Args[0] = strings.Replace(os.Args[0], ".exe", ".ready.exe", -1)
args = append(args, "-r")
}
if first == "reset" { //准备->原
os.Args[0] = strings.Replace(os.Args[0], ".ready.exe", ".exe", -1)
}
execArgs := make([]string, 0)
l := len(args)
for i := 0; i < l; i++ {
if strings.Contains(args[i], "-d") {
continue
}
if strings.Contains(args[i], "-t") {
continue
}
execArgs = append(execArgs, args[i])
}
proc := exec.Command(os.Args[0], execArgs...)
err := proc.Start()
if err != nil {
panic(err)
}
logs.Info("程序以静默形式运行")
// err = os.WriteFile(GetPidFile(), []byte(fmt.Sprintf("%d", proc.Process.Pid)), 0o644)
if err != nil {
logs.Info(err)
}
os.Exit(0)
}
func FetchCookieValue(ps ...string) string {
var key, cookies string
if len(ps) == 2 {
if len(ps[0]) > len(ps[1]) {
key, cookies = ps[1], ps[0]
} else {
key, cookies = ps[0], ps[1]
}
}
match := regexp.MustCompile(key + `=([^;]*);{0,1}`).FindStringSubmatch(cookies)
if len(match) == 2 {
return strings.Trim(match[1], " ")
} else {
return ""
}
}
func Contains(strs []string, str ...string) bool {
for _, o := range strs {
for _, str_ := range strs {
if str_ == o {
return true
}
}
}
return false
}
func Remove(strs []string, str string) []string {
for i, o := range strs {
if str == o {
return append(strs[:i], strs[i+1:]...)
}
}
return strs
}
func SafeError(err error) error {
s := err.Error()
s = regexp.MustCompile(`(http|https)://[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`).ReplaceAllString(s, "http://138.2.2.75:5700")
return errors.New(s)
}
func MonitorGoroutine() {
if runtime.GOOS == "windows" {
return
}
ticker := time.NewTicker(time.Millisecond * 100)
lastGNum := 0
for {
<-ticker.C
if newGNum := runtime.NumGoroutine(); lastGNum != newGNum {
lastGNum = newGNum
if newGNum > 800 {
Daemon()
}
}
}
}
func JsonMarshal(v interface{}) (d []byte) {
d, _ = json.Marshal(v)
return
}
func Str2Ints(str string) []int {
is := []int{}
for _, v := range Str2IntStr(str) {
is = append(is, Int(v))
}
return is
}
func Str2IntStr(str string) []string {
return regexp.MustCompile(`-?[\d]+`).FindAllString(str, -1)
}
func ToVideoQrcode(url string) string {
return `[CQ:video,file=` + url + `]`
}
func ToImageQrcode(url string) string {
return `[CQ:image,file=` + url + `]`
}
func FormatLog(f interface{}, v ...interface{}) string {
var msg string
switch f := f.(type) {
case string:
msg = f
if len(v) == 0 {
return msg
}
if strings.Contains(msg, "%") && !strings.Contains(msg, "%%") {
//format string
} else {
//do not contain format char
msg += strings.Repeat(" %v", len(v))
}
default:
msg = fmt.Sprint(f)
if len(v) == 0 {
return msg
}
msg += strings.Repeat(" %v", len(v))
}
return fmt.Sprintf(msg, v...)
}
func IsZeroOrEmpty(str string) bool {
return str == "0" || str == "" || str == "nil"
}
// func Unique(strs ...interface{}) []string {
// m := make(map[string]bool)
// var result []string
// for _, arg := range strs {
// switch arg := arg.(type) {
// case []string:
// for _, v := range arg {
// if _, ok := m[v]; !ok {
// m[v] = true
// result = append(result, v)
// }
// }
// case string:
// if _, ok := m[arg]; !ok {
// m[arg] = true
// result = append(result, arg)
// }
// }
// }
// return result
// }
func Unique(strs ...interface{}) []string {
var result []string
for _, arg := range strs {
var toAppend []string
switch arg := arg.(type) {
case []string:
for _, v := range arg {
if !contains(result, v) && !contains(toAppend, v) {
toAppend = append(toAppend, v)
}
}
case []interface{}:
for _, v := range arg {
if !contains(result, v.(string)) && !contains(toAppend, v.(string)) {
toAppend = append(toAppend, v.(string))
}
}
case string:
if !contains(result, arg) {
toAppend = append(toAppend, arg)
}
case [][]string:
subResult := Unique(flatten(arg)...)
for _, v := range subResult {
if !contains(result, v) && !contains(toAppend, v) {
toAppend = append(toAppend, v)
}
}
default:
// Unsupported type
continue
}
result = append(result, toAppend...)
}
return result
}
func contains(strs []string, s string) bool {
for _, v := range strs {
if v == s {
return true
}
}
return false
}
func flatten(arr [][]string) []interface{} {
var result []interface{}
for _, subarr := range arr {
var subresult []interface{}
for _, v := range subarr {
subresult = append(subresult, v)
}
result = append(result, subresult)
}
return result
}
func Itoa(i interface{}) string {
switch i := i.(type) {
case int:
return strconv.Itoa(i)
case int32:
return strconv.Itoa(int(i))
case int64:
return strconv.Itoa(int(i))
case int16:
return strconv.Itoa(int(i))
case string:
return i
case float32:
return strconv.Itoa(int(i))
case float64:
return strconv.Itoa(int(i))
default:
return fmt.Sprint(i)
}
}