Procházet zdrojové kódy

d01 Переход на модель rpc

SVI před 3 roky
rodič
revize
14bfd332ee

+ 74 - 0
desktop/client_serv/client_serv.go

@@ -0,0 +1,74 @@
+// package client_serv -- клиент подключения к бото-серверу
+package client_serv
+
+import (
+	"fmt"
+	"log"
+	"net/rpc"
+
+	"wartank/server/serv_rpc"
+)
+
+// ClientServ -- клиент подключения к бото-серверу
+type ClientServ struct {
+	client *rpc.Client
+	url    string
+}
+
+// NewClientServ -- возвращает новый клиент к бото-серверу
+func NewClientServ() *ClientServ {
+	sf := &ClientServ{}
+	return sf
+}
+
+// Connect -- подключает клиента к бото-серверу
+func (sf *ClientServ) Connect(url_ string) error {
+	sf.url = url_
+	var err error
+	sf.client, err = rpc.DialHTTP("tcp", url_)
+	if err != nil {
+		return fmt.Errorf("ClientSrv.Connect(): in connect to bot-server, err=\n\t%w", err)
+	}
+	req := &serv_rpc.EchoReq{}
+	resp := &serv_rpc.EchoResp{}
+	err = sf.client.Call("ServRpc.Echo", req, &resp)
+	if err != nil {
+		return fmt.Errorf("ClientServ.Connect(): in make Echo-request to bot-server, err=\n\t%w", err)
+	}
+	if resp.Result != "WarTank!" {
+		return fmt.Errorf("ClientServ.Connect(): bad response on Echo request(%v!='WarTank!')", resp.Result)
+	}
+	return nil
+}
+
+// Login -- логинится на сервер
+func (sf *ClientServ) Login(login, pass string) error {
+	log.Println("ClientServ.Login()")
+	req := &serv_rpc.LoginReq{
+		Login: login,
+		Pass:  pass,
+	}
+	resp := &serv_rpc.LoginResp{}
+	err := sf.client.Call("ServRpc.Login", req, resp)
+	if err != nil {
+		return fmt.Errorf("ClientServ.Login(): err=\n\t%w", err)
+	}
+	if resp.Result != "ok" {
+		return fmt.Errorf("ClientServ.Login(): resp=%q", resp.Result)
+	}
+	return nil
+}
+
+// MakeAdmin -- создаёт админа на сервере
+func (sf *ClientServ) MakeAdmin(pass string) error {
+	log.Println("ClientServ.MakeAdmin()")
+	req := &serv_rpc.MakeAdminReq{
+		Pass: pass,
+	}
+	resp := &serv_rpc.MakeAdminResp{}
+	err := sf.client.Call("ServRpc.MakeAdmin", req, resp)
+	if err != nil {
+		return fmt.Errorf("ClientServ.MakeAdmin(): in make request, err=\n\t%w", err)
+	}
+	return nil
+}

+ 162 - 78
desktop/desktop.go

@@ -8,24 +8,33 @@ import (
 
 	"github.com/charmbracelet/bubbles/textinput"
 	tea "github.com/charmbracelet/bubbletea"
+
+	"wartank/desktop/client_serv"
 )
 
 // Desktop -- консольный клиент для вар-танка
 type Desktop struct {
 	TeaModel
-	p *tea.Program // Объект приложения
+	p         *tea.Program            // Объект приложения
+	client    *client_serv.ClientServ // Клиент подключния к бото-серверу
+	isConnect bool                    // Признак подключения к бот-серверу
+	isLogin   bool                    // Признак логина на сервер
 }
 
+var desk *Desktop
+
 func NewDesktop() *Desktop {
-	sf := &Desktop{}
+	sf := &Desktop{
+		client: client_serv.NewClientServ(),
+	}
 	sf.TeaModel = NewModel()
 	go sf.tick()
 	sf.p = tea.NewProgram(sf, tea.WithAltScreen(), tea.WithANSICompressor())
+	desk = sf
 	if _, err := sf.p.Run(); err != nil {
 		fmt.Printf("Опа! здесь какая-то ошибочка: %v", err)
 		os.Exit(1)
 	}
-
 	return sf
 }
 
@@ -40,6 +49,8 @@ const (
 	ModeInputLoginServer       // Режим ввода логина на сервер
 	ModeInputPassServer        // Режим ввода пароля входа на сервер
 	ModeConnectServer          // Режим подключения к серверу
+	ModeLoginServer            // Режим логина на сервер
+	ModeServerMakeAdmin        // Создать админа для бот-сервера
 )
 
 type TeaModel struct {
@@ -98,29 +109,29 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			return sf, tea.Quit
 		}
 	}
-	switch sf.mode {
+	switch desk.mode {
 	case ModeDefault:
 		switch msg := msg.(type) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
 			case "up", "k": // Если "up" или "k" перемещение курсора вверх
-				if sf.cursor > 0 {
-					sf.cursor--
+				if desk.cursor > 0 {
+					desk.cursor--
 				}
 			case "down", "j": // Если "down" или "j" перемещение курсора вниз
-				if sf.cursor < len(sf.choices)-1 {
-					sf.cursor++
+				if desk.cursor < len(desk.choices)-1 {
+					desk.cursor++
 				}
 			case "enter", " ": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
-				_, ok := sf.selected[sf.cursor]
+				_, ok := desk.selected[desk.cursor]
 				if ok {
-					delete(sf.selected, sf.cursor)
+					delete(desk.selected, desk.cursor)
 				} else {
-					sf.selected[sf.cursor] = struct{}{}
+					desk.selected[desk.cursor] = struct{}{}
 				}
 			case "w": // Настройки графического клиента
-				sf.mode = ModeConfig
+				desk.mode = ModeConfig
 			}
 		}
 	case ModeConfig:
@@ -128,12 +139,20 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeDefault
+			case "esc": // Вернуться на шаг назад
+				desk.mode = ModeDefault
 			case "1": // Выбор один
-				sf.mode = ModeConfigServer
+				desk.mode = ModeConfigServer
 			case "2": // Вход на сервер
-				sf.mode = ModeConnectServer
+				if !desk.isConnect {
+					desk.mode = ModeConnectServer
+				}
+			case "3": // Логин на сервер
+				if !desk.isLogin {
+					desk.mode = ModeLoginServer
+				}
+			case "4": // Создать админа
+				desk.mode = ModeServerMakeAdmin
 			}
 		}
 	case ModeConfigServer:
@@ -141,20 +160,20 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeConfig
+			case "esc": // Вернуться на шаг назад
+				desk.mode = ModeConfig
 			case "1": // Выбор хоста сервера
-				sf.mode = ModeInputHostServer
-				sf.textInput.Reset()
-				sf.textInput.Placeholder = "localhost:18050"
+				desk.mode = ModeInputHostServer
+				desk.textInput.Reset()
+				desk.textInput.Placeholder = "localhost:18050"
 			case "2": // Выбор логина для входа
-				sf.mode = ModeInputLoginServer
-				sf.textInput.Reset()
-				sf.textInput.Placeholder = "login"
+				desk.mode = ModeInputLoginServer
+				desk.textInput.Reset()
+				desk.textInput.Placeholder = "login"
 			case "3": // Выбор пароля для входа
-				sf.mode = ModeInputPassServer
-				sf.textInput.Reset()
-				sf.textInput.Placeholder = "pass"
+				desk.mode = ModeInputPassServer
+				desk.textInput.Reset()
+				desk.textInput.Placeholder = "pass"
 			}
 		}
 	case ModeInputHostServer:
@@ -162,13 +181,13 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeConfigServer
+			case "esc": // Вернуться на шаг назад
+				desk.mode = ModeConfigServer
 			case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
-				sf.host = sf.textInput.Value()
-				sf.mode = ModeConfigServer
+				desk.host = desk.textInput.Value()
+				desk.mode = ModeConfigServer
 			default:
-				sf.textInput, cmd = sf.textInput.Update(msg)
+				desk.textInput, cmd = desk.textInput.Update(msg)
 			}
 		}
 	case ModeInputLoginServer:
@@ -176,13 +195,13 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeConfigServer
+			case "esc": // Вернуться на шаг назад
+				desk.mode = ModeConfigServer
 			case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
-				sf.login = sf.textInput.Value()
-				sf.mode = ModeConfigServer
+				desk.login = desk.textInput.Value()
+				desk.mode = ModeConfigServer
 			default:
-				sf.textInput, cmd = sf.textInput.Update(msg)
+				desk.textInput, cmd = desk.textInput.Update(msg)
 			}
 		}
 	case ModeInputPassServer:
@@ -190,13 +209,13 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeConfigServer
+			case "esc": // Вернуться на шаг назад
+				desk.mode = ModeConfigServer
 			case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
-				sf.pass = sf.textInput.Value()
-				sf.mode = ModeConfigServer
+				desk.pass = desk.textInput.Value()
+				desk.mode = ModeConfigServer
 			default:
-				sf.textInput, cmd = sf.textInput.Update(msg)
+				desk.textInput, cmd = desk.textInput.Update(msg)
 			}
 		}
 	case ModeConnectServer:
@@ -204,98 +223,163 @@ func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		// Может клавиша нажата
 		case tea.KeyMsg:
 			switch msg.String() { // Да, нажато, а что именно?
-			case "q": // Вернуться на шаг назад
-				sf.mode = ModeConfigServer
-			case "esc": // Нажатие "esc" или "пробел" прекращает подключение к серверу
-				sf.pass = sf.textInput.Value()
-				sf.mode = ModeConfigServer
-			default:
-				sf.textInput, cmd = sf.textInput.Update(msg)
+			case "esc": // Нажатие "esc" прекращает подключение к серверу
+				desk.mode = ModeConfigServer
+			}
+		}
+	case ModeLoginServer:
+		switch msg := msg.(type) {
+		// Может клавиша нажата
+		case tea.KeyMsg:
+			switch msg.String() { // Да, нажато, а что именно?
+			case "esc": // Нажатие "esc" прекращает логин на сервер
+				desk.mode = ModeConfig
+			}
+		}
+	case ModeServerMakeAdmin:
+		switch msg := msg.(type) {
+		// Может клавиша нажата
+		case tea.KeyMsg:
+			switch msg.String() { // Да, нажато, а что именно?
+			case "esc": // Нажатие "esc" прекращает логин на сервер
+				desk.mode = ModeConfig
 			}
 		}
 	}
-
 	// Возвращает обновлённую модель дляe Bubble Tea runtime для обработки.
 	//Здесь команду возвращать надо.
 
-	return sf, cmd
+	return desk, cmd
 }
 
 func (sf Desktop) View() string {
 	s := time.Now().Local().Format("[ WarTank ] = 2006-01-02 15:04:05.000")
-	s += fmt.Sprintf("\tХост=%q\tЛогин=%q\tПароль=%q\n\n", sf.host, sf.login, sf.pass)
-	switch sf.mode {
+	s += fmt.Sprintf("\tХост=%q\tЛогин=%q\tПароль=%q\tПодключено=%v\tЛогин=%v\n\n", desk.host, desk.login, desk.pass, desk.isConnect, desk.isLogin)
+	switch desk.mode {
 	case ModeDefault: // Исходное содержимое
-		s += sf.winDefault()
+		s += desk.winDefault()
 	case ModeConfig: // Показать настройки клиента
-		s += sf.winConfig()
+		s += desk.winConfig()
 	case ModeConfigServer: // Конфигурация сервера
-		s += sf.winConfigServer()
+		s += desk.winConfigServer()
 	case ModeInputHostServer: // Ввод хоста для сервера
-		s += sf.winHostServer()
+		s += desk.winHostServer()
 	case ModeInputLoginServer: // Ввод логина для входа на сервер
-		s += sf.winLoginServer()
+		s += desk.winLoginServer()
 	case ModeInputPassServer: // ввод пароля
-		s += sf.winPassServer()
+		s += desk.winPassServer()
+	case ModeConnectServer: // Режим подключения к серверу
+		s += desk.winConnectServer()
+	case ModeLoginServer: // Режим логина на сервер
+		s += desk.winServerLogin()
+	case ModeServerMakeAdmin: // Режим содания админа на бот-сервере
+		s += desk.winServerMakeAdmin()
 	}
 
 	return s
 }
 
-func (sf Desktop) winPassServer() string {
-	s := "=Ввод пароля для сервера вар-танк=\n\n"
-	s += fmt.Sprintf(">%v\n", sf.textInput.View())
-	s += "\n\n[ctrl+q]-выход [q]-назад\n"
+func (sf *Desktop) winServerMakeAdmin() string {
+	s := "=Создание админа на бот-сервере вар-танк=\n\n"
+	err := desk.client.MakeAdmin(desk.pass)
+	if err != nil {
+		s += fmt.Sprintf("Desktop.winServerMakeAdmin(): err=\n\t%v", err)
+		s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
+		return s
+	}
+	s += "Desktop.winServerMakeAdmin(): ok\n"
+	desk.isLogin = true
+	s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
 	return s
 }
 
-func (sf Desktop) winLoginServer() string {
+func (sf *Desktop) winServerLogin() string {
+	s := "=Логин на бот-сервер вар-танк=\n\n"
+	err := desk.client.Login(desk.login, desk.pass)
+	if err != nil {
+		s += fmt.Sprintf("Desktop.winServerLogin(): err=\n\t%v", err)
+		s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
+		return s
+	}
+	s += "Desktop.winServerLogin(): ok\n"
+	desk.isLogin = true
+	s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
+	return s
+}
+
+func (sf *Desktop) winConnectServer() string {
+	s := "=Подключение к бот-серверу вар-танк=\n\n"
+	if !desk.isConnect {
+		err := desk.client.Connect(desk.host)
+		if err != nil {
+			s += fmt.Sprintf("Desktop.winConnectServer(): err=\n\t%v", err)
+			s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
+			return s
+		}
+	}
+	s += "Desktop.winConnectServer(): ok\n"
+	desk.isConnect = true
+	s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
+	return s
+}
+
+func (sf *Desktop) winPassServer() string {
+	s := "=Ввод пароля для бот-сервера вар-танк=\n\n"
+	s += fmt.Sprintf(">%v\n", desk.textInput.View())
+	s += "\n\n[ctrl+q]-выход [esc]-назад\n"
+	return s
+}
+
+func (sf *Desktop) winLoginServer() string {
 	s := "=Ввод логина для сервера вар-танк=\n\n"
-	s += fmt.Sprintf(">%v\n", sf.textInput.View())
-	s += "\n\n[ctrl+q]-выход [q]-назад\n"
+	s += fmt.Sprintf(">%v\n", desk.textInput.View())
+	s += "\n\n[ctrl+q]-выход [esc]-назад\n"
 	return s
 }
 
-func (sf Desktop) winHostServer() string {
+func (sf *Desktop) winHostServer() string {
 	s := "=Ввод хоста для сервера вар-танк=\n\n"
-	s += fmt.Sprintf(">%v\n", sf.textInput.View())
-	s += "\n\n[ctrl+q]-выход [q]-назад\n"
+	s += fmt.Sprintf(">%v\n", desk.textInput.View())
+	s += "\n\n[ctrl+q]-выход [esc]-назад\n"
 	return s
 }
-func (sf Desktop) winConfigServer() string {
+
+func (sf *Desktop) winConfigServer() string {
 	s := "Настройки сервера вар-танк\n\n"
 	s += "[1]-Настройки хоста сервера\n"
 	s += "[2]-Логин для входа\n"
 	s += "[3]-Пароль для входа\n"
-	s += "\n\n[ctrl+q]-выход [q]-назад\n"
+	s += "\n\n[ctrl+q]-выход [esc]-назад\n"
 	return s
 }
 
-func (m TeaModel) winConfig() string {
+func (sf *Desktop) winConfig() string {
 	s := "Настройки клиента\n\n"
 	s += "[1]-Настройки сервера\n"
 	s += "[2]-Вход на сервер\n"
-	s += "\n\n[ctrl+q]-выход [q]-назад\n"
+	s += "[3]-Логин на сервер\n"
+	s += "[4]-Сделать админа на бот-сервере\n"
+	s += "\n\n[ctrl+q]-выход [esc]-назад\n"
 	return s
 }
 
-func (m TeaModel) winDefault() string {
+func (sf *Desktop) winDefault() string {
 	// Заголовок
 	s := "Что нам нужно сделать?\n\n"
 
 	// Перебор по списку выбора
-	for i, choice := range m.choices {
+	for i, choice := range desk.choices {
 
 		// Курсор указывает на этот выбор?
 		cursor := " " // нет курсора
-		if m.cursor == i {
+		if desk.cursor == i {
 			cursor = ">" // есть курсор
 		}
 
 		// Этот элемент выбран?
 		checked := " " // не выбран
-		if _, ok := m.selected[i]; ok {
-			checked = "x" // выбран!
+		if _, ok := desk.selected[i]; ok {
+			checked = "+" // выбран!
 		}
 
 		// отрендерить заново

+ 0 - 8
pkg/mock/mockapp/mockapp.go

@@ -14,7 +14,6 @@ type MockApp struct {
 	bot      types.IWarBot
 	store    types.IStore
 	block    *sync.RWMutex
-	ServWeb_ types.IServWeb
 }
 
 func NewMockApp() *MockApp {
@@ -45,9 +44,6 @@ func (sf *MockApp) CtxApp() context.Context {
 	return sf.ctx
 }
 
-func (sf *MockApp) GuiWeb() types.IGuiWeb {
-	return nil
-}
 func (sf *MockApp) Tank() types.ITank {
 	return nil
 }
@@ -68,10 +64,6 @@ func (sf *MockApp) NetClient() types.IBotNet {
 	return nil
 }
 
-func (sf *MockApp) ServWeb() types.IServWeb {
-	return sf.ServWeb_
-}
-
 func (sf *MockApp) ServBots() types.IServBots {
 	return nil
 }

+ 0 - 15
pkg/types/iguiweb.go

@@ -1,15 +0,0 @@
-package types
-
-import (
-	"github.com/gofiber/fiber/v2"
-)
-
-/*
-	Интерфейс к веб-морде
-*/
-
-// IGuiWeb -- интерфейс к веб-морде
-type IGuiWeb interface {
-	// Router -- возвращает роутер
-	Router() *fiber.App
-}

+ 0 - 11
pkg/types/iserv_web.go

@@ -1,11 +0,0 @@
-package types
-
-import "github.com/gofiber/fiber/v2"
-
-// IServWeb -- интерфейс к веб-серверу
-type IServWeb interface {
-	// Router -- возвращае тссылку на роутер веб-сервера
-	Router() *fiber.App
-	// Run -- запускает сервер в работу
-	Run() error
-}

+ 0 - 2
pkg/types/iserver.go

@@ -11,8 +11,6 @@ type IServer interface {
 	Store() IStore
 	// Run -- запускает приложение в работу
 	Run() error
-	// ServWeb -- возвращает ссылку на веб-сервер
-	ServWeb() IServWeb
 	// ServBots -- словарь имеющихся ботов
 	ServBots() IServBots
 }

+ 116 - 0
server/serv_rpc/serv_rpc.go

@@ -0,0 +1,116 @@
+// package serv_rpc -- сервер RPC-запросов
+package serv_rpc
+
+import (
+	"fmt"
+	"log"
+	"net"
+	"net/http"
+	"net/rpc"
+
+	"wartank/pkg/types"
+)
+
+type ServRpc struct {
+	serv types.IServer
+}
+
+// NewServRpc -- возвращает новый сервер RPC-запросов
+func NewServRpc(serv types.IServer) (*ServRpc, error) {
+	if serv == nil {
+		return nil, fmt.Errorf("NewServRpc(): IServer==nil")
+	}
+	sf := &ServRpc{
+		serv: serv,
+	}
+	return sf, nil
+}
+
+// Run -- запускает сервис в работу
+func (sf *ServRpc) Run() {
+	rpc.Register(sf)
+	rpc.HandleHTTP()
+	lister, err := net.Listen("tcp", ":18050")
+	if err != nil {
+		log.Printf("NewServRc(): listen error, err=\n\t%v\n", err)
+		sf.serv.CancelApp()
+		return
+	}
+	go http.Serve(lister, nil)
+}
+
+// EchoReq -- эхо запрос на сервер
+type EchoReq struct{}
+
+// EchoResp -- эхо ответ на запрос
+type EchoResp struct {
+	Result string
+}
+
+// Echo -- эхо запрос для клиента
+func (sf *ServRpc) Echo(req *EchoReq, resp *EchoResp) error {
+	log.Println("ServRpc.Echo()")
+	resp.Result = "WarTank!"
+	return nil
+}
+
+// LoginReq -- запрос на логин на сервер
+type LoginReq struct {
+	Login string
+	Pass  string
+}
+
+// LoginResp -- ответ на запрос логина
+//
+// Вернёт ошибку если:
+//  1. Нужно создать админа
+//  2. Неверная пара логин/пароль
+type LoginResp struct {
+	Result string
+}
+
+// Login -- запросвхода на сервер
+func (sf *ServRpc) Login(req *LoginReq, resp *LoginResp) error {
+	log.Println("ServRpc.Login()")
+	store := sf.serv.Store()
+	_, err := store.Get("/users/admin")
+	if err != nil {
+		return fmt.Errorf("ServRpc.Login(): not have admin")
+	}
+	binData, err := store.Get("/users/" + req.Login)
+	if err != nil {
+		return fmt.Errorf("ServRpc.Login(): bad account")
+	}
+	strPass := string(binData)
+	if req.Pass != strPass {
+		return fmt.Errorf("ServRpc.Login():  bad  account")
+	}
+	resp.Result = "ok"
+	return nil
+}
+
+// MakeAdminReq -- запрос насоздание админа
+type MakeAdminReq struct {
+	Pass string
+}
+
+// MakeAdminResp -- ответ на создание админа
+type MakeAdminResp struct {
+	Result string
+}
+
+// MakeAdmin -- создание админа на бот-сервере
+func (sf *ServRpc) MakeAdmin(req *MakeAdminReq, resp *MakeAdminResp) error {
+	log.Println("ServRpc.MakeAdmin()")
+	store := sf.serv.Store()
+	_, err := store.Get("/users/admin")
+	if err == nil {
+		return fmt.Errorf("ServRpc.Login(): admin already exists")
+	}
+	err = store.Put("/users/admin", req.Pass)
+	if err != nil {
+		return fmt.Errorf("ServRpc.Login(): in put admin to store, err=\n\t%w", err)
+	}
+	resp.Result = "ok"
+	return nil
+}

binární
server/serv_web.zip


+ 0 - 88
server/serv_web/serv_web.go

@@ -1,88 +0,0 @@
-// package serv_web -- сервер бота на файбере
-package serv_web
-
-import (
-	"fmt"
-	"log"
-	"os"
-	"sync"
-	"time"
-
-	"github.com/gofiber/fiber/v2"
-	// "github.com/gofiber/template/html"
-
-	"wartank/server/serv_web/web_api"
-
-	"wartank/pkg/types"
-)
-
-/*
-	Главный тип бота на файбере
-*/
-
-// ServWeb -- главный тип приложения
-type ServWeb struct {
-	app    types.IServer
-	api    *web_api.WebApi
-	router *fiber.App
-	block  *sync.RWMutex
-	port   string // Порт веб-сервера
-}
-
-// NewServWeb -- возвращае тновый *ServFiber
-func NewServWeb(app types.IServer) (serv *ServWeb, err error) {
-	fmt.Printf("NewServWeb()\n")
-	if app == nil {
-		return nil, fmt.Errorf("NewServWeb(): IApp is nil")
-	}
-	port := os.Getenv("SERVER_PORT")
-	if port == "" {
-		return nil, fmt.Errorf("NewServWeb(): env SERVER_PORT not set")
-	}
-	sf := &ServWeb{
-		app:   app,
-		block: &sync.RWMutex{},
-		port:  port,
-	}
-	// engine := html.New("./static/tmpl", "*.tmpl.html")
-	fiberConfig := fiber.Config{
-		ServerHeader:    "WarTank",
-		BodyLimit:       10 * 1024 * 1024,
-		Concurrency:     512,
-		ReadTimeout:     30 * time.Second,
-		WriteTimeout:    30 * time.Second,
-		IdleTimeout:     30 * time.Second,
-		ReadBufferSize:  20 * 1024,
-		WriteBufferSize: 20 * 1024,
-		AppName:         "WarTank",
-		Network:         fiber.NetworkTCP4,
-		// Views:           engine,
-	}
-	sf.router = fiber.New(fiberConfig)
-	// sf.router.Static("/static", "./static")
-	return sf, nil
-}
-
-// Run -- запускает бота в работу
-func (sf *ServWeb) Run() error {
-	log.Printf("ServWeb.Run()\n")
-	var err error
-	{
-		sf.api, err = web_api.NewWebApi(sf.app)
-		if err != nil {
-			return fmt.Errorf("ServWeb.Run(): in make WebApi, err=\n\t%w", err)
-		}
-	}
-
-	sf.api.Run()
-	log.Printf("ServWeb.Run(): listen\n")
-	if err := sf.router.Listen(":" + sf.port); err != nil {
-		panic(fmt.Errorf("ServWeb.Run(): in serving web, err=\n\t%w", err))
-	}
-	return nil
-}
-
-// Router -- возвращает роутер сервера
-func (sf *ServWeb) Router() *fiber.App {
-	return sf.router
-}

+ 0 - 183
server/serv_web/web_api/web_api.go

@@ -1,183 +0,0 @@
-// 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
-		}
-	}
-}

+ 5 - 10
server/server.go

@@ -8,14 +8,14 @@ import (
 	"wartank/pkg/store"
 	"wartank/pkg/types"
 	"wartank/server/serv_bots"
-	"wartank/server/serv_web"
+	"wartank/server/serv_rpc"
 )
 
 // Server -- главный тип приложения
 type Server struct {
 	*kernel.Kernel
 	store    types.IStore
-	servWeb  *serv_web.ServWeb
+	servRpc  *serv_rpc.ServRpc
 	servBots *serv_bots.ServBots
 }
 
@@ -36,9 +36,9 @@ func NewServer() (sf *Server, err error) {
 	if err != nil {
 		return nil, fmt.Errorf("NewServer(): in create ServBots, err=%w", err)
 	}
-	sf.servWeb, err = serv_web.NewServWeb(sf)
+	sf.servRpc, err = serv_rpc.NewServRpc(sf)
 	if err != nil {
-		return nil, fmt.Errorf("NewServer(): in make IServWeb, err=\n\t%w", err)
+		return nil, fmt.Errorf("NewServer(): in make IServRpc, err=\n\t%w", err)
 	}
 	return sf, nil
 }
@@ -55,7 +55,7 @@ func (sf *Server) Run() error {
 		return fmt.Errorf("Server.Run(): in load bots, err=\n\t%w", err)
 	}
 
-	go sf.servWeb.Run()
+	go sf.servRpc.Run()
 	<-sf.Done()
 	// if err := sf._erverWeb.Error(); err != nil {
 	// 	return fmt.Errorf("Server.Run(): in work IServHttp, err=\n\t%w", err)
@@ -66,11 +66,6 @@ func (sf *Server) Run() error {
 	return nil
 }
 
-// ServWeb -- возвращает веб-сервер
-func (sf *Server) ServWeb() types.IServWeb {
-	return sf.servWeb
-}
-
 // ServBots -- возвращает словарь ботов
 func (sf *Server) ServBots() types.IServBots {
 	return sf.servBots