desktop.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // package desktop -- консольный клиент для вар-танка
  2. package desktop
  3. import (
  4. "fmt"
  5. "time"
  6. "github.com/charmbracelet/bubbles/textinput"
  7. tea "github.com/charmbracelet/bubbletea"
  8. "wartank/desktop/client_serv"
  9. "wartank/desktop/win_config"
  10. "wartank/desktop/win_config_server"
  11. "wartank/desktop/win_config_server_host_input"
  12. "wartank/desktop/win_config_server_login_input"
  13. "wartank/desktop/win_default"
  14. "wartank/pkg/alias"
  15. "wartank/pkg/cons"
  16. "wartank/pkg/types"
  17. )
  18. // Desktop -- консольный клиент для вар-танка
  19. type Desktop struct {
  20. TeaModel
  21. winName alias.AWinName // Режим показа на экране
  22. p *tea.Program // Объект приложения
  23. client *client_serv.ClientServ // Клиент подключния к бото-серверу
  24. isConnect bool // Признак подключения к бот-серверу
  25. isLogin bool // Признак логина на сервер
  26. isMakeAdmin bool // Признак создания админа
  27. dictWin map[alias.AWinName]types.ITermWin // Список окон показа
  28. }
  29. var desk *Desktop
  30. func NewDesktop() (*Desktop, error) {
  31. sf := &Desktop{
  32. client: client_serv.NewClientServ(),
  33. dictWin: make(map[alias.AWinName]types.ITermWin),
  34. }
  35. sf.TeaModel = NewModel()
  36. sf.p = tea.NewProgram(sf, tea.WithAltScreen(), tea.WithANSICompressor())
  37. desk = sf
  38. { // Создание окон
  39. { // WinDefault
  40. winDefault, err := win_default.NewWinDefault(sf)
  41. if err != nil {
  42. return nil, fmt.Errorf("NewDesktop(): in create WinDefault, err=\n\t%w", err)
  43. }
  44. sf.dictWin[winDefault.Name()] = winDefault
  45. }
  46. { // WinConfig
  47. winConfig, err := win_config.NewWinConfig(sf)
  48. if err != nil {
  49. return nil, fmt.Errorf("NewDesktop(): in create WinConfig, err=\n\t%w", err)
  50. }
  51. sf.dictWin[winConfig.Name()] = winConfig
  52. }
  53. { // WinConfigServer
  54. winConfigServer, err := win_config_server.NewWinConfigServer(sf)
  55. if err != nil {
  56. return nil, fmt.Errorf("NewDesktop(): in create WinConfigServer, err=\n\t%w", err)
  57. }
  58. sf.dictWin[winConfigServer.Name()] = winConfigServer
  59. }
  60. { // WinConfigServerHostInput
  61. winConfigServerHostInput, err := win_config_server_host_input.NewWinConfigServerHostInput(sf)
  62. if err != nil {
  63. return nil, fmt.Errorf("NewDesktop(): in create WinConfigServerHostInput, err=\n\t%w", err)
  64. }
  65. sf.dictWin[winConfigServerHostInput.Name()] = winConfigServerHostInput
  66. }
  67. { // WinConfigServerLoginInput
  68. winConfigServerLoginInput, err := win_config_server_login_input.NewWinConfigServerLoginInput(sf)
  69. if err != nil {
  70. return nil, fmt.Errorf("NewDesktop(): in create WinConfigServerLoginInput, err=\n\t%w", err)
  71. }
  72. sf.dictWin[winConfigServerLoginInput.Name()] = winConfigServerLoginInput
  73. }
  74. }
  75. sf.winName = cons.WinDefault
  76. go sf.tick()
  77. return sf, nil
  78. }
  79. // SetWin -- устанавливает главное окно
  80. func (sf *Desktop) SetWin(winName alias.AWinName) {
  81. sf.winName = winName
  82. }
  83. type TeaModel struct {
  84. textInput textinput.Model
  85. host string // Имя хоста сервера (с портом)
  86. login string // Логин для сервера
  87. pass string // Пароль для сервера
  88. }
  89. func NewModel() TeaModel {
  90. ti := textinput.New()
  91. ti.Placeholder = "localhost"
  92. ti.Focus()
  93. ti.CharLimit = 156
  94. ti.Width = 20
  95. m := TeaModel{
  96. textInput: ti,
  97. }
  98. return m
  99. }
  100. func (sf *Desktop) tick() {
  101. for {
  102. time.Sleep(time.Second * 1)
  103. msg := tea.MouseEvent{}
  104. // m.Update(msg)
  105. sf.p.Send(msg)
  106. }
  107. }
  108. // Run -- запускает в работу консольный клиент
  109. func (sf *Desktop) Run() error {
  110. if _, err := sf.p.Run(); err != nil {
  111. return fmt.Errorf("Deskto.Run(): err=\n\t%w", err)
  112. }
  113. return nil
  114. }
  115. // Init -- инициализация перед запуском главного цикла
  116. func (sf *Desktop) Init() tea.Cmd {
  117. // Просто вернуть `nil`, т.е. никаких команд
  118. return textinput.Blink
  119. }
  120. // Update -- обновление консоли по требованию
  121. func (sf *Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  122. var cmd tea.Cmd
  123. switch msg := msg.(type) {
  124. // Может клавиша нажата
  125. case tea.KeyMsg:
  126. switch msg.String() { // Да, нажато, а что именно?
  127. case "ctrl+q": // Надо выйти из программы
  128. return sf, tea.Quit
  129. }
  130. }
  131. mod_, cmd_ := sf.dictWin[sf.winName].Update(msg)
  132. if mod_ != nil {
  133. return mod_, cmd_
  134. }
  135. /*
  136. case ModeInputPassServer:
  137. switch msg := msg.(type) {
  138. // Может клавиша нажата
  139. case tea.KeyMsg:
  140. switch msg.String() { // Да, нажато, а что именно?
  141. case "esc": // Вернуться на шаг назад
  142. desk.winName = ModeConfigServer
  143. case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
  144. desk.pass = desk.textInput.Value()
  145. desk.winName = ModeConfigServer
  146. default:
  147. desk.textInput, cmd = desk.textInput.Update(msg)
  148. }
  149. }
  150. case ModeConnectServer:
  151. switch msg := msg.(type) {
  152. // Может клавиша нажата
  153. case tea.KeyMsg:
  154. switch msg.String() { // Да, нажато, а что именно?
  155. case "esc": // Нажатие "esc" прекращает подключение к серверу
  156. desk.winName = ModeConfigServer
  157. }
  158. }
  159. case ModeLoginServer:
  160. switch msg := msg.(type) {
  161. // Может клавиша нажата
  162. case tea.KeyMsg:
  163. switch msg.String() { // Да, нажато, а что именно?
  164. case "esc": // Нажатие "esc" прекращает логин на сервер
  165. desk.winName = ModeConfig
  166. }
  167. }
  168. case ModeServerMakeAdmin:
  169. switch msg := msg.(type) {
  170. // Может клавиша нажата
  171. case tea.KeyMsg:
  172. switch msg.String() { // Да, нажато, а что именно?
  173. case "esc": // Нажатие "esc" прекращает создание админа
  174. desk.winName = ModeConfig
  175. }
  176. }
  177. case ModeShowMenuBot:
  178. // Может клавиша нажата
  179. switch msg := msg.(type) {
  180. case tea.KeyMsg:
  181. switch msg.String() { // Да, нажато, а что именно?
  182. case "esc": // Нажатие "esc" прекращает показ меню
  183. desk.winName = ModeConfig
  184. }
  185. }
  186. // Возвращает обновлённую модель дляe Bubble Tea runtime для обработки.
  187. //Здесь команду возвращать надо.
  188. */
  189. return desk, cmd
  190. }
  191. func (sf *Desktop) View() string {
  192. s := time.Now().Local().Format("[ WarTank ] = 2006-01-02 15:04:05.000")
  193. s += fmt.Sprintf("\tХост=%q\tЛогин=%q\tПароль=%q\tПодключено=%v\tЛогин=%v\tЕстьАдмин=%v\n\n", desk.host, desk.login, desk.pass, desk.isConnect, desk.isLogin, desk.isMakeAdmin)
  194. s += desk.dictWin[desk.winName].View()
  195. /*
  196. switch desk.winName {
  197. case ModeInputPassServer: // ввод пароля
  198. s += desk.winPassServer()
  199. case ModeConnectServer: // Режим подключения к серверу
  200. s += desk.winConnectServer()
  201. case ModeLoginServer: // Режим логина на сервер
  202. s += desk.winServerLogin()
  203. case ModeServerMakeAdmin: // Режим содания админа на бот-сервере
  204. s += desk.winServerMakeAdmin()
  205. case ModeShowMenuBot: // Меню бото-фермы
  206. s += desk.winMenuBotoFerma()
  207. }
  208. */
  209. return s
  210. }
  211. /*
  212. func (sf *Desktop) winMenuBotoFerma() string {
  213. s := "=Меню бото-фермы вар-танк=\n\n"
  214. s += "[1]-Список ботов\n"
  215. s += "[2]-Добавить бота\n"
  216. s += "[3]-Удалить бота\n"
  217. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  218. return s
  219. }
  220. func (sf *Desktop) winServerMakeAdmin() string {
  221. s := "=Создание админа на бот-сервере вар-танк=\n\n"
  222. if !desk.isMakeAdmin {
  223. err := desk.client.MakeAdmin(desk.pass)
  224. if err != nil {
  225. s += fmt.Sprintf("Desktop.winServerMakeAdmin(): err=\n\t%v", err)
  226. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  227. return s
  228. }
  229. }
  230. s += "Desktop.winServerMakeAdmin(): ok\n"
  231. desk.isMakeAdmin = true
  232. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  233. return s
  234. }
  235. func (sf *Desktop) winServerLogin() string {
  236. s := "=Логин на бот-сервер вар-танк=\n\n"
  237. err := desk.client.Login(desk.login, desk.pass)
  238. if err != nil {
  239. s += fmt.Sprintf("Desktop.winServerLogin(): err=\n\t%v", err)
  240. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  241. return s
  242. }
  243. s += "Desktop.winServerLogin(): ok\n"
  244. desk.isLogin = true
  245. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  246. return s
  247. }
  248. func (sf *Desktop) winConnectServer() string {
  249. s := "=Подключение к бот-серверу вар-танк=\n\n"
  250. if !desk.isConnect {
  251. err := desk.client.Connect(desk.host)
  252. if err != nil {
  253. s += fmt.Sprintf("Desktop.winConnectServer(): err=\n\t%v", err)
  254. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  255. return s
  256. }
  257. }
  258. s += "Desktop.winConnectServer(): ok\n"
  259. desk.isConnect = true
  260. s += "\n\n[ctrl+q]-выход [esc]-отмена\n"
  261. return s
  262. }
  263. func (sf *Desktop) winPassServer() string {
  264. s := "=Ввод пароля для бот-сервера вар-танк=\n\n"
  265. s += fmt.Sprintf(">%v\n", desk.textInput.View())
  266. s += "\n\n[ctrl+q]-выход [esc]-назад\n"
  267. return s
  268. }
  269. */
  270. // IsLogin -- возвращает признак логина на сервер ботов
  271. func (sf *Desktop) IsLogin() bool {
  272. return sf.isLogin
  273. }
  274. // IsConnect -- возвращает признак подключения на сервер ботов
  275. func (sf *Desktop) IsConnect() bool {
  276. return sf.isConnect
  277. }
  278. // SetHost -- устанавливает имя хоста бото-фермы
  279. func (sf *Desktop) SetHost(hostName string) {
  280. sf.host = hostName
  281. }
  282. // SetLogin -- устанавливает логин бото-фермы
  283. func (sf *Desktop) SetLogin(login string) {
  284. sf.login = login
  285. }