desktop.go 10 KB

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