// package web_api -- реализация API запросов в веб-сервер package web_api import ( "encoding/json" "fmt" "log" "sync" "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/websocket/v2" "wartank/pkg/types" ) // WebApi -- рализация веб-запросов type WebApi struct { server types.IServer store types.IStore } // NewWebApi -- возвращает новый WebApi func NewWebApi(server types.IServer) (*WebApi, error) { if server == nil { return nil, fmt.Errorf("NewWebApi(): IServer is nil") } sf := &WebApi{ server: server, store: server.Store(), } server.ServWeb().Router().Use("/api/ws", sf.fnWs) server.ServWeb().Router().Get("/api/ws", websocket.New(sf.fnWsRun)) return sf, nil } // Run -- заглушка к вызову func (sf *WebApi) Run() {} // fnWs -- апгрейдит веб-сокет func (sf *WebApi) fnWs(c *fiber.Ctx) error { if websocket.IsWebSocketUpgrade(c) { c.Locals("allowed", true) return c.Next() } return fiber.ErrUpgradeRequired } // fnWsRun -- запускает веб-сокет в работу func (sf *WebApi) fnWsRun(c *websocket.Conn) { // c.Locals is added to the *websocket.Conn log.Println(c.Locals("allowed")) // true log.Println(c.Params("id")) // 123 log.Println(c.Query("v")) // 1.0 log.Println(c.Cookies("session")) // "" // websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index var ( mt int dictReq = make(map[string]string) dictResp = make(map[string]string) binReq []byte err error block sync.Mutex ) fnWrite := func() (isOk bool) { defer block.Unlock() binResp, err := json.Marshal(dictResp) if err != nil { log.Println("WebApi.fnWsRun(): in marshall response, err=", err) return false } if err = c.WriteMessage(mt, binResp); err != nil { log.Println("WebApi.fnWsRun(): in write, err=", err) return false } return true } for { block.Lock() if mt, binReq, err = c.ReadMessage(); err != nil { log.Println("WebApi.fnWsRun(): in read, err=", err) return } dictResp = make(map[string]string) dictResp["err"] = "" err = json.Unmarshal(binReq, &dictReq) if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in unmarshall request, err=\n\t%v", err) if !fnWrite() { return } continue } topic, isOk := dictReq["topic"] if !isOk { dictResp["err"] = "WebApi.fnWsRun(): dictReq not have key `topic`" if !fnWrite() { return } continue } switch topic { case "/server/time": // Запрос времени сервера dictResp["/server/time"] = time.Now().UTC().Format("2006-01-02 15:04:05.000") case "/root/password/is_exists": _, err := sf.store.Get("/root/password/val") if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in get root password, err=\n\t%v", err) } else { dictResp["/root/password/is_exists"] = "true" } case "/root/password/set": strPass := dictReq["pass"] err := sf.store.Put("/root/password/val", strPass) if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in save root password, err=\n\t%v", err) } case "/root/password/check": // Проверка пароля рута binPass, err_ := sf.store.Get("/root/password/val") if err_ != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in get root password, err=\n\t%v", err_) } else { strPassRoot := string(binPass) strPassUser := dictReq["pass"] if strPassRoot != strPassUser { dictResp["err"] = "WebApi.fnWsRun(): bad root password" } } case "/bot/list/load": // Запрос списка ботов binBots, err := sf.store.Get("/bot/list") if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in get list bot from store, err=\n\t%v\n", err) } else { dictResp["/bot/list"] = string(binBots) } case "/bot/list/save": // Сохранение списка ботов strBotList := dictReq["binData"] err := sf.store.Put("/bot/list", strBotList) if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in save list bot to store, err=\n\t%v\n", err) } case "/store/put": // Поместить запись в хранилище key := dictReq["key"] val := dictReq["val"] err := sf.store.Put(key, val) if err != nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): in put key(%q) to store, err=\n\t%v\n", key, err) } case "/bot/status": // Получить статус бота name := dictReq["name"] bot := sf.server.ServBots().Get(name) if bot == nil { dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): unknown bit name (%q)", name) } else { dictResp["/bot/pass"] = bot.Pass() dictResp["/bot/name"] = bot.Name() dictResp["/bot/online"] = fmt.Sprint(bot.BotNet().IsOnline().Get()) dictResp["/bot/fuel"] = fmt.Sprint(bot.Angar().Fuel().Get()) dictResp["/bot/gold"] = fmt.Sprint(bot.Angar().Gold().Get()) angar := bot.Angar() base := angar.Base() bank := base.Bank() silverBot := bank.SilverBot() dictResp["/bot/silver"] = fmt.Sprint(silverBot.Get()) dictResp["/bank/silver-time"] = bot.Angar().Base().Bank().CountDown().String() dictResp["/bank/silver-mode"] = bot.Angar().Base().Bank().ModeCurrent().Work() dictResp["/angar/silver-all"] = fmt.Sprint(bot.Angar().SilverAll().Get()) dictResp["/bot/mine-time"] = bot.Angar().Base().Mine().CountDown().String() dictResp["/bot/mine-mode"] = bot.Angar().Base().Mine().ModeCurrent().Work() dictResp["/mine/ruda"] = fmt.Sprint(bot.Angar().Base().Mine().Ruda().Get()) } default: dictReq = make(map[string]string) dictResp["err"] = fmt.Sprintf("WebApi.fnWsRun(): unknown topic (%q)", topic) } if !fnWrite() { return } } }