desktop.go 12 KB

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