| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- // package warbot -- бот для игры в wartank
- package warbot
- import (
- "context"
- "fmt"
- "log"
- "strings"
- "time"
- "wartank/pkg/alias"
- "wartank/pkg/components/safe_bool"
- "wartank/pkg/types"
- "wartank/server/serv_bots/warbot/angar"
- "wartank/server/serv_bots/warbot/tank"
- "wartank/server/serv_bots/warbot/warbot_config"
- "wartank/server/serv_bots/warbot/warbot_net"
- )
- // ВарБот -- бот для игры в вартанк
- type ВарБот struct {
- сервер types.ИСервер
- store types.ИХранилище
- танк *tank.Танк
- errFinal error // Финальная ошибка работы, если была
- ангар types.ИАнгар
- сеть types.ИБотСеть
- еслиРаботает *safe_bool.БезопБул
- еслиАвтозапуск *safe_bool.БезопБул
- конфиг *warbot_config.ВарБотКонфиг // Конфиг бота для хранения в базе
- кнт context.Context // Контекст бота
- фтОтмена func() // Функция отменя контекста бота
- }
- // ЗагрузитьВарБот -- загружает бота из базы
- func ЗагрузитьВарБот(сервер types.ИСервер, номер alias.БотНомер) (types.ИБот, error) {
- { // Предусловия
- if сервер == nil {
- return nil, fmt.Errorf("ЗагрузитьВарБот(): IApp is nil")
- }
- if номер == 0 {
- return nil, fmt.Errorf("ЗагрузитьВарБот(): номер пустой")
- }
- }
- стрНомер := fmt.Sprint(номер)
- log.Printf("ЗагрузитьВарБот(): номер=%q\n", стрНомер)
- store := сервер.Хранилище()
- binData, err := store.Получ("/bots/" + стрНомер)
- if err != nil {
- if !strings.Contains(err.Error(), "not found") {
- return nil, fmt.Errorf("ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%w", номер, err)
- }
- return nil, fmt.Errorf("ЗагрузитьВарБот(): bot '%v' not found in store", номер)
- }
- конфиг := &warbot_config.ВарБотКонфиг{}
- if err = конфиг.Unmarshall(binData); err != nil {
- return nil, fmt.Errorf("ЗагрузитьВарБот(): in unmarshall WarBotConfig(%v) from store, err=\n\t%w", номер, err)
- }
- сам, err := создатьЯдроВарБот(сервер, конфиг)
- if err != nil {
- return nil, fmt.Errorf("ЗагрузитьВарБот(): in make core for bot '%v', err=\n\t%w", номер, err)
- }
- go сам.рестарт()
- return сам, nil
- }
- // Каждые два часа перезапускает себя
- func (сам *ВарБот) рестарт() {
- time.Sleep(time.Hour * 2)
- сам.сервер.Отменить()
- log.Printf("ВарБот.рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_)
- }
- // НовВарБот -- возвращает новый WarBot
- func НовВарБот(сервер types.ИСервер, номер alias.БотНомер, логин, пароль string, еслиАвто bool) (*ВарБот, error) {
- { // Предусловия
- if сервер == nil {
- return nil, fmt.Errorf("НовВарБот(): IApp is nil")
- }
- if логин == "" {
- return nil, fmt.Errorf("НовВарБот(): login is empty")
- }
- if пароль == "" {
- return nil, fmt.Errorf("НовВарБот(): pass is empty")
- }
- }
- log.Printf("НовВарБот(): name=%q\n", логин)
- config := &warbot_config.ВарБотКонфиг{
- ЕслиАвтозапуск_: еслиАвто,
- Логин_: логин,
- Пароль_: пароль,
- Номер_: номер,
- }
- сам, err := создатьЯдроВарБот(сервер, config)
- if err != nil {
- return nil, fmt.Errorf("НовВарБот(): in make core bot %q, err=\n\t%w", логин, err)
- }
- if err := сам.сохр(); err != nil {
- return nil, fmt.Errorf("НовВарБот(): in self save to store, err=\n\t%w", err)
- }
- return сам, nil
- }
- // Создаёт ядро бота
- func создатьЯдроВарБот(серв types.ИСервер, конфиг *warbot_config.ВарБотКонфиг) (*ВарБот, error) {
- { // Предусловия
- if серв == nil {
- return nil, fmt.Errorf("NewWarBot(): IServer==nil")
- }
- if конфиг == nil {
- return nil, fmt.Errorf("NewWarBot(): WarBotConfig==nil")
- }
- }
- танк, ош := tank.NewTank()
- if ош != nil {
- return nil, fmt.Errorf("NewWarBot(): при создании параметров танка, ош=\n\t%w", ош)
- }
- ctx, fnCancel := context.WithCancel(серв.Контекст())
- сам := &ВарБот{
- сервер: серв,
- store: серв.Хранилище(),
- танк: танк,
- еслиРаботает: safe_bool.НовБезопБул(),
- еслиАвтозапуск: safe_bool.НовБезопБул(),
- конфиг: конфиг,
- кнт: ctx,
- фтОтмена: fnCancel,
- }
- var err error
- { // WarBotNet
- сам.сеть, err = warbot_net.НовВарБотСеть(сам)
- if err != nil {
- return nil, fmt.Errorf("NewWarBot(): in make IBotNet, err=\n\t%w", err)
- }
- }
- сам.ангар, err = angar.НовАнгар(сам)
- if err != nil {
- return nil, fmt.Errorf("NewWarBot(): bot(%q) in make IAngar, err=\n\t%w", сам.Имя(), err)
- }
- if сам.конфиг.ЕслиАвтозапуск_ {
- сам.еслиАвтозапуск.Уст()
- сам.Пуск()
- }
- return сам, nil
- }
- // Сервер -- возвращает ссылку на объект сервера
- func (сам *ВарБот) Сервер() types.ИСервер {
- return сам.сервер
- }
- // ЕслиПуск -- возвращает признак, что бот подключен
- func (сам *ВарБот) ЕслиПуск() bool {
- return сам.еслиРаботает.Получ()
- }
- // Номер -- возвращает номер бота
- func (сам *ВарБот) Номер() alias.БотНомер {
- return сам.конфиг.Номер()
- }
- // Имя -- возвращает имя бота
- func (сам *ВарБот) Имя() string {
- return сам.конфиг.Логин()
- }
- // Пароль -- возвращает пароль бота
- func (сам *ВарБот) Пароль() string {
- return сам.конфиг.Пароль_
- }
- // Пуск -- запускает бот в работу
- func (сам *ВарБот) Пуск() {
- if сам.еслиРаботает.Получ() {
- return
- }
- if err := сам.ангар.Пуск(); err != nil {
- log.Printf("WarBot.Run(): bot(%q) in run angar, err=\n\t%v\n", сам.Имя(), err)
- return
- }
- сам.еслиРаботает.Уст()
- }
- // Error -- возвращает финальную ошибку работы, если была
- func (сам *ВарБот) Error() error {
- return сам.errFinal
- }
- // Ангар -- возвращает ангар игры
- func (сам *ВарБот) Ангар() types.ИАнгар {
- return сам.ангар
- }
- // Танк -- возвращает объект танка
- func (сам *ВарБот) Танк() types.ИТанк {
- return сам.танк
- }
- // Сеть -- возвращает ссылку на свой сетевой клиент
- func (сам *ВарБот) Сеть() types.ИБотСеть {
- return сам.сеть
- }
- // АвтоИграЕсли -- возвращает признак автоматичского запуска бота
- func (сам *ВарБот) АвтоИграЕсли() bool {
- return сам.еслиАвтозапуск.Получ()
- }
- // АвтоИграУст -- устанавливает признак автоматического запуска бота
- func (сам *ВарБот) АвтоИграУст() {
- log.Printf("WarBot.SetAutoGame()")
- сам.еслиАвтозапуск.Уст()
- сам.конфиг.ЕслиАвтозапуск_ = true
- сам.saveConfig()
- }
- // АвтоИграСброс -- сбрасывает признак автоматического запуска бота
- func (сам *ВарБот) АвтоИграСброс() {
- log.Printf("WarBot.ResetAutoGame()")
- сам.еслиАвтозапуск.Уст()
- сам.конфиг.ЕслиАвтозапуск_ = false
- сам.saveConfig()
- }
- // Сохраняет конфиг бота
- func (сам *ВарБот) saveConfig() {
- log.Printf("WarBot.saveConfig()")
- strConf := сам.конфиг.Marshall()
- err := сам.store.Уст("/bots/"+сам.Имя(), strConf)
- if err != nil {
- log.Printf("WarBot.saveConfig(): err=\n\t%v\n", err)
- }
- }
- // Кнт -- возвращает контекст бота
- func (сам *ВарБот) Кнт() context.Context {
- return сам.кнт
- }
- // Закончить -- отменяет контекст бота
- func (сам *ВарБот) Закончить() {
- сам.фтОтмена()
- }
- // Сохраняет себя в базу
- func (сам *ВарБот) сохр() error {
- стрНомер := fmt.Sprint(сам.Номер())
- err := сам.store.Уст("/bots/"+стрНомер, сам.конфиг.Marshall())
- if err != nil {
- return fmt.Errorf("WarBot.save(): in self save to store bot(%q), err=\n\t%w", сам.Имя(), err)
- }
- return nil
- }
|