Jelajahi Sumber

Merge branch 'dev' into feat/platform-windows

Jacky 11 bulan lalu
induk
melakukan
3bb40bc189

+ 2 - 3
.github/workflows/build.yml

@@ -2,9 +2,8 @@ name: Build
 
 on:
   push:
-    branches:
-      - '*'
-      - '!weblate'
+    branches-ignore:
+      - 'weblate'
     paths:
       - "app/**/*.js"
       - "app/**/*.vue"

+ 26 - 10
api/analytic/analytic.go

@@ -37,10 +37,9 @@ func Analytic(c *gin.Context) {
 
 	for {
 		stat.Memory, err = analytic.GetMemoryStat()
-
 		if err != nil {
 			logger.Error(err)
-			return
+			continue
 		}
 
 		cpuTimesBefore, _ := cpu.Times(false)
@@ -57,18 +56,29 @@ func Analytic(c *gin.Context) {
 			Total:  cast.ToFloat64(fmt.Sprintf("%.2f", (cpuUserUsage+cpuSystemUsage)*100)),
 		}
 
-		stat.Uptime, _ = host.Uptime()
+		stat.Uptime, err = host.Uptime()
+		if err != nil {
+			logger.Error(err)
+			continue
+		}
 
-		stat.LoadAvg, _ = load.Avg()
+		stat.LoadAvg, err = load.Avg()
+		if err != nil {
+			logger.Error(err)
+			continue
+		}
 
 		stat.Disk, err = analytic.GetDiskStat()
-
 		if err != nil {
 			logger.Error(err)
-			return
+			continue
 		}
 
-		network, _ := net.IOCounters(false)
+		network, err := net.IOCounters(false)
+		if err != nil {
+			logger.Error(err)
+			continue
+		}
 
 		if len(network) > 0 {
 			stat.Network = network[0]
@@ -80,7 +90,8 @@ func Analytic(c *gin.Context) {
 			logger.Error(err)
 			break
 		}
-		time.Sleep(800 * time.Microsecond)
+
+		time.Sleep(1000 * time.Microsecond)
 	}
 }
 
@@ -109,7 +120,12 @@ func GetAnalyticInit(c *gin.Context) {
 	if len(network) > 0 {
 		_net = network[0]
 	}
-	hostInfo, _ := host.Info()
+
+	hostInfo, err := host.Info()
+	if err != nil {
+		logger.Error(err)
+		hostInfo = &host.InfoStat{}
+	}
 
 	switch hostInfo.Platform {
 	case "ubuntu":
@@ -119,9 +135,9 @@ func GetAnalyticInit(c *gin.Context) {
 	}
 
 	loadAvg, err := load.Avg()
-
 	if err != nil {
 		logger.Error(err)
+		loadAvg = &load.AvgStat{}
 	}
 
 	c.JSON(http.StatusOK, InitResp{

+ 10 - 8
api/config/get.go

@@ -10,6 +10,7 @@ import (
 	"github.com/sashabaranov/go-openai"
 	"net/http"
 	"os"
+	"path/filepath"
 )
 
 type APIConfigResp struct {
@@ -19,30 +20,30 @@ type APIConfigResp struct {
 }
 
 func GetConfig(c *gin.Context) {
-	name := c.Param("name")
+	relativePath := c.Param("path")
 
-	path := nginx.GetConfPath("/", name)
-	if !helper.IsUnderDirectory(path, nginx.GetConfPath()) {
+	absPath := nginx.GetConfPath(relativePath)
+	if !helper.IsUnderDirectory(absPath, nginx.GetConfPath()) {
 		c.JSON(http.StatusForbidden, gin.H{
 			"message": "path is not under the nginx conf path",
 		})
 		return
 	}
 
-	stat, err := os.Stat(path)
+	stat, err := os.Stat(absPath)
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
 	}
 
-	content, err := os.ReadFile(path)
+	content, err := os.ReadFile(absPath)
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
 	}
 	q := query.Config
 	g := query.ChatGPTLog
-	chatgpt, err := g.Where(g.Name.Eq(path)).FirstOrCreate()
+	chatgpt, err := g.Where(g.Name.Eq(absPath)).FirstOrCreate()
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
@@ -52,7 +53,7 @@ func GetConfig(c *gin.Context) {
 		chatgpt.Content = make([]openai.ChatCompletionMessage, 0)
 	}
 
-	cfg, err := q.Where(q.Filepath.Eq(path)).FirstOrInit()
+	cfg, err := q.Where(q.Filepath.Eq(absPath)).FirstOrInit()
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
@@ -63,8 +64,9 @@ func GetConfig(c *gin.Context) {
 			Name:            stat.Name(),
 			Content:         string(content),
 			ChatGPTMessages: chatgpt.Content,
-			FilePath:        path,
+			FilePath:        absPath,
 			ModifiedAt:      stat.ModTime(),
+			Dir:             filepath.Dir(relativePath),
 		},
 		SyncNodeIds:   cfg.SyncNodeIds,
 		SyncOverwrite: cfg.SyncOverwrite,

+ 18 - 49
api/config/modify.go

@@ -11,6 +11,7 @@ import (
 	"github.com/sashabaranov/go-openai"
 	"net/http"
 	"os"
+	"path/filepath"
 	"time"
 )
 
@@ -19,11 +20,9 @@ type EditConfigJson struct {
 }
 
 func EditConfig(c *gin.Context) {
-	name := c.Param("name")
+	relativePath := c.Param("path")
 	var json struct {
 		Name          string   `json:"name" binding:"required"`
-		Filepath      string   `json:"filepath" binding:"required"`
-		NewFilepath   string   `json:"new_filepath" binding:"required"`
 		Content       string   `json:"content"`
 		SyncOverwrite bool     `json:"sync_overwrite"`
 		SyncNodeIds   []uint64 `json:"sync_node_ids"`
@@ -32,22 +31,8 @@ func EditConfig(c *gin.Context) {
 		return
 	}
 
-	path := json.Filepath
-	if !helper.IsUnderDirectory(path, nginx.GetConfPath()) {
-		c.JSON(http.StatusForbidden, gin.H{
-			"message": "filepath is not under the nginx conf path",
-		})
-		return
-	}
-
-	if !helper.IsUnderDirectory(json.NewFilepath, nginx.GetConfPath()) {
-		c.JSON(http.StatusForbidden, gin.H{
-			"message": "new filepath is not under the nginx conf path",
-		})
-		return
-	}
-
-	if !helper.FileExists(path) {
+	absPath := nginx.GetConfPath(relativePath)
+	if !helper.FileExists(absPath) {
 		c.JSON(http.StatusNotFound, gin.H{
 			"message": "file not found",
 		})
@@ -55,14 +40,14 @@ func EditConfig(c *gin.Context) {
 	}
 
 	content := json.Content
-	origContent, err := os.ReadFile(path)
+	origContent, err := os.ReadFile(absPath)
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
 	}
 
 	if content != "" && content != string(origContent) {
-		err = os.WriteFile(path, []byte(content), 0644)
+		err = os.WriteFile(absPath, []byte(content), 0644)
 		if err != nil {
 			api.ErrHandler(c, err)
 			return
@@ -70,17 +55,15 @@ func EditConfig(c *gin.Context) {
 	}
 
 	q := query.Config
-	cfg, err := q.Where(q.Filepath.Eq(json.Filepath)).FirstOrCreate()
+	cfg, err := q.Where(q.Filepath.Eq(absPath)).FirstOrCreate()
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
 	}
 
-	_, err = q.Where(q.Filepath.Eq(json.Filepath)).
-		Select(q.Name, q.Filepath, q.SyncNodeIds, q.SyncOverwrite).
+	_, err = q.Where(q.Filepath.Eq(absPath)).
+		Select(q.SyncNodeIds, q.SyncOverwrite).
 		Updates(&model.Config{
-			Name:          json.Name,
-			Filepath:      json.NewFilepath,
 			SyncNodeIds:   json.SyncNodeIds,
 			SyncOverwrite: json.SyncOverwrite,
 		})
@@ -89,27 +72,12 @@ func EditConfig(c *gin.Context) {
 		return
 	}
 
-	g := query.ChatGPTLog
-	// handle rename
-	if path != json.NewFilepath {
-		if helper.FileExists(json.NewFilepath) {
-			c.JSON(http.StatusNotAcceptable, gin.H{
-				"message": "File exists",
-			})
-			return
-		}
-		err := os.Rename(json.Filepath, json.NewFilepath)
-		if err != nil {
-			api.ErrHandler(c, err)
-			return
-		}
-
-		// update ChatGPT record
-		_, _ = g.Where(g.Name.Eq(json.NewFilepath)).Delete()
-		_, _ = g.Where(g.Name.Eq(path)).Update(g.Name, json.NewFilepath)
-	}
+	// use the new values
+	cfg.SyncNodeIds = json.SyncNodeIds
+	cfg.SyncOverwrite = json.SyncOverwrite
 
-	err = config.SyncToRemoteServer(cfg, json.NewFilepath)
+	g := query.ChatGPTLog
+	err = config.SyncToRemoteServer(cfg, absPath)
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
@@ -123,7 +91,7 @@ func EditConfig(c *gin.Context) {
 		return
 	}
 
-	chatgpt, err := g.Where(g.Name.Eq(json.NewFilepath)).FirstOrCreate()
+	chatgpt, err := g.Where(g.Name.Eq(absPath)).FirstOrCreate()
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
@@ -134,10 +102,11 @@ func EditConfig(c *gin.Context) {
 	}
 
 	c.JSON(http.StatusOK, config.Config{
-		Name:            name,
+		Name:            filepath.Base(absPath),
 		Content:         content,
 		ChatGPTMessages: chatgpt.Content,
-		FilePath:        json.NewFilepath,
+		FilePath:        absPath,
 		ModifiedAt:      time.Now(),
+		Dir:             filepath.Dir(relativePath),
 	})
 }

+ 7 - 2
api/config/rename.go

@@ -5,11 +5,13 @@ import (
 	"github.com/0xJacky/Nginx-UI/internal/config"
 	"github.com/0xJacky/Nginx-UI/internal/helper"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
+	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/gin-gonic/gin"
 	"github.com/uozi-tech/cosy/logger"
 	"net/http"
 	"os"
+	"strings"
 )
 
 func Rename(c *gin.Context) {
@@ -77,7 +79,10 @@ func Rename(c *gin.Context) {
 		_, _ = g.Where(g.Name.Like(origFullPath+"%")).Update(g.Name, g.Name.Replace(origFullPath, newFullPath))
 	}
 
-	_, err = q.Where(q.Filepath.Eq(origFullPath)).Update(q.Filepath, newFullPath)
+	_, err = q.Where(q.Filepath.Eq(origFullPath)).Updates(&model.Config{
+		Filepath: newFullPath,
+		Name:     json.NewName,
+	})
 	if err != nil {
 		api.ErrHandler(c, err)
 		return
@@ -92,6 +97,6 @@ func Rename(c *gin.Context) {
 	}
 
 	c.JSON(http.StatusOK, gin.H{
-		"message": "ok",
+		"path": strings.TrimLeft(newFullPath, nginx.GetConfPath()),
 	})
 }

+ 2 - 2
api/config/router.go

@@ -9,9 +9,9 @@ func InitRouter(r *gin.RouterGroup) {
 	r.GET("config_base_path", GetBasePath)
 
 	r.GET("configs", GetConfigs)
-	r.GET("configs/*name", GetConfig)
+	r.GET("configs/*path", GetConfig)
 	r.POST("configs", AddConfig)
-	r.POST("configs/*name", EditConfig)
+	r.POST("configs/*path", EditConfig)
 
 	o := r.Group("", middleware.RequireSecureSession())
 	{

+ 10 - 5
api/nginx/nginx_log.go

@@ -49,7 +49,6 @@ func GetNginxLogPage(c *gin.Context) {
 	}
 
 	logPath, err := getLogPath(&control)
-
 	if err != nil {
 		c.JSON(http.StatusInternalServerError, nginxLogPageResp{
 			Error: err.Error(),
@@ -59,7 +58,6 @@ func GetNginxLogPage(c *gin.Context) {
 	}
 
 	logFileStat, err := os.Stat(logPath)
-
 	if err != nil {
 		c.JSON(http.StatusInternalServerError, nginxLogPageResp{
 			Error: err.Error(),
@@ -76,8 +74,16 @@ func GetNginxLogPage(c *gin.Context) {
 		return
 	}
 
-	f, err := os.Open(logPath)
+	// to fix: seek invalid argument #674
+	if logFileStat.Size() == 0 {
+		c.JSON(http.StatusOK, nginxLogPageResp{
+			Page:    1,
+			Content: "",
+		})
+		return
+	}
 
+	f, err := os.Open(logPath)
 	if err != nil {
 		c.JSON(http.StatusInternalServerError, nginxLogPageResp{
 			Error: err.Error(),
@@ -112,8 +118,7 @@ func GetNginxLogPage(c *gin.Context) {
 	}
 
 	n, err := f.Read(buf)
-
-	if err != nil && err != io.EOF {
+	if err != nil && !errors.Is(err, io.EOF) {
 		c.JSON(http.StatusInternalServerError, nginxLogPageResp{
 			Error: err.Error(),
 		})

+ 12 - 12
app/package.json

@@ -2,7 +2,7 @@
   "name": "nginx-ui-app-next",
   "type": "module",
   "version": "2.0.0-beta.39",
-  "packageManager": "pnpm@9.12.2",
+  "packageManager": "pnpm@9.12.3",
   "scripts": {
     "dev": "vite --host",
     "typecheck": "vue-tsc --noEmit",
@@ -19,9 +19,9 @@
     "@simplewebauthn/browser": "^11.0.0",
     "@vue/reactivity": "^3.5.12",
     "@vue/shared": "^3.5.12",
-    "@vueuse/components": "^11.1.0",
-    "@vueuse/core": "^11.1.0",
-    "@vueuse/integrations": "^11.1.0",
+    "@vueuse/components": "^11.2.0",
+    "@vueuse/core": "^11.2.0",
+    "@vueuse/integrations": "^11.2.0",
     "@xterm/addon-attach": "^0.11.0",
     "@xterm/addon-fit": "^0.10.0",
     "@xterm/xterm": "^5.5.0",
@@ -34,13 +34,13 @@
     "marked": "^14.1.3",
     "marked-highlight": "^2.2.0",
     "nprogress": "^0.2.0",
-    "pinia": "^2.2.4",
+    "pinia": "^2.2.6",
     "pinia-plugin-persistedstate": "^4.1.2",
     "reconnecting-websocket": "^4.4.0",
     "sortablejs": "^1.15.3",
-    "universal-cookie": "^7.2.1",
+    "universal-cookie": "^7.2.2",
     "unocss": "^0.63.6",
-    "vite-plugin-build-id": "0.4.2",
+    "vite-plugin-build-id": "0.5.0",
     "vue": "^3.5.12",
     "vue-dompurify-html": "^5.1.0",
     "vue-router": "^4.4.5",
@@ -52,14 +52,14 @@
   },
   "devDependencies": {
     "@antfu/eslint-config": "^3.8.0",
-    "@iconify-json/fa": "1.1.5",
-    "@iconify-json/tabler": "1.1.95",
+    "@iconify-json/fa": "1.2.0",
+    "@iconify-json/tabler": "1.2.7",
     "@iconify/tools": "^4.0.7",
     "@iconify/types": "^2.0.0",
     "@iconify/utils": "^2.1.33",
     "@iconify/vue": "^4.1.2",
     "@simplewebauthn/types": "^11.0.0",
-    "@types/lodash": "^4.17.12",
+    "@types/lodash": "^4.17.13",
     "@types/nprogress": "^0.2.3",
     "@types/sortablejs": "^1.15.8",
     "@vitejs/plugin-vue": "^5.1.4",
@@ -68,7 +68,7 @@
     "@vue/tsconfig": "^0.5.1",
     "ace-builds": "^1.36.3",
     "autoprefixer": "^10.4.20",
-    "eslint": "^9.13.0",
+    "eslint": "^9.14.0",
     "eslint-plugin-sonarjs": "^2.0.4",
     "less": "^4.2.0",
     "postcss": "^8.4.47",
@@ -79,6 +79,6 @@
     "unplugin-vue-define-options": "^1.5.2",
     "vite": "^5.4.10",
     "vite-svg-loader": "^5.1.0",
-    "vue-tsc": "^2.1.6"
+    "vue-tsc": "^2.1.10"
   }
 }

File diff ditekan karena terlalu besar
+ 233 - 205
app/pnpm-lock.yaml


+ 2 - 1
app/src/api/config.ts

@@ -10,6 +10,7 @@ export interface Config {
   modified_at: string
   sync_node_ids?: number[]
   sync_overwrite?: false
+  dir: string
 }
 
 class ConfigCurd extends Curd<Config> {
@@ -25,7 +26,7 @@ class ConfigCurd extends Curd<Config> {
     return http.post('/config_mkdir', { base_path: basePath, folder_name: name })
   }
 
-  rename(basePath: string, origName: string, newName: string, syncNodeIds: number[]) {
+  rename(basePath: string, origName: string, newName: string, syncNodeIds?: number[]) {
     return http.post('/config_rename', {
       base_path: basePath,
       orig_name: origName,

+ 3 - 3
app/src/components/Notification/config.ts

@@ -11,13 +11,13 @@ export function syncConfigError(text: string) {
     return $gettext('Please upgrade the remote Nginx UI to the latest version')
   }
 
-  return $gettext('Sync config %{config_name} to %{env_name} failed, response: %{resp}', { config_name: data.cert_name, env_name: data.env_name, resp: data.resp_body }, true)
+  return $gettext('Sync config %{config_name} to %{env_name} failed, response: %{resp}', { config_name: data.config_name, env_name: data.env_name, resp: data.resp_body }, true)
 }
 
 export function syncRenameConfigSuccess(text: string) {
   const data = JSON.parse(text)
 
-  return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} successfully', { orig_path: data.orig_path, new_path: data.orig_path, env_name: data.env_name })
+  return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} successfully', { orig_path: data.orig_path, new_path: data.new_path, env_name: data.env_name })
 }
 
 export function syncRenameConfigError(text: string) {
@@ -27,7 +27,7 @@ export function syncRenameConfigError(text: string) {
     return $gettext('Please upgrade the remote Nginx UI to the latest version')
   }
 
-  return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, response: %{resp}', { orig_path: data.orig_path, new_path: data.orig_path, resp: data.resp_body, env_name: data.env_name }, true)
+  return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, response: %{resp}', { orig_path: data.orig_path, new_path: data.new_path, resp: data.resp_body, env_name: data.env_name }, true)
 }
 
 export function saveSiteSuccess(text: string) {

+ 2 - 1
app/src/views/config/ConfigEditor.vue

@@ -11,6 +11,7 @@ import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
 import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
 import { formatDateTime } from '@/lib/helper'
 import { useSettingsStore } from '@/pinia'
+import ConfigName from '@/views/config/components/ConfigName.vue'
 import InspectConfig from '@/views/config/InspectConfig.vue'
 import { InfoCircleOutlined } from '@ant-design/icons-vue'
 import { message } from 'ant-design-vue'
@@ -255,7 +256,7 @@ function goBack() {
                 name="name"
                 :label="$gettext('Name')"
               >
-                <AInput v-model:value="data.name" />
+                <ConfigName :name="data.name" :dir="data.dir" />
               </AFormItem>
               <AFormItem
                 v-if="!addMode"

+ 2 - 3
app/src/views/config/ConfigList.vue

@@ -7,7 +7,6 @@ import Mkdir from '@/views/config/components/Mkdir.vue'
 import Rename from '@/views/config/components/Rename.vue'
 import configColumns from '@/views/config/configColumns'
 import InspectConfig from '@/views/config/InspectConfig.vue'
-import { $gettext } from '../../gettext'
 
 const table = ref()
 const route = useRoute()
@@ -143,12 +142,12 @@ const refRename = ref()
           size="small"
           @click="() => {
             if (!record.is_dir) {
-              $router.push({
+              router.push({
                 path: `/config/${basePath}${record.name}/edit`,
               })
             }
             else {
-              $router.push({
+              router.push({
                 query: {
                   dir: basePath + record.name,
                 },

+ 67 - 0
app/src/views/config/components/ConfigName.vue

@@ -0,0 +1,67 @@
+<script setup lang="ts">
+import config from '@/api/config'
+import use2FAModal from '@/components/TwoFA/use2FAModal'
+import { message } from 'ant-design-vue'
+
+const props = defineProps<{
+  dir?: string
+}>()
+
+const name = defineModel<string>('name', { default: '' })
+
+const router = useRouter()
+
+const modify = ref(false)
+const buffer = ref('')
+const loading = ref(false)
+
+function clickModify() {
+  buffer.value = name.value
+  modify.value = true
+}
+
+function save() {
+  loading.value = true
+  const otpModal = use2FAModal()
+
+  otpModal.open().then(() => {
+    config.rename(props.dir!, name.value, buffer.value).then(r => {
+      modify.value = false
+      message.success($gettext('Renamed successfully'))
+      router.push({
+        path: `/config/${r.path}/edit`,
+      })
+    }).catch(e => {
+      message.error($gettext(e?.message ?? 'Server error'))
+    }).finally(() => {
+      loading.value = false
+    })
+  })
+}
+</script>
+
+<template>
+  <div v-if="!modify" class="flex items-center">
+    <div class="mr-2">
+      {{ name }}
+    </div>
+    <div>
+      <AButton type="link" size="small" @click="clickModify">
+        {{ $gettext('Rename') }}
+      </AButton>
+    </div>
+  </div>
+  <div v-else>
+    <AInput v-model:value="buffer">
+      <template #suffix>
+        <AButton :disabled="buffer === name" type="link" size="small" :loading @click="save">
+          {{ $gettext('Save') }}
+        </AButton>
+      </template>
+    </AInput>
+  </div>
+</template>
+
+<style scoped lang="less">
+
+</style>

+ 12 - 1
app/src/views/dashboard/ServerAnalytic.vue

@@ -6,9 +6,20 @@ import analytic from '@/api/analytic'
 import AreaChart from '@/components/Chart/AreaChart.vue'
 import RadialBarChart from '@/components/Chart/RadialBarChart.vue'
 import { bytesToSize } from '@/lib/helper'
+import { useSettingsStore } from '@/pinia'
 
 let websocket: ReconnectingWebSocket | WebSocket
 
+const settings = useSettingsStore()
+
+const { language } = storeToRefs(settings)
+
+const rerender = ref(0)
+
+watch(language, () => {
+  rerender.value += 1
+})
+
 const host: HostInfoStat = reactive({
   platform: '',
   platformVersion: '',
@@ -153,7 +164,7 @@ function wsOnMessage(m: MessageEvent) {
 </script>
 
 <template>
-  <div>
+  <div :key="rerender">
     <ARow
       :gutter="[{ xs: 0, sm: 16 }, 16]"
       class="first-row"

+ 3 - 3
docs/package.json

@@ -7,13 +7,13 @@
     "docs:preview": "vitepress preview"
   },
   "dependencies": {
-    "vitepress": "^1.4.1",
+    "vitepress": "^1.4.5",
     "vue": "^3.5.12"
   },
   "devDependencies": {
-    "@types/node": "^22.8.1",
+    "@types/node": "^22.8.7",
     "less": "^4.2.0"
   },
   "license": "AGPL-3.0",
-  "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228"
+  "packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee"
 }

+ 66 - 66
docs/pnpm-lock.yaml

@@ -9,15 +9,15 @@ importers:
   .:
     dependencies:
       vitepress:
-        specifier: ^1.4.1
-        version: 1.4.1(@algolia/client-search@4.24.0)(@types/node@22.8.1)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0)
+        specifier: ^1.4.5
+        version: 1.4.5(@algolia/client-search@4.24.0)(@types/node@22.8.7)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0)
       vue:
         specifier: ^3.5.12
         version: 3.5.12
     devDependencies:
       '@types/node':
-        specifier: ^22.8.1
-        version: 22.8.1
+        specifier: ^22.8.7
+        version: 22.8.7
       less:
         specifier: ^4.2.0
         version: 4.2.0
@@ -350,20 +350,20 @@ packages:
     cpu: [x64]
     os: [win32]
 
-  '@shikijs/core@1.22.0':
-    resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==}
+  '@shikijs/core@1.22.2':
+    resolution: {integrity: sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==}
 
-  '@shikijs/engine-javascript@1.22.0':
-    resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==}
+  '@shikijs/engine-javascript@1.22.2':
+    resolution: {integrity: sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==}
 
-  '@shikijs/engine-oniguruma@1.22.0':
-    resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==}
+  '@shikijs/engine-oniguruma@1.22.2':
+    resolution: {integrity: sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==}
 
-  '@shikijs/transformers@1.22.0':
-    resolution: {integrity: sha512-k7iMOYuGQA62KwAuJOQBgH2IQb5vP8uiB3lMvAMGUgAMMurePOx3Z7oNqJdcpxqZP6I9cc7nc4DNqSKduCxmdg==}
+  '@shikijs/transformers@1.22.2':
+    resolution: {integrity: sha512-8f78OiBa6pZDoZ53lYTmuvpFPlWtevn23bzG+azpPVvZg7ITax57o/K3TC91eYL3OMJOO0onPbgnQyZjRos8XQ==}
 
-  '@shikijs/types@1.22.0':
-    resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==}
+  '@shikijs/types@1.22.2':
+    resolution: {integrity: sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==}
 
   '@shikijs/vscode-textmate@9.3.0':
     resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==}
@@ -386,8 +386,8 @@ packages:
   '@types/mdurl@2.0.0':
     resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
 
-  '@types/node@22.8.1':
-    resolution: {integrity: sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==}
+  '@types/node@22.8.7':
+    resolution: {integrity: sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==}
 
   '@types/unist@3.0.3':
     resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
@@ -417,14 +417,14 @@ packages:
   '@vue/compiler-ssr@3.5.12':
     resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==}
 
-  '@vue/devtools-api@7.4.6':
-    resolution: {integrity: sha512-XipBV5k0/IfTr0sNBDTg7OBUCp51cYMMXyPxLXJZ4K/wmUeMqt8cVdr2ZZGOFq+si/jTyCYnNxeKoyev5DOUUA==}
+  '@vue/devtools-api@7.6.2':
+    resolution: {integrity: sha512-NCT0ujqlwAhoFvCsAG7G5qS8w/A/dhvFSt2BhmNxyqgpYDrf9CG1zYyWLQkE3dsZ+5lCT6ULUic2VKNaE07Vzg==}
 
-  '@vue/devtools-kit@7.4.6':
-    resolution: {integrity: sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==}
+  '@vue/devtools-kit@7.6.2':
+    resolution: {integrity: sha512-k61BxHRmcTtIQZFouF9QWt9nCCNtSdw12lhg8VNtHq5/XOBGD+ewiK27a40UJ8UPYoCJvi80hbvbYr5E/Zeu1g==}
 
-  '@vue/devtools-shared@7.4.6':
-    resolution: {integrity: sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==}
+  '@vue/devtools-shared@7.6.2':
+    resolution: {integrity: sha512-lcjyJ7hCC0W0kNwnCGMLVTMvDLoZgjcq9BvboPgS+6jQyDul7fpzRSKTGtGhCHoxrDox7qBAKGbAl2Rcf7GE1A==}
 
   '@vue/reactivity@3.5.12':
     resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==}
@@ -496,8 +496,8 @@ packages:
   algoliasearch@4.24.0:
     resolution: {integrity: sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==}
 
-  birpc@0.2.17:
-    resolution: {integrity: sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==}
+  birpc@0.2.19:
+    resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==}
 
   ccount@2.0.1:
     resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -691,8 +691,8 @@ packages:
     resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
     hasBin: true
 
-  shiki@1.22.0:
-    resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==}
+  shiki@1.22.2:
+    resolution: {integrity: sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==}
 
   source-map-js@1.2.1:
     resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
@@ -753,8 +753,8 @@ packages:
   vfile@6.0.3:
     resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
 
-  vite@5.4.8:
-    resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==}
+  vite@5.4.10:
+    resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==}
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
@@ -784,8 +784,8 @@ packages:
       terser:
         optional: true
 
-  vitepress@1.4.1:
-    resolution: {integrity: sha512-C2rQ7PMlDVqgsaHOa0uJtgGGWaGv74QMaGL62lxKbtFkYtosJB5HAfZ8+pEbfzzvLemYaYwaiQdFLBlexK2sFw==}
+  vitepress@1.4.5:
+    resolution: {integrity: sha512-9K0k8kvdEbeowVCpKF/x0AySSq0Pr9pM8xufLgQcKMjsifwxtDjXJjcFhZv4LYw2dcpdYiBq2j7PnWi0tCaMCg==}
     hasBin: true
     peerDependencies:
       markdown-it-mathjax3: ^4
@@ -1081,31 +1081,31 @@ snapshots:
   '@rollup/rollup-win32-x64-msvc@4.24.0':
     optional: true
 
-  '@shikijs/core@1.22.0':
+  '@shikijs/core@1.22.2':
     dependencies:
-      '@shikijs/engine-javascript': 1.22.0
-      '@shikijs/engine-oniguruma': 1.22.0
-      '@shikijs/types': 1.22.0
+      '@shikijs/engine-javascript': 1.22.2
+      '@shikijs/engine-oniguruma': 1.22.2
+      '@shikijs/types': 1.22.2
       '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
       hast-util-to-html: 9.0.3
 
-  '@shikijs/engine-javascript@1.22.0':
+  '@shikijs/engine-javascript@1.22.2':
     dependencies:
-      '@shikijs/types': 1.22.0
+      '@shikijs/types': 1.22.2
       '@shikijs/vscode-textmate': 9.3.0
       oniguruma-to-js: 0.4.3
 
-  '@shikijs/engine-oniguruma@1.22.0':
+  '@shikijs/engine-oniguruma@1.22.2':
     dependencies:
-      '@shikijs/types': 1.22.0
+      '@shikijs/types': 1.22.2
       '@shikijs/vscode-textmate': 9.3.0
 
-  '@shikijs/transformers@1.22.0':
+  '@shikijs/transformers@1.22.2':
     dependencies:
-      shiki: 1.22.0
+      shiki: 1.22.2
 
-  '@shikijs/types@1.22.0':
+  '@shikijs/types@1.22.2':
     dependencies:
       '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
@@ -1131,7 +1131,7 @@ snapshots:
 
   '@types/mdurl@2.0.0': {}
 
-  '@types/node@22.8.1':
+  '@types/node@22.8.7':
     dependencies:
       undici-types: 6.19.8
 
@@ -1141,9 +1141,9 @@ snapshots:
 
   '@ungap/structured-clone@1.2.0': {}
 
-  '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@22.8.1)(less@4.2.0))(vue@3.5.12)':
+  '@vitejs/plugin-vue@5.1.4(vite@5.4.10(@types/node@22.8.7)(less@4.2.0))(vue@3.5.12)':
     dependencies:
-      vite: 5.4.8(@types/node@22.8.1)(less@4.2.0)
+      vite: 5.4.10(@types/node@22.8.7)(less@4.2.0)
       vue: 3.5.12
 
   '@vue/compiler-core@3.5.12':
@@ -1176,21 +1176,21 @@ snapshots:
       '@vue/compiler-dom': 3.5.12
       '@vue/shared': 3.5.12
 
-  '@vue/devtools-api@7.4.6':
+  '@vue/devtools-api@7.6.2':
     dependencies:
-      '@vue/devtools-kit': 7.4.6
+      '@vue/devtools-kit': 7.6.2
 
-  '@vue/devtools-kit@7.4.6':
+  '@vue/devtools-kit@7.6.2':
     dependencies:
-      '@vue/devtools-shared': 7.4.6
-      birpc: 0.2.17
+      '@vue/devtools-shared': 7.6.2
+      birpc: 0.2.19
       hookable: 5.5.3
       mitt: 3.0.1
       perfect-debounce: 1.0.0
       speakingurl: 14.0.1
       superjson: 2.2.1
 
-  '@vue/devtools-shared@7.4.6':
+  '@vue/devtools-shared@7.6.2':
     dependencies:
       rfdc: 1.4.1
 
@@ -1266,7 +1266,7 @@ snapshots:
       '@algolia/requester-node-http': 4.24.0
       '@algolia/transporter': 4.24.0
 
-  birpc@0.2.17: {}
+  birpc@0.2.19: {}
 
   ccount@2.0.1: {}
 
@@ -1504,12 +1504,12 @@ snapshots:
   semver@5.7.2:
     optional: true
 
-  shiki@1.22.0:
+  shiki@1.22.2:
     dependencies:
-      '@shikijs/core': 1.22.0
-      '@shikijs/engine-javascript': 1.22.0
-      '@shikijs/engine-oniguruma': 1.22.0
-      '@shikijs/types': 1.22.0
+      '@shikijs/core': 1.22.2
+      '@shikijs/engine-javascript': 1.22.2
+      '@shikijs/engine-oniguruma': 1.22.2
+      '@shikijs/types': 1.22.2
       '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
 
@@ -1574,34 +1574,34 @@ snapshots:
       '@types/unist': 3.0.3
       vfile-message: 4.0.2
 
-  vite@5.4.8(@types/node@22.8.1)(less@4.2.0):
+  vite@5.4.10(@types/node@22.8.7)(less@4.2.0):
     dependencies:
       esbuild: 0.21.5
       postcss: 8.4.47
       rollup: 4.24.0
     optionalDependencies:
-      '@types/node': 22.8.1
+      '@types/node': 22.8.7
       fsevents: 2.3.3
       less: 4.2.0
 
-  vitepress@1.4.1(@algolia/client-search@4.24.0)(@types/node@22.8.1)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0):
+  vitepress@1.4.5(@algolia/client-search@4.24.0)(@types/node@22.8.7)(less@4.2.0)(postcss@8.4.47)(search-insights@2.13.0):
     dependencies:
       '@docsearch/css': 3.6.2
       '@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(search-insights@2.13.0)
-      '@shikijs/core': 1.22.0
-      '@shikijs/transformers': 1.22.0
-      '@shikijs/types': 1.22.0
+      '@shikijs/core': 1.22.2
+      '@shikijs/transformers': 1.22.2
+      '@shikijs/types': 1.22.2
       '@types/markdown-it': 14.1.2
-      '@vitejs/plugin-vue': 5.1.4(vite@5.4.8(@types/node@22.8.1)(less@4.2.0))(vue@3.5.12)
-      '@vue/devtools-api': 7.4.6
+      '@vitejs/plugin-vue': 5.1.4(vite@5.4.10(@types/node@22.8.7)(less@4.2.0))(vue@3.5.12)
+      '@vue/devtools-api': 7.6.2
       '@vue/shared': 3.5.12
       '@vueuse/core': 11.1.0(vue@3.5.12)
       '@vueuse/integrations': 11.1.0(focus-trap@7.6.0)(vue@3.5.12)
       focus-trap: 7.6.0
       mark.js: 8.11.1
       minisearch: 7.1.0
-      shiki: 1.22.0
-      vite: 5.4.8(@types/node@22.8.1)(less@4.2.0)
+      shiki: 1.22.2
+      vite: 5.4.10(@types/node@22.8.7)(less@4.2.0)
       vue: 3.5.12
     optionalDependencies:
       postcss: 8.4.47

+ 33 - 32
go.mod

@@ -7,8 +7,8 @@ require (
 	github.com/0xJacky/pofile v0.2.1
 	github.com/BurntSushi/toml v1.4.0
 	github.com/caarlos0/env/v11 v11.2.2
-	github.com/casdoor/casdoor-go-sdk v1.2.0
-	github.com/creack/pty v1.1.23
+	github.com/casdoor/casdoor-go-sdk v1.3.0
+	github.com/creack/pty v1.1.24
 	github.com/dgraph-io/ristretto/v2 v2.0.0-alpha
 	github.com/dustin/go-humanize v1.0.1
 	github.com/elliotchance/orderedmap/v2 v2.4.0
@@ -16,7 +16,7 @@ require (
 	github.com/gin-contrib/static v1.1.2
 	github.com/gin-gonic/gin v1.10.0
 	github.com/go-acme/lego/v4 v4.19.2
-	github.com/go-co-op/gocron/v2 v2.12.1
+	github.com/go-co-op/gocron/v2 v2.12.3
 	github.com/go-playground/validator/v10 v10.22.1
 	github.com/go-resty/resty/v2 v2.15.3
 	github.com/go-webauthn/webauthn v0.11.2
@@ -30,12 +30,12 @@ require (
 	github.com/pquerna/otp v1.4.0
 	github.com/pretty66/websocketproxy v0.0.0-20220507015215-930b3a686308
 	github.com/samber/lo v1.47.0
-	github.com/sashabaranov/go-openai v1.32.3
-	github.com/shirou/gopsutil/v4 v4.24.9
+	github.com/sashabaranov/go-openai v1.32.5
+	github.com/shirou/gopsutil/v4 v4.24.10
 	github.com/spf13/cast v1.7.0
 	github.com/stretchr/testify v1.9.0
 	github.com/tufanbarisyildirim/gonginx v0.0.0-20241013191809-e73b7dd454e8
-	github.com/uozi-tech/cosy v1.9.12
+	github.com/uozi-tech/cosy v1.9.13
 	github.com/uozi-tech/cosy-driver-sqlite v0.2.0
 	go.uber.org/zap v1.27.0
 	golang.org/x/crypto v0.28.0
@@ -48,8 +48,8 @@ require (
 
 require (
 	aead.dev/minisign v0.3.0 // indirect
-	cloud.google.com/go/auth v0.9.9 // indirect
-	cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
+	cloud.google.com/go/auth v0.10.0 // indirect
+	cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
 	cloud.google.com/go/compute/metadata v0.5.2 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
 	github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
@@ -69,25 +69,25 @@ require (
 	github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
 	github.com/Azure/go-autorest/logger v0.2.1 // indirect
 	github.com/Azure/go-autorest/tracing v0.6.0 // indirect
-	github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
+	github.com/AzureAD/microsoft-authentication-library-for-go v1.2.3 // indirect
 	github.com/Microsoft/go-winio v0.6.2 // indirect
 	github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
 	github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
-	github.com/aliyun/alibaba-cloud-sdk-go v1.63.39 // indirect
-	github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect
-	github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect
-	github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect
-	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect
+	github.com/aliyun/alibaba-cloud-sdk-go v1.63.45 // indirect
+	github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
+	github.com/aws/aws-sdk-go-v2/config v1.28.1 // indirect
+	github.com/aws/aws-sdk-go-v2/credentials v1.17.42 // indirect
+	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
-	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/route53 v1.45.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect
+	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect
+	github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.3 // indirect
+	github.com/aws/aws-sdk-go-v2/service/route53 v1.46.0 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect
+	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect
 	github.com/aws/smithy-go v1.22.0 // indirect
 	github.com/benbjohnson/clock v1.3.5 // indirect
 	github.com/boombuler/barcode v1.0.2 // indirect
@@ -109,7 +109,7 @@ require (
 	github.com/exoscale/egoscale/v3 v3.1.7 // indirect
 	github.com/fatih/structs v1.1.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
-	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/fsnotify/fsnotify v1.8.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
 	github.com/gabriel-vasile/mimetype v1.4.6 // indirect
 	github.com/ghodss/yaml v1.0.0 // indirect
@@ -127,7 +127,7 @@ require (
 	github.com/goccy/go-json v0.10.3 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/google/go-querystring v1.1.0 // indirect
 	github.com/google/go-tpm v0.9.1 // indirect
@@ -143,7 +143,7 @@ require (
 	github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
 	github.com/hashicorp/go-uuid v1.0.3 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
-	github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.119 // indirect
+	github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.120 // indirect
 	github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
 	github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
 	github.com/itchyny/timefmt-go v0.1.6 // indirect
@@ -224,8 +224,8 @@ require (
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.19.0 // indirect
 	github.com/subosito/gotenv v1.6.0 // indirect
-	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030 // indirect
-	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1030 // indirect
+	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034 // indirect
+	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1034 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
 	github.com/tklauser/go-sysconf v0.3.14 // indirect
 	github.com/tklauser/numcpus v0.9.0 // indirect
@@ -236,10 +236,10 @@ require (
 	github.com/uozi-tech/cosy-driver-mysql v0.2.2 // indirect
 	github.com/uozi-tech/cosy-driver-postgres v0.2.1 // indirect
 	github.com/vinyldns/go-vinyldns v0.9.16 // indirect
-	github.com/vultr/govultr/v3 v3.11.1 // indirect
+	github.com/vultr/govultr/v3 v3.11.2 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
-	github.com/yandex-cloud/go-genproto v0.0.0-20241021132621-28bb61d00c2f // indirect
-	github.com/yandex-cloud/go-sdk v0.0.0-20241021153520-213d4c625eca // indirect
+	github.com/yandex-cloud/go-genproto v0.0.0-20241101135610-76a0cfc1a773 // indirect
+	github.com/yandex-cloud/go-sdk v0.0.0-20241101143304-947cf519f6bd // indirect
 	github.com/yusufpapurcu/wmi v1.2.4 // indirect
 	go.mongodb.org/mongo-driver v1.17.1 // indirect
 	go.opencensus.io v0.24.0 // indirect
@@ -260,7 +260,7 @@ require (
 	golang.org/x/text v0.19.0 // indirect
 	golang.org/x/time v0.7.0 // indirect
 	golang.org/x/tools v0.26.0 // indirect
-	google.golang.org/api v0.203.0 // indirect
+	google.golang.org/api v0.204.0 // indirect
 	google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
@@ -282,7 +282,8 @@ require (
 	k8s.io/klog/v2 v2.130.1 // indirect
 	k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 // indirect
 	sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
-	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
+	sigs.k8s.io/yaml v1.4.0 // indirect
 )
 
 replace code.pfad.fr/risefront v1.0.0 => github.com/nginxui/risefront v1.0.2

+ 64 - 0
go.sum

@@ -102,8 +102,12 @@ cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM
 cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
 cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ=
 cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
+cloud.google.com/go/auth v0.10.0 h1:tWlkvFAh+wwTOzXIjrwM64karR1iTBZ/GRr0S/DULYo=
+cloud.google.com/go/auth v0.10.0/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
 cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
 cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
+cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk=
+cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
 cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
 cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
 cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8=
@@ -658,6 +662,8 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ
 github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.3 h1:6LyjnnaLpcOKK0fbYisI+mb8CE7iNe7i89nMNQxFxs8=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
 github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
@@ -684,6 +690,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.39 h1:zlenrBGDiSEu7YnpWiAPscKNolgIo9Z6jvM5pcWAEL4=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.39/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
+github.com/aliyun/alibaba-cloud-sdk-go v1.63.45 h1:H74VbmrHgZcb7MN9ud8panaIXtY1nLgHZRWjJv2gyKU=
+github.com/aliyun/alibaba-cloud-sdk-go v1.63.45/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
@@ -696,32 +704,56 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
 github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI=
 github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
+github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
+github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
 github.com/aws/aws-sdk-go-v2/config v1.28.0 h1:FosVYWcqEtWNxHn8gB/Vs6jOlNwSoyOCA/g/sxyySOQ=
 github.com/aws/aws-sdk-go-v2/config v1.28.0/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc=
+github.com/aws/aws-sdk-go-v2/config v1.28.1 h1:oxIvOUXy8x0U3fR//0eq+RdCKimWI900+SV+10xsCBw=
+github.com/aws/aws-sdk-go-v2/config v1.28.1/go.mod h1:bRQcttQJiARbd5JZxw6wG0yIK3eLeSCPdg6uqmmlIiI=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8=
 github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q=
 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 h1:68jFVtt3NulEzojFesM/WVarlFpCaXLKaBxDpzkQ9OQ=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18/go.mod h1:Fjnn5jQVIo6VyedMc0/EhPpfNlPl7dHV916O6B+49aE=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk=
 github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s=
 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.2 h1:KACHg9TlCAph5Brs8RqVrm1SK0FVLBiDPhkZApIG5x4=
 github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.2/go.mod h1:eZZLyXEbSmrhlNXeGnZUyBUQXUwnzaJqT8tFoQGxSRA=
+github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.3 h1:lcsqV11EaB74iNKr/PaXV0Og1D/lCZIhIf+kPucTfPw=
+github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.3/go.mod h1:IyYNP3fIP5/BvFKqQFj7wwQnKuH0wndcv6j4DyG9pRk=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.45.2 h1:P4ElvGTPph12a87YpxPDIqCvVICeYJFV32UMMS/TIPc=
 github.com/aws/aws-sdk-go-v2/service/route53 v1.45.2/go.mod h1:zLKE53MjadFH0VYrDerAx25brxLYiSg4Vk3C+qPY4BQ=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.46.0 h1:AaOWmXBSDSIEsTzx8Y2nYAxckgmBPNiRU5mjn/a9ynI=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.46.0/go.mod h1:IN9bx4yLAa3a3J7A41skQefcYObNv6ARAd2i5WxvGKg=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk=
 github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 h1:UTpsIf0loCIWEbrqdLb+0RxnTXfWh2vhw4nQmFi4nPc=
+github.com/aws/aws-sdk-go-v2/service/sso v1.24.3/go.mod h1:FZ9j3PFHHAR+w0BSEjK955w5YD2UwB/l/H0yAK3MJvI=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 h1:2YCmIXv3tmiItw0LlYf6v7gEHebLY45kBEnPezbUKyU=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3/go.mod h1:u19stRyNPxGhj6dRm+Cdgu6N75qnbW7+QN0q0dsAk58=
 github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo=
 github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo=
+github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 h1:wVnQ6tigGsRqSWDEEyH6lSAJ9OyFUsSnbaUWChuSGzs=
+github.com/aws/aws-sdk-go-v2/service/sts v1.32.3/go.mod h1:VZa9yTFyj4o10YGsmDO4gbQJUvvhY72fhumT8W4LqsE=
 github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
 github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -754,6 +786,8 @@ github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3
 github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
 github.com/casdoor/casdoor-go-sdk v1.2.0 h1:DHLO8joZwgrAgdhhEZCPdrtLHdV89cXAa9UKxT7kwXg=
 github.com/casdoor/casdoor-go-sdk v1.2.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
+github.com/casdoor/casdoor-go-sdk v1.3.0 h1:iUZKsrNUkhtAoyitFIFw3e6TchctAdoxmVgLDtNAgpc=
+github.com/casdoor/casdoor-go-sdk v1.3.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -807,6 +841,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
 github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
+github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
+github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -868,6 +904,8 @@ github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
 github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
 github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
@@ -885,6 +923,8 @@ github.com/go-acme/lego/v4 v4.19.2/go.mod h1:wtDe3dDkmV4/oI2nydpNXSJpvV10J9RCyZ6
 github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
 github.com/go-co-op/gocron/v2 v2.12.1 h1:dCIIBFbzhWKdgXeEifBjHPzgQ1hoWhjS4289Hjjy1uw=
 github.com/go-co-op/gocron/v2 v2.12.1/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
+github.com/go-co-op/gocron/v2 v2.12.3 h1:3JkKjkFoAPp/i0YE+sonlF5gi+xnBChwYh75nX16MaE=
+github.com/go-co-op/gocron/v2 v2.12.3/go.mod h1:xY7bJxGazKam1cz04EebrlP4S9q4iWdiAylMGP3jY9w=
 github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
 github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
@@ -959,6 +999,8 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
+github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
@@ -1160,6 +1202,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.119 h1:2pi/hbcuv0CNVcsODkTYZY+X9j5uc1GTjSjX1cWMp/4=
 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.119/go.mod h1:JWz2ujO9X3oU5wb6kXp+DpR2UuDj2SldDbX8T0FSuhI=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.120 h1:i+rlH2xzkEMGbol86Fq/ioxgAaOnX2vkH4i/bLptc5s=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.120/go.mod h1:JWz2ujO9X3oU5wb6kXp+DpR2UuDj2SldDbX8T0FSuhI=
 github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -1548,6 +1592,8 @@ github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
 github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
 github.com/sashabaranov/go-openai v1.32.3 h1:6xZ393PbZFoJrgwveBXVZggmyH7zdp4joUdnCy7FFD8=
 github.com/sashabaranov/go-openai v1.32.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
+github.com/sashabaranov/go-openai v1.32.5 h1:/eNVa8KzlE7mJdKPZDj6886MUzZQjoVHyn0sLvIt5qA=
+github.com/sashabaranov/go-openai v1.32.5/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770=
 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8=
@@ -1558,6 +1604,8 @@ github.com/selectel/go-selvpcclient/v3 v3.1.1 h1:C1q2LqqosiapoLpnGITGmysg0YCSQYD
 github.com/selectel/go-selvpcclient/v3 v3.1.1/go.mod h1:NM7IXhh1IzqZ88DOw1Qc5Ez3tULLViXo95l5+rKPuyQ=
 github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI=
 github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q=
+github.com/shirou/gopsutil/v4 v4.24.10 h1:7VOzPtfw/5YDU+jLEoBwXwxJbQetULywoSV4RYY7HkM=
+github.com/shirou/gopsutil/v4 v4.24.10/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
 github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
@@ -1643,8 +1691,12 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030 h1:kwiUoCkooUgy7iPyhEEbio7WT21kGJUeZ5JeJfb/dYk=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034 h1:T7ewuO2DD+5R2LRpD2kTRy25aCkVDVdYkmmyUS63i08=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1030 h1:U1n/Jr0rpKctFrTOsONkZlkbQeNiLqDbi5+MS7fGMO4=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1030/go.mod h1:erWu7r8lbWSjjVuWOlLFziOEY0K674qAOWHVSvdSvrY=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1034 h1:hXxv58/eSlDj80n0P0ISXh91pC/2vqurJNwn5SpXFPI=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1034/go.mod h1:hwTIplwF9IYWz5HQcyw0+R8aqJB0lEZB8sI0pIA5Htw=
 github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
 github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
 github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
@@ -1669,6 +1721,8 @@ github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec h1:2s/ghQ8wKE+
 github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec/go.mod h1:BZr7Qs3ku1ckpqed8tCRSqTlp8NAeZfAVpfx4OzXMss=
 github.com/uozi-tech/cosy v1.9.12 h1:mIfRhrb3EW1tkjaZdsfY/zFbP2dZdyYopmQ5X/AU+VY=
 github.com/uozi-tech/cosy v1.9.12/go.mod h1:aQI/OU3EVF125K5ECgSg3+CTfG4cp5XOkr++DEP/Fas=
+github.com/uozi-tech/cosy v1.9.13 h1:twpCjjUz34eYnvGLCCZmnA466MV1r0f0rea/Hqgmgp8=
+github.com/uozi-tech/cosy v1.9.13/go.mod h1:aQI/OU3EVF125K5ECgSg3+CTfG4cp5XOkr++DEP/Fas=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2 h1:22S/XNIvuaKGqxQPsYPXN8TZ8hHjCQdcJKVQ83Vzxoo=
 github.com/uozi-tech/cosy-driver-mysql v0.2.2/go.mod h1:EZnRIbSj1V5U0gEeTobrXai/d1SV11lkl4zP9NFEmyE=
 github.com/uozi-tech/cosy-driver-postgres v0.2.1 h1:OICakGuT+omva6QOJCxTJ5Lfr7CGXLmk/zD+aS51Z2o=
@@ -1679,6 +1733,8 @@ github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4
 github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=
 github.com/vultr/govultr/v3 v3.11.1 h1:Wc6wFTwh/gBZlOqSK1Hn3P9JWoFa7NCf52vGLwQcJOg=
 github.com/vultr/govultr/v3 v3.11.1/go.mod h1:q34Wd76upKmf+vxFMgaNMH3A8BbsPBmSYZUGC8oZa5w=
+github.com/vultr/govultr/v3 v3.11.2 h1:F3QBuWb9mz3ZOecmVKm31dRAJ5f8fe279+dxZDpS64c=
+github.com/vultr/govultr/v3 v3.11.2/go.mod h1:q34Wd76upKmf+vxFMgaNMH3A8BbsPBmSYZUGC8oZa5w=
 github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@@ -1690,8 +1746,12 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/yandex-cloud/go-genproto v0.0.0-20241021132621-28bb61d00c2f h1:u7ETK40lM4ygnDzYtGFLk36fWARftvU+I0zwTYrOVwE=
 github.com/yandex-cloud/go-genproto v0.0.0-20241021132621-28bb61d00c2f/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=
+github.com/yandex-cloud/go-genproto v0.0.0-20241101135610-76a0cfc1a773 h1:xkWrnYFWxiwCKVbmuOEMR030UCFklpglmOcPv9yJz2c=
+github.com/yandex-cloud/go-genproto v0.0.0-20241101135610-76a0cfc1a773/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=
 github.com/yandex-cloud/go-sdk v0.0.0-20241021153520-213d4c625eca h1:m3Hne9w8jnfiPPDw9KqSLtRa7Et+gzCIub2ky5uUGGM=
 github.com/yandex-cloud/go-sdk v0.0.0-20241021153520-213d4c625eca/go.mod h1:id1/mPjMDlqamdsay74AJLVVLGCRTnjMIKuXpNzVN08=
+github.com/yandex-cloud/go-sdk v0.0.0-20241101143304-947cf519f6bd h1:LcA5pQoWjS2hhG6bV2ZL9eBEV2wLSVbM2KcpDphYP/w=
+github.com/yandex-cloud/go-sdk v0.0.0-20241101143304-947cf519f6bd/go.mod h1:oku4OkbdLLOOpZEz2XxYGXI7rFhxBI5W0cLPmpStdqA=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -2306,6 +2366,8 @@ google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45
 google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
 google.golang.org/api v0.203.0 h1:SrEeuwU3S11Wlscsn+LA1kb/Y5xT8uggJSkIhD08NAU=
 google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI=
+google.golang.org/api v0.204.0 h1:3PjmQQEDkR/ENVZZwIYB4W/KzYtN8OrqnNcHWpeR8E4=
+google.golang.org/api v0.204.0/go.mod h1:69y8QSoKIbL9F94bWgWAq6wGqGwyjBgi2y8rAK8zLag=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2640,6 +2702,8 @@ sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7np
 sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
 sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

+ 4 - 2
internal/analytic/analytic.go

@@ -25,8 +25,10 @@ var (
 )
 
 func init() {
-	network, _ := net.IOCounters(false)
-
+	network, err := net.IOCounters(false)
+	if err != nil {
+		logger.Error(err)
+	}
 	if len(network) > 0 {
 		LastNetRecv = network[0].BytesRecv
 		LastNetSent = network[0].BytesSent

+ 0 - 2
internal/analytic/node.go

@@ -75,7 +75,6 @@ func InitNode(env *model.Environment) (n *Node) {
 	}
 
 	u, err := url.JoinPath(env.URL, "/api/node")
-
 	if err != nil {
 		logger.Error(err)
 		return
@@ -98,7 +97,6 @@ func InitNode(env *model.Environment) (n *Node) {
 	req.Header.Set("X-Node-Secret", env.Token)
 
 	resp, err := client.Do(req)
-
 	if err != nil {
 		logger.Error(err)
 		return

+ 6 - 2
internal/analytic/node_record.go

@@ -75,7 +75,6 @@ func nodeAnalyticRecord(env *model.Environment, ctx context.Context) (err error)
 	mutex.Unlock()
 
 	u, err := env.GetWebSocketURL("/api/analytic/intro")
-
 	if err != nil {
 		return
 	}
@@ -84,7 +83,12 @@ func nodeAnalyticRecord(env *model.Environment, ctx context.Context) (err error)
 
 	header.Set("X-Node-Secret", env.Token)
 
-	c, _, err := websocket.DefaultDialer.Dial(u, header)
+	dial := &websocket.Dialer{
+		Proxy:            http.ProxyFromEnvironment,
+		HandshakeTimeout: 5 * time.Second,
+	}
+
+	c, _, err := dial.Dial(u, header)
 	if err != nil {
 		return
 	}

+ 7 - 5
internal/analytic/record.go

@@ -12,7 +12,7 @@ import (
 func getTotalDiskIO() (read, write uint64) {
 	diskIOCounters, err := disk.IOCounters()
 	if err != nil {
-		logger.Error(err.Error())
+		logger.Error(err)
 		return
 	}
 	for _, v := range diskIOCounters {
@@ -25,15 +25,18 @@ func getTotalDiskIO() (read, write uint64) {
 func recordCpu(now time.Time) {
 	cpuTimesBefore, err := cpu.Times(false)
 	if err != nil {
-		logger.Error(err.Error())
+		logger.Error(err)
 		return
 	}
+
 	time.Sleep(1000 * time.Millisecond)
+
 	cpuTimesAfter, err := cpu.Times(false)
 	if err != nil {
-		logger.Error(err.Error())
+		logger.Error(err)
 		return
 	}
+
 	threadNum := runtime.GOMAXPROCS(0)
 
 	cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000)
@@ -66,9 +69,8 @@ func recordCpu(now time.Time) {
 
 func recordNetwork(now time.Time) {
 	network, err := net.IOCounters(false)
-
 	if err != nil {
-		logger.Error(err.Error())
+		logger.Error(err)
 		return
 	}
 

+ 1 - 0
internal/config/config.go

@@ -17,4 +17,5 @@ type Config struct {
 	SiteCategoryID  uint64                         `json:"site_category_id"`
 	SiteCategory    *model.SiteCategory            `json:"site_category,omitempty"`
 	Enabled         bool                           `json:"enabled"`
+	Dir             string                         `json:"dir"`
 }

+ 1 - 1
model/site.go

@@ -2,7 +2,7 @@ package model
 
 type Site struct {
 	Model
-	Path           string        `json:"path" gorm:"uniqueIndex"`
+	Path           string        `json:"path"`
 	Advanced       bool          `json:"advanced"`
 	SiteCategoryID uint64        `json:"site_category_id"`
 	SiteCategory   *SiteCategory `json:"site_category,omitempty"`

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini