diff --git a/.idea/vcs.xml b/.idea/vcs.xml index a57048e..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..372adba --- /dev/null +++ b/doc.go @@ -0,0 +1,21 @@ +package main + +const ( + helpDoc string = ` +欢迎使用ProjectWIND! + 使用方法: + ProjectWIND [options] + Options: + -h, --help 显示帮助文档 + -v, --version 显示版本信息 + -r, --run 运行wind + -s, 创建Linux service + -i, --init 初始化配置文件 + Website: + github.com/Sheyiyuan/ProjectWIND + + For Developers: + -w, + ` + version string = `WIND v0.1.0` +) diff --git a/main.go b/main.go index 095d7bc..abb8261 100644 --- a/main.go +++ b/main.go @@ -1,175 +1,46 @@ package main import ( - "ProjectWIND/protocol" - "ProjectWIND/typed" - "encoding/json" - "errors" "fmt" - "io" - "log" "os" ) -func init() { - // 初始化日志记录器 - log.SetFlags(log.Ldate | log.Ltime) - log.SetPrefix("[WIND] ") - - // 检查并创建必要的目录和文件 - if _, err := os.Stat("./data/"); os.IsNotExist(err) { - // 如果不存在,则创建该文件夹 - err := os.Mkdir("./data/", 0755) - if err != nil { - log.Fatal(err) - } - } - - // 检查./data/文件夹中是否存在config.json文件 - if _, err := os.Stat("./data/config.json"); os.IsNotExist(err) { - // 如果不存在,则创建该文件 - file, err := os.Create("./data/config.json") - if err != nil { - log.Fatal(err) - } - defer func(file *os.File) { - err := file.Close() - if err != nil { - log.Fatal(err) - } - }(file) - } - // 检查并更新配置文件 - err := checkAndUpdateConfig("./data/config.json") - if err != nil { - log.Fatal(err) - } - - // 检查./data/文件夹中是否存在app/文件夹 - if _, err := os.Stat("./data/app/"); os.IsNotExist(err) { - // 如果不存在,则创建该文件夹 - err := os.Mkdir("./data/app/", 0755) - if err != nil { - log.Fatal(err) - } - } - - // 检查./data/文件夹中是否存在database/文件夹 - if _, err := os.Stat("./data/database/"); os.IsNotExist(err) { - // 如果不存在,则创建该文件夹 - err := os.Mkdir("./data/database/", 0755) - if err != nil { - log.Fatal(err) - } - } - - // 检查./data/文件夹中是否存在log/文件夹 - if _, err := os.Stat("./data/log/"); os.IsNotExist(err) { - // 如果不存在,则创建该文件夹 - err := os.Mkdir("./data/log/", 0755) - if err != nil { - log.Fatal(err) - } - } -} - func main() { - //读取参数 - if len(os.Args) == 1 || os.Args[0] == "help" || os.Args[0] == "-h" || os.Args[0] == "--help" { - fmt.Println(`Usage: input command "start"or"-s" to start the server.`) + //如果没有参数,则启动WebUI + if len(os.Args) <= 1 { + startWebUI() return } - command := os.Args[1] - switch command { - case "start": - case "-s": - { - log.Println("Starting ProjectWIND...") - // 启动 WebSocket 处理程序 - log.Println("Starting WebSocket handler...") - _, err := protocol.WebSocketHandler() - if err != nil { - // 如果发生错误,记录错误并退出程序 - log.Fatal(err) - } - return - } - default: - { - fmt.Println("Invalid command.") - return - } + cmdArgs := os.Args[1:] + if cmdArgs[0] == "-h" || cmdArgs[0] == "--help" { + fmt.Printf("%v\n", helpDoc) + return } -} -func checkAndUpdateConfig(configPath string) error { - var config typed.ConfigInfo - // 定义默认配置 - var defaultConfig typed.ConfigInfo - defaultConfig.CoreName = "windCore" - defaultConfig.WebUIPort = 3211 - defaultConfig.ProtocolAddr = make(map[string]string) - defaultConfig.ServiceName = "wind" - // 读取配置文件 - file, err := os.Open(configPath) - if err != nil { - return err - } - defer func(file *os.File) { - err := file.Close() - if err != nil { - log.Printf("Failed to close config file: %v", err) - } - }(file) - - // 解码JSON配置 - decoder := json.NewDecoder(file) - err = decoder.Decode(&config) - if err != nil { - if !errors.Is(err, io.EOF) { - return err - } - } - - // 检查并更新配置 - if config.ProtocolAddr == nil { - config.ProtocolAddr = defaultConfig.ProtocolAddr - } - if config.WebUIPort == 0 { - config.WebUIPort = defaultConfig.WebUIPort - } - if config.CoreName == "" { - config.CoreName = defaultConfig.CoreName - } - if config.ServiceName == "" { - config.ServiceName = defaultConfig.ServiceName - } - if config.PasswordHash == "" { - config.PasswordHash = "" - } - - formattedJSON, err := json.MarshalIndent(config, "", " ") - if err != nil { - fmt.Println("Error formatting JSON:", err) - return err - } - - // 将格式化后的JSON字符串写入文件 - file, err = os.Create("./data/config.json") - if err != nil { - fmt.Println("Error creating file:", err) - return err - } - defer func(file *os.File) { - err := file.Close() - if err != nil { - log.Printf("Failed to close config file: %v", err) - } - }(file) - - _, err = file.Write(formattedJSON) - if err != nil { - fmt.Println("Error writing to file:", err) - return err - } - return nil + if cmdArgs[0] == "-r" || cmdArgs[0] == "--run" { + // 启动服务 + startWebUI() + return + } + if cmdArgs[0] == "-i" || cmdArgs[0] == "--init" { + // 初始化项目 + initCore() + return + } + if cmdArgs[0] == "-v" || cmdArgs[0] == "--version" { + // 显示版本信息 + fmt.Printf(`%v\n`, version) + return + } + if cmdArgs[0] == "-s" || cmdArgs[0] == "--service" { + // 注册Linux服务并启动 + registerService() + return + } + if cmdArgs[0] == "-p" || cmdArgs[0] == "--protocol" { + // 连接到协议端 + startProtocol() + return + } + fmt.Println("Invalid command.") + return } diff --git a/protocol/api.go b/protocol/api.go index f407993..2d49f86 100644 --- a/protocol/api.go +++ b/protocol/api.go @@ -31,7 +31,7 @@ func SendMessage(messageType string, message string, targetId int64, autoEscape return false, err } // 发送消息 - _, err = wsSendMessage(messageJson) + err = wsSendMessage(messageJson) if err != nil { return false, err } diff --git a/protocol/web_socket.go b/protocol/web_socket.go index 1e48b4e..576a840 100644 --- a/protocol/web_socket.go +++ b/protocol/web_socket.go @@ -9,14 +9,16 @@ import ( "github.com/gorilla/websocket" ) -const ( - severURL = "your_server_url" -) +var gProtocolAddr string -func WebSocketHandler() (*websocket.Conn, error) { - u, err := url.Parse(severURL) +// WebSocketHandler 接收WebSocket连接处的消息并处理 +func WebSocketHandler(protocolAddr string) (*websocket.Conn, error) { + // 保存全局变量 + gProtocolAddr = protocolAddr + // 解析连接URL + u, err := url.Parse(protocolAddr) if err != nil { - log.Println("Parse URL error:", err) + log.Println("[ERROR] Parse URL error:", err) return nil, err } @@ -47,6 +49,7 @@ func WebSocketHandler() (*websocket.Conn, error) { return conn, nil } +// processMessage 处理接收到的消息 func processMessage(messageType int, message []byte) { if messageType != websocket.TextMessage { log.Println("[INFO] Invalid message type:", messageType) @@ -95,17 +98,17 @@ func processMessage(messageType int, message []byte) { } // wsSendMessage 向WebSocket服务器发送消息并返回发送状态 -func wsSendMessage(message []byte) (bool, error) { +func wsSendMessage(message []byte) error { // 解析连接URL - u, err := url.Parse(fmt.Sprintf("%v/api", severURL)) + u, err := url.Parse(fmt.Sprintf("%v/api", gProtocolAddr)) if err != nil { - return false, fmt.Errorf("无效的URL: %v", err) + return fmt.Errorf("无效的URL: %v", err) } // 建立连接 conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil) if err != nil { - return false, fmt.Errorf("连接失败: %v", err) + return fmt.Errorf("连接失败: %v", err) } defer func(conn *websocket.Conn) { err := conn.Close() @@ -117,8 +120,8 @@ func wsSendMessage(message []byte) (bool, error) { // 发送消息 err = conn.WriteMessage(websocket.TextMessage, message) if err != nil { - return false, fmt.Errorf("发送消息失败: %v", err) + return fmt.Errorf("发送消息失败: %v", err) } - return true, nil + return nil } diff --git a/typed/typed.go b/typed/typed.go index a569949..beb9587 100644 --- a/typed/typed.go +++ b/typed/typed.go @@ -1,11 +1,11 @@ package typed type ConfigInfo struct { - CoreName string `json:"core_name"` - ProtocolAddr map[string]string `json:"protocol_addr"` - WebUIPort uint16 `json:"webui_port"` - PasswordHash string `json:"password_hash"` - ServiceName string `json:"service_name"` + CoreName string `json:"core_name"` + ProtocolAddr string `json:"protocol_addr"` + WebUIPort uint16 `json:"webui_port"` + PasswordHash string `json:"password_hash"` + ServiceName string `json:"service_name"` } type MessageEventInfo struct { diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..668aa33 --- /dev/null +++ b/utils.go @@ -0,0 +1,293 @@ +package main + +import ( + "ProjectWIND/protocol" + "ProjectWIND/typed" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "os" + "time" +) + +func initCore() string { + // 初始化日志记录器 + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + log.SetPrefix("[WIND] ") + + log.Println("[INFO] 正在初始化WIND配置文件...") + + err := checkAndUpdateConfig("./data/config.json") + if err != nil { + log.Fatal(err) + } + // 创建日志文件 + logFile := fmt.Sprintf("./data/log/WIND_CORE_%s.log", time.Now().Format("20060102150405")) + _, err = os.Stat(logFile) + if os.IsNotExist(err) { + file, err := os.Create(logFile) + if err != nil { + log.Fatalf("[ERROR] Failed to create log file: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close log file: %v", err) + } + }(file) + } + + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + log.Fatalf("[ERROR] Failed to create log file: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close log file: %v", err) + } + }(file) + + // 设置日志输出到文件 + log.SetOutput(io.MultiWriter(os.Stdout, file)) + log.Println("[INFO] WIND配置文件初始化完成!") + return logFile +} + +func checkAndUpdateConfig(configPath string) error { + // 检查并创建必要的目录和文件 + if _, err := os.Stat("./data/"); os.IsNotExist(err) { + // 如果不存在,则创建该文件夹 + err := os.Mkdir("./data/", 0755) + if err != nil { + log.Fatal(err) + } + } + + // 检查./data/文件夹中是否存在config.json文件 + if _, err := os.Stat("./data/config.json"); os.IsNotExist(err) { + // 如果不存在,则创建该文件 + file, err := os.Create("./data/config.json") + if err != nil { + log.Fatal(err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Fatal(err) + } + }(file) + } + + // 检查并更新配置文件 + var config typed.ConfigInfo + + // 定义默认配置 + var defaultConfig typed.ConfigInfo + defaultConfig.CoreName = "windCore" + defaultConfig.WebUIPort = 3211 + defaultConfig.ProtocolAddr = "" + defaultConfig.ServiceName = "wind" + // 读取配置文件 + file, err := os.Open(configPath) + if err != nil { + return err + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close config file: %v", err) + } + }(file) + + // 解码JSON配置 + decoder := json.NewDecoder(file) + err = decoder.Decode(&config) + if err != nil { + if !errors.Is(err, io.EOF) { + return err + } + } + + // 检查并更新配置 + if config.ProtocolAddr == "" { + config.ProtocolAddr = defaultConfig.ProtocolAddr + } + if config.WebUIPort == 0 { + config.WebUIPort = defaultConfig.WebUIPort + } + if config.CoreName == "" { + config.CoreName = defaultConfig.CoreName + } + if config.ServiceName == "" { + config.ServiceName = defaultConfig.ServiceName + } + if config.PasswordHash == "" { + config.PasswordHash = "" + } + + formattedJSON, err := json.MarshalIndent(config, "", " ") + if err != nil { + return err + } + + // 将格式化后的JSON字符串写入文件 + file, err = os.Create("./data/config.json") + if err != nil { + log.Println("Error creating file:", err) + return err + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("Failed to close config file: %v", err) + } + }(file) + + _, err = file.Write(formattedJSON) + if err != nil { + log.Println("[ERROR] Error writing to file:", err) + return err + } + + // 检查./data/文件夹中是否存在app/文件夹 + if _, err := os.Stat("./data/app/"); os.IsNotExist(err) { + // 如果不存在,则创建该文件夹 + err := os.Mkdir("./data/app/", 0755) + if err != nil { + return err + } + } + + // 检查./data/文件夹中是否存在images/文件夹 + if _, err := os.Stat("./data/images/"); os.IsNotExist(err) { + // 如果不存在,则创建该文件夹 + err := os.Mkdir("./data/images/", 0755) + if err != nil { + return err + } + } + + // 检查./data/文件夹中是否存在database/文件夹 + if _, err := os.Stat("./data/database/"); os.IsNotExist(err) { + // 如果不存在,则创建该文件夹 + err := os.Mkdir("./data/database/", 0755) + if err != nil { + return err + } + } + + // 检查./data/文件夹中是否存在log/文件夹 + if _, err := os.Stat("./data/log/"); os.IsNotExist(err) { + // 如果不存在,则创建该文件夹 + err := os.Mkdir("./data/log/", 0755) + if err != nil { + return err + } + } + + return nil +} + +func startWebUI() { + { + //初始化 + logFile := initCore() + // 设置日志输出到文件 + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + log.SetPrefix("[WIND] ") + // 打开日志文件 + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + log.Fatalf("[ERROR] Failed to create log file: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close log file: %v", err) + } + }(file) + // 设置日志输出到文件 + log.SetOutput(io.MultiWriter(os.Stdout, file)) + + log.Println("[INFO] 正在启动WIND核心服务...") + // 启动 WebSocket 处理程序 + + //TODO: 这里要添加webUI的启动代码 + } +} + +func registerService() { + //初始化 + logFile := initCore() + // 设置日志输出到文件 + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + log.SetPrefix("[WIND] ") + // 打开日志文件 + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + log.Fatalf("[ERROR] Failed to create log file: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close log file: %v", err) + } + }(file) + // 设置日志输出到文件 + log.SetOutput(io.MultiWriter(os.Stdout, file)) + //TODO: 这里要添加注册服务的代码 +} + +func startProtocol() { + //初始化 + logFile := initCore() + // 设置日志输出到文件 + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + log.SetPrefix("[WIND] ") + // 打开日志文件 + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + log.Fatalf("[ERROR] Failed to create log file: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close log file: %v", err) + } + }(file) + // 设置日志输出到文件 + log.SetOutput(io.MultiWriter(os.Stdout, file)) + //从配置文件中读取配置信息 + log.Println("[INFO] 正在启动WIND协议服务...") + var config typed.ConfigInfo + file, err = os.Open("./data/config.json") + if err != nil { + log.Printf("[ERROR] Failed to open config file when linking to protocol: %v", err) + } + defer func(file *os.File) { + err := file.Close() + if err != nil { + log.Printf("[ERROR] Failed to close config file: %v", err) + } + }(file) + + decoder := json.NewDecoder(file) + err = decoder.Decode(&config) + if err != nil { + log.Printf("[ERROR] Failed to decode config file when linking to protocol: %v", err) + } + //获取协议地址 + protocolAddr := config.ProtocolAddr + //链接协议 + // 启动 WebSocket 处理程序 + log.Println("[INFO] 正在启动WebSocket链接程序...") + _, err = protocol.WebSocketHandler(protocolAddr) + if err != nil { + // 如果发生错误,记录错误并退出程序 + log.Fatal(err) + } + return +}