desktop.go 11 KB

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