Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test4 #46

Merged
merged 92 commits into from
Nov 6, 2023
Merged
Changes from 1 commit
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
fad0d50
Compiled main.go and pushed changes
Hoshinonyaruko Oct 23, 2023
fda2572
test
Hoshinonyaruko Oct 23, 2023
34cfac1
适配了频道私聊,用bolt数据库取代ini
Hoshinonyaruko Oct 23, 2023
7fc1f10
适配了nonebot2
Hoshinonyaruko Oct 24, 2023
28f9a73
Merge branch 'main' of https://github.com/Hoshinonyaruko/Gensokyo
Hoshinonyaruko Oct 24, 2023
9fadda4
适配私域
Hoshinonyaruko Oct 24, 2023
1336c6a
add license
Hoshinonyaruko Oct 24, 2023
b094949
add a lot
Hoshinonyaruko Oct 25, 2023
f4787f5
Resolved merge conflicts
Hoshinonyaruko Oct 25, 2023
86698c6
trss support
Hoshinonyaruko Oct 26, 2023
045f3e9
fix
Hoshinonyaruko Oct 26, 2023
618561c
add action
Hoshinonyaruko Oct 26, 2023
7e803aa
add action
Hoshinonyaruko Oct 26, 2023
ece4cef
add action
Hoshinonyaruko Oct 26, 2023
f864a50
fixbug
Hoshinonyaruko Oct 26, 2023
4564731
add wss
Hoshinonyaruko Oct 26, 2023
070e4df
merge
Hoshinonyaruko Oct 26, 2023
84e8fe9
bugfix
Hoshinonyaruko Oct 26, 2023
0e4fd50
fix action
Hoshinonyaruko Oct 26, 2023
fe2234a
fix action again
Hoshinonyaruko Oct 26, 2023
cf67a11
fix action againnn
Hoshinonyaruko Oct 26, 2023
0875837
fa
Hoshinonyaruko Oct 26, 2023
3a3c33f
fix
Hoshinonyaruko Oct 26, 2023
8789fa8
add a lot
Hoshinonyaruko Oct 27, 2023
7943466
add ws server token
Hoshinonyaruko Oct 28, 2023
4660983
merge
Hoshinonyaruko Oct 28, 2023
2a1026a
bugifx
Hoshinonyaruko Oct 28, 2023
4186970
fix
Hoshinonyaruko Oct 28, 2023
2f26828
fixat
Hoshinonyaruko Oct 28, 2023
007e1af
bugfix
Hoshinonyaruko Oct 28, 2023
c41fd77
bugfix
Hoshinonyaruko Oct 28, 2023
d8354b7
test
Hoshinonyaruko Oct 28, 2023
6e3c63c
test
Hoshinonyaruko Oct 28, 2023
f08d9d7
test2
Hoshinonyaruko Oct 28, 2023
4dd6e15
add url service
Hoshinonyaruko Oct 31, 2023
1f8c174
add url service
Hoshinonyaruko Oct 31, 2023
240f569
add url service
Hoshinonyaruko Oct 31, 2023
b191cb7
bugfix
Hoshinonyaruko Oct 31, 2023
42daab3
merge
Hoshinonyaruko Oct 31, 2023
8fec03f
fix
Hoshinonyaruko Oct 31, 2023
cca528b
fix
Hoshinonyaruko Oct 31, 2023
463a182
fix
Hoshinonyaruko Oct 31, 2023
e9187a1
bug fix
Hoshinonyaruko Nov 1, 2023
5ba2815
fix
Hoshinonyaruko Nov 1, 2023
c16e1af
fix
Hoshinonyaruko Nov 1, 2023
ec7863d
test
Hoshinonyaruko Nov 2, 2023
e8a7e73
ok
Hoshinonyaruko Nov 2, 2023
122d17d
add webui
Hoshinonyaruko Nov 2, 2023
4e9c209
merge
Hoshinonyaruko Nov 2, 2023
b502d61
add image_compress
Hoshinonyaruko Nov 3, 2023
3519e3e
merge
Hoshinonyaruko Nov 3, 2023
530ff96
bug fix
Hoshinonyaruko Nov 3, 2023
155a701
fix cq code
Hoshinonyaruko Nov 3, 2023
2f5ee4a
fixbug
Hoshinonyaruko Nov 3, 2023
afa03e3
bugfix
Hoshinonyaruko Nov 3, 2023
fdd1a73
merge
Hoshinonyaruko Nov 3, 2023
fe39cd2
bugfix
Hoshinonyaruko Nov 3, 2023
be08cbe
bugfix
Hoshinonyaruko Nov 3, 2023
931dfef
merge
Hoshinonyaruko Nov 3, 2023
73819c8
bugfix
Hoshinonyaruko Nov 3, 2023
b27f062
bugfix
Hoshinonyaruko Nov 3, 2023
1a94197
bugfix
Hoshinonyaruko Nov 3, 2023
745b28e
bugfix
Hoshinonyaruko Nov 3, 2023
1212c9a
bugfix
Hoshinonyaruko Nov 4, 2023
44d8669
bugfix
Hoshinonyaruko Nov 4, 2023
564aba5
add new feature
Hoshinonyaruko Nov 5, 2023
d7345c1
bugfix
Hoshinonyaruko Nov 5, 2023
472a224
bugfix
Hoshinonyaruko Nov 5, 2023
e22b58b
bugfix
Hoshinonyaruko Nov 5, 2023
22cb473
bugfix
Hoshinonyaruko Nov 5, 2023
e563929
bugfix
Hoshinonyaruko Nov 5, 2023
829b5d7
merge
Hoshinonyaruko Nov 5, 2023
b496ac1
bugfix
Hoshinonyaruko Nov 5, 2023
13e7700
bugfix
Hoshinonyaruko Nov 5, 2023
eb7e630
bugfix
Hoshinonyaruko Nov 5, 2023
32d490f
test
Hoshinonyaruko Nov 5, 2023
9815e3a
test
Hoshinonyaruko Nov 5, 2023
7747de6
test
Hoshinonyaruko Nov 5, 2023
fe2e4be
test
Hoshinonyaruko Nov 5, 2023
ec9e797
test
Hoshinonyaruko Nov 5, 2023
3548108
test
Hoshinonyaruko Nov 5, 2023
1e50a7c
test
Hoshinonyaruko Nov 5, 2023
812e6ea
test
Hoshinonyaruko Nov 5, 2023
76363a6
test
Hoshinonyaruko Nov 5, 2023
d8b05cd
test
Hoshinonyaruko Nov 5, 2023
c2e2b20
test
Hoshinonyaruko Nov 5, 2023
cefac16
test
Hoshinonyaruko Nov 5, 2023
273db15
test
Hoshinonyaruko Nov 5, 2023
5379f7d
test
Hoshinonyaruko Nov 5, 2023
56e2429
test
Hoshinonyaruko Nov 5, 2023
4466f30
test
Hoshinonyaruko Nov 6, 2023
a32a124
test
Hoshinonyaruko Nov 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
bugfix
Hoshinonyaruko committed Nov 3, 2023
commit be08cbed95b0253ecf94af5d94e0e7cf7c45575f
178 changes: 169 additions & 9 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package config

import (
"errors"
"fmt"
"log"
"os"
"path/filepath"
"reflect"
"strings"
"sync"

@@ -48,6 +50,7 @@ type Settings struct {
Password string `yaml:"server_user_password"`
ImageLimit int `yaml:"image_sizelimit"`
RemovePrefix bool `yaml:"remove_prefix"`
BackupPort string `yaml:"backup_port"`
}

// LoadConfig 从文件中加载配置并初始化单例配置
@@ -63,15 +66,146 @@ func LoadConfig(path string) (*Config, error) {
return nil, err
}

mu.Lock()
if instance == nil {
instance = conf
// 确保配置完整性
if err := ensureConfigComplete(conf, path); err != nil {
return nil, err
}
mu.Unlock()

return conf, nil
}

func ensureConfigComplete(conf *Config, path string) error {
// 读取配置文件到缓冲区
configData, err := os.ReadFile(path)
if err != nil {
return err
}

// 将现有的配置解析到结构体中
currentConfig := &Config{}
err = yaml.Unmarshal(configData, currentConfig)
if err != nil {
return err
}

// 解析默认配置模板到结构体中
defaultConfig := &Config{}
err = yaml.Unmarshal([]byte(template.ConfigTemplate), defaultConfig)
if err != nil {
return err
}

// 使用反射比较现有配置和默认配置
missingSettings, err := getMissingSettings(&currentConfig.Settings, &defaultConfig.Settings)
if err != nil {
return err
}

if len(missingSettings) > 0 {
// 如果存在缺失的设置,从默认配置模板中提取缺失的字段及其注释
fmt.Println("缺失的设置:", missingSettings)
missingConfigLines, err := extractMissingConfigLines(missingSettings, template.ConfigTemplate)
if err != nil {
return err
}

// 将缺失的配置追加到现有配置文件
err = appendToConfigFile(path, missingConfigLines)
if err != nil {
return err
}

fmt.Println("检测到配置文件缺少项。已经更新配置文件,正在重启程序以应用新的配置。")
sys.RestartApplication()
}

return nil
}

func getMissingSettings(current, defaultConf interface{}) (map[string]string, error) {
missingSettings := make(map[string]string)

// Ensure we are dealing with pointers and get the underlying element.
currentVal := reflect.ValueOf(current)
if currentVal.Kind() != reflect.Ptr {
return nil, errors.New("current config is not a pointer")
}
currentVal = currentVal.Elem()

defaultVal := reflect.ValueOf(defaultConf)
if defaultVal.Kind() != reflect.Ptr {
return nil, errors.New("default config is not a pointer")
}
defaultVal = defaultVal.Elem()

for i := 0; i < currentVal.NumField(); i++ {
fieldInfo := currentVal.Type().Field(i) // 获取字段信息
yamlTag := fieldInfo.Tag.Get("yaml") // 从字段信息中获取 yaml 标签
if yamlTag == "" {
continue // 如果没有 yaml 标签,则跳过
}

// 使用strings来处理可能的逗号分隔的选项,例如 "fieldname,omitempty"
yamlKeyName := strings.Split(yamlTag, ",")[0] // 获取标签前的实际 YAML 键名

if isZeroOfUnderlyingType(currentVal.Field(i).Interface()) &&
!isZeroOfUnderlyingType(defaultVal.Field(i).Interface()) {
missingSettings[fieldInfo.Name] = yamlKeyName
}
}

return missingSettings, nil
}

func extractMissingConfigLines(missingSettings map[string]string, configTemplate string) ([]string, error) {
var missingConfigLines []string

// Split the configuration template into lines.
lines := strings.Split(configTemplate, "\n")
for _, yamlKey := range missingSettings {
found := false
for _, line := range lines {
// Check if the line contains the YAML key.
if strings.Contains(line, yamlKey) {
missingConfigLines = append(missingConfigLines, line)
found = true
break
}
}
if !found {
return nil, fmt.Errorf("missing configuration for key: %s", yamlKey)
}
}

return missingConfigLines, nil
}

func appendToConfigFile(path string, lines []string) error {
file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件错误:", err)
return err
}
defer file.Close()

// 写入缺失的配置项
for _, line := range lines {
if _, err := file.WriteString("\n" + line); err != nil {
fmt.Println("写入配置错误:", err)
return err
}
}

// 输出写入状态
fmt.Println("配置已更新,写入到文件:", path)

return nil
}

func isZeroOfUnderlyingType(x interface{}) bool {
return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// UpdateConfig 将配置写入文件
func UpdateConfig(conf *Config, path string) error {
data, err := yaml.Marshal(conf)
@@ -316,9 +450,16 @@ func GetDeveloperLog() bool {
}

// ComposeWebUIURL 组合webui的完整访问地址
func ComposeWebUIURL() string {
// 参数 useBackupPort 控制是否使用备用端口
func ComposeWebUIURL(useBackupPort bool) string {
serverDir := GetServer_dir()
port := GetPortValue()

var port string
if useBackupPort {
port = GetBackupPort()
} else {
port = GetPortValue()
}

// 判断端口是不是443,如果是,则使用https协议
protocol := "http"
@@ -330,11 +471,17 @@ func ComposeWebUIURL() string {
return fmt.Sprintf("%s://%s:%s/webui", protocol, serverDir, port)
}

// ComposeWebUIURL 组合webui的完整访问地址
func ComposeWebUIURLv2() string {
// ComposeWebUIURLv2 组合webui的完整访问地址
// 参数 useBackupPort 控制是否使用备用端口
func ComposeWebUIURLv2(useBackupPort bool) string {
ip, _ := sys.GetPublicIP()

port := GetPortValue()
var port string
if useBackupPort {
port = GetBackupPort()
} else {
port = GetPortValue()
}

// 判断端口是不是443,如果是,则使用https协议
protocol := "http"
@@ -394,3 +541,16 @@ func GetRemovePrefixValue() bool {
}
return instance.Settings.RemovePrefix
}

// GetLotusPort retrieves the LotusPort setting from your singleton instance.
func GetBackupPort() string {
mu.Lock()
defer mu.Unlock()

if instance == nil {
mylog.Println("Warning: instance is nil when trying to get LotusPort.")
return ""
}

return instance.Settings.BackupPort
}
18 changes: 14 additions & 4 deletions handlers/message_parser.go
Original file line number Diff line number Diff line change
@@ -186,10 +186,20 @@ func transformMessageText(messageText string) string {
})

// 使用xurls来查找和替换所有的URL
messageText = xurls.Relaxed.ReplaceAllStringFunc(messageText, func(originalURL string) string {
shortURL := url.GenerateShortURL(originalURL)
return shortURL
})
if config.GetLotusValue() {
// 连接到另一个gensokyo
messageText = xurls.Relaxed.ReplaceAllStringFunc(messageText, func(originalURL string) string {
shortURL := url.GenerateShortURL(originalURL)
return shortURL
})
} else {
// Lotus is false, prepend the base URL to the shortURL
messageText = xurls.Relaxed.ReplaceAllStringFunc(messageText, func(originalURL string) string {
shortURL := url.GenerateShortURL(originalURL)
// 使用getBaseURL函数来获取baseUrl并与shortURL组合
return url.GetBaseURL() + "/url/" + shortURL
})
}
return messageText
}

161 changes: 82 additions & 79 deletions main.go
Original file line number Diff line number Diff line change
@@ -67,8 +67,9 @@ func main() {
if err != nil {
log.Fatalf("error: %v", err)
}
webuiURL := config.ComposeWebUIURL() // 调用函数获取URL
webuiURLv2 := config.ComposeWebUIURLv2() // 调用函数获取URL

webuiURL := config.ComposeWebUIURL(conf.Settings.Lotus) // 调用函数获取URL
webuiURLv2 := config.ComposeWebUIURLv2(conf.Settings.Lotus) // 调用函数获取URL

var api openapi.OpenAPI
var apiV2 openapi.OpenAPI
@@ -209,90 +210,92 @@ func main() {

//图片上传 调用次数限制
rateLimiter := server.NewRateLimiter()
//是否启动服务器
shouldStartServer := !conf.Settings.Lotus || conf.Settings.EnableWsServer
//如果连接到其他gensokyo,则不需要启动服务器
var httpServer *http.Server
if shouldStartServer {
var r *gin.Engine
if config.GetDeveloperLog() { // 我假设这个函数是从您提供的例子中来的
r = gin.Default()
// 根据 lotus 的值选择端口
var serverPort string
if conf.Settings.Lotus {
serverPort = conf.Settings.Port
} else {
serverPort = conf.Settings.BackupPort
}
var r *gin.Engine
if config.GetDeveloperLog() { // 我假设这个函数是从您提供的例子中来的
r = gin.Default()
} else {
r = gin.New()
r.Use(gin.Recovery()) // 添加恢复中间件,但不添加日志中间件
}
r.GET("/getid", server.GetIDHandler)
r.POST("/uploadpic", server.UploadBase64ImageHandler(rateLimiter))
r.Static("/channel_temp", "./channel_temp")
//webui和它的api
webuiGroup := r.Group("/webui")
{
webuiGroup.GET("/*filepath", webui.CombinedMiddleware)
webuiGroup.POST("/*filepath", webui.CombinedMiddleware)
webuiGroup.PUT("/*filepath", webui.CombinedMiddleware)
webuiGroup.DELETE("/*filepath", webui.CombinedMiddleware)
webuiGroup.PATCH("/*filepath", webui.CombinedMiddleware)
}
//r.GET("/webui/api/serverdata", getServerDataHandler)
//r.GET("/webui/api/logdata", getLogDataHandler)
//正向ws
if conf.Settings.AppID != 12345 {
r.GET("/ws", server.WsHandlerWithDependencies(api, apiV2, p))
}
r.POST("/url", url.CreateShortURLHandler)
r.GET("/url/:shortURL", url.RedirectFromShortURLHandler)
if config.GetIdentifyFile() {
appIDStr := config.GetAppIDStr()
fileName := appIDStr + ".json"
r.GET("/"+fileName, func(c *gin.Context) {
content := fmt.Sprintf(`{"bot_appid":%d}`, config.GetAppID())
c.Header("Content-Type", "application/json")
c.String(200, content)
})
}
// 创建一个http.Server实例(主服务器)
httpServer := &http.Server{
Addr: "0.0.0.0:" + serverPort,
Handler: r,
}

// 在一个新的goroutine中启动主服务器
go func() {
if serverPort == "443" {
// 使用HTTPS
crtPath := config.GetCrtPath()
keyPath := config.GetKeyPath()
if crtPath == "" || keyPath == "" {
log.Fatalf("crt or key path is missing for HTTPS")
return
}
if err := httpServer.ListenAndServeTLS(crtPath, keyPath); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen (HTTPS): %s\n", err)
}
} else {
r = gin.New()
r.Use(gin.Recovery()) // 添加恢复中间件,但不添加日志中间件
}
r.GET("/getid", server.GetIDHandler)
r.POST("/uploadpic", server.UploadBase64ImageHandler(rateLimiter))
r.Static("/channel_temp", "./channel_temp")
//webui和它的api
webuiGroup := r.Group("/webui")
{
webuiGroup.GET("/*filepath", webui.CombinedMiddleware)
webuiGroup.POST("/*filepath", webui.CombinedMiddleware)
webuiGroup.PUT("/*filepath", webui.CombinedMiddleware)
webuiGroup.DELETE("/*filepath", webui.CombinedMiddleware)
webuiGroup.PATCH("/*filepath", webui.CombinedMiddleware)
}
//r.GET("/webui/api/serverdata", getServerDataHandler)
//r.GET("/webui/api/logdata", getLogDataHandler)
//正向ws
if conf.Settings.AppID != 12345 {
r.GET("/ws", server.WsHandlerWithDependencies(api, apiV2, p))
}
r.POST("/url", url.CreateShortURLHandler)
r.GET("/url/:shortURL", url.RedirectFromShortURLHandler)
if config.GetIdentifyFile() {
appIDStr := config.GetAppIDStr()
fileName := appIDStr + ".json"
r.GET("/"+fileName, func(c *gin.Context) {
content := fmt.Sprintf(`{"bot_appid":%d}`, config.GetAppID())
c.Header("Content-Type", "application/json")
c.String(200, content)
})
}
// 创建一个http.Server实例(主服务器)
httpServer := &http.Server{
Addr: "0.0.0.0:" + conf.Settings.Port,
Handler: r,
// 使用HTTP
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}
}()

// 在一个新的goroutine中启动主服务器
// 如果主服务器使用443端口,同时在一个新的goroutine中启动444端口的HTTP服务器 todo 更优解
if serverPort == "443" {
go func() {
if conf.Settings.Port == "443" {
// 使用HTTPS
crtPath := config.GetCrtPath()
keyPath := config.GetKeyPath()
if crtPath == "" || keyPath == "" {
log.Fatalf("crt or key path is missing for HTTPS")
return
}
if err := httpServer.ListenAndServeTLS(crtPath, keyPath); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen (HTTPS): %s\n", err)
}
} else {
// 使用HTTP
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
// 创建另一个http.Server实例(用于444端口)
httpServer444 := &http.Server{
Addr: "0.0.0.0:444",
Handler: r,
}
}()

// 如果主服务器使用443端口,同时在一个新的goroutine中启动444端口的HTTP服务器 todo 更优解
if conf.Settings.Port == "443" {
go func() {
// 创建另一个http.Server实例(用于444端口)
httpServer444 := &http.Server{
Addr: "0.0.0.0:444",
Handler: r,
}

// 启动444端口的HTTP服务器
if err := httpServer444.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen (HTTP 444): %s\n", err)
}
}()
}
// 启动444端口的HTTP服务器
if err := httpServer444.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen (HTTP 444): %s\n", err)
}
}()
}

// 使用color库输出天蓝色的文本
cyan := color.New(color.FgCyan)
cyan.Printf("欢迎来到Gensokyo, 控制台地址: %s\n", webuiURL)
1 change: 1 addition & 0 deletions template/config_template.go
Original file line number Diff line number Diff line change
@@ -49,6 +49,7 @@ settings:
server_user_password : "admin" #默认网页面板密码
image_sizelimit : 0 #代表kb 腾讯api要求图片1500ms完成传输 如果图片发不出 请提升上行或设置此值 默认为0 不压缩
remove_prefix : false #是否忽略公域机器人指令前第一个/
backup_port : "5200" #当totus为ture时,port值不再是本地webui的端口,使用lotus_Port来访问webui
`
const Logo = `
'
3 changes: 2 additions & 1 deletion template/config_template.yml
Original file line number Diff line number Diff line change
@@ -40,4 +40,5 @@ settings:
server_user_name : "useradmin" #默认网页面板用户名
server_user_password : "admin" #默认网页面板密码
image_sizelimit : 0 #代表kb 腾讯api要求图片1500ms完成传输 如果图片发不出 请提升上行或设置此值 默认为0 不压缩
remove_prefix : false #是否忽略公域机器人指令前第一个/
remove_prefix : false #是否忽略公域机器人指令前第一个/
backup_port : "5200" #当totus为ture时,port值不再是本地webui的端口,使用lotus_Port来访问webui