// package bot -- бот для игры в wartank package bot import ( "context" "fmt" "log" "strings" "time" . "wartank/app/lev0/alias" . "wartank/app/lev0/types" "wartank/app/lev2/arena/arena_angar" "wartank/app/lev3/bot/bot_config" "wartank/app/lev3/bot/bot_net" "wartank/app/lev3/bot/bot_stat/tank_stat" "wartank/kernel" . "wartank/kernel/kernel_types" ) // ВарБот -- бот для игры в вартанк type Бот struct { прилож ИПриложение хран ИЯдроХранилище стата ИТанкСтат errFinal error // Финальная ошибка работы, если была ангар ИАренаАнгар сеть ИБотСеть еслиРаботает ИБезопБул еслиАвтозапуск ИБезопБулНаблюд конфиг *bot_config.БотКонфиг // Конфиг бота для хранения в базе кнт context.Context // Контекст бота фтОтмена func() // Функция отменя контекста бота лог ИЯдроЛог конт ИБотКонтекст } // ЗагрузитьВарБот -- загружает бота из базы func ЗагрузитьВарБот(конт ИЯдроКонтекст, номер АБотНомер) *Бот { лог := kernel.НовЛог("ВарБот") лог.Инфо("ЗагрузитьВарБот()\n") лог.Паника(номер == 0, "ЗагрузитьВарБот(): номер пустой") стрНомер := fmt.Sprint(номер) лог.Инфо("ЗагрузитьВарБот(): номер=%q\n", стрНомер) хран := конт.Получ("kernStore").(ИЯдроХранилище) binData, err := хран.Get("/bots/" + стрНомер) if err != nil { if !strings.Contains(err.Error(), "not found") { лог.Паника(true, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err) } лог.Паника(err != nil, "ЗагрузитьВарБот(): in load bot '%v' from store, err=\n\t%v\n", номер, err) } конфиг := &bot_config.БотКонфиг{} конфиг.Unmarshal(binData) сам := создатьЯдроВарБот(конт, конфиг) go сам.рестарт() _ = ИБот(сам) return сам } // Каждые два часа перезапускает себя func (сам *Бот) рестарт() { time.Sleep(time.Hour * 2) сам.прилож.Отменить() сам.лог.Инфо("рестарт(): бот %q перезагружен\n", сам.конфиг.Логин_) } // НовВарБот -- возвращает новый WarBot func НовВарБот(конт ИЯдроКонтекст, номер АБотНомер, логин, пароль string, еслиАвто bool) *Бот { лог := kernel.НовЛог("ВарБот") лог.Инфо("НовВарБот()\n") лог.Паника(логин == "", "НовВарБот(): логин пустой") лог.Паника(пароль == "", "НовВарБот(): пароль пустой") лог.Инфо("НовВарБот(): name=%q\n", логин) config := &bot_config.БотКонфиг{ ЕслиАвтозапуск_: еслиАвто, Логин_: логин, Пароль_: пароль, Номер_: номер, } сам := создатьЯдроВарБот(конт, config) сам.сохрКонфиг() _ = ИБот(сам) return сам } // Создаёт ядро бота func создатьЯдроВарБот(конт ИЯдроКонтекст, конфиг *bot_config.БотКонфиг) *Бот { лог := kernel.НовЛог("ВарБот") лог.Инфо("создатьЯдроВарБот()\n") лог.Паника(конфиг == nil, "создатьЯдроВарБот(): ВарБотКонфиг==nil") ctx, fnCancel := context.WithCancel(конт.Конт()) приложение := конт.Получ("приложение").(ИПриложение) контБот := kernel.НовКонтекст() сам := &Бот{ конт: контБот, прилож: приложение, хран: конт.Получ("kernStore").(ИЯдроХранилище), стата: tank_stat.НовТанкСтат(конт), еслиРаботает: kernel.НовБезопБул(), конфиг: конфиг, кнт: ctx, фтОтмена: fnCancel, лог: лог, } сам.еслиАвтозапуск = kernel.НовБезопБулНаблюд(сам.Имя(), сам.автозапускИзм) сам.конт.Уст("бот", сам) сам.конт.Уст("приложение", приложение) сам.сеть = bot_net.НовБотСеть(сам.конт) сам.ангар = arena_angar.НовАнгар(сам.конт) if сам.конфиг.ЕслиАвтозапуск_ { сам.еслиАвтозапуск.Уст() сам.Пуск() } return сам } // ЕслиРабота -- возвращает признак, что бот подключен func (сам *Бот) ЕслиРабота() bool { return сам.еслиРаботает.Получ() } // Номер -- возвращает номер бота func (сам *Бот) Номер() АБотНомер { return сам.конфиг.Номер() } // Имя -- возвращает имя бота func (сам *Бот) Имя() string { return сам.конфиг.Логин() } // Пароль -- возвращает пароль бота func (сам *Бот) Пароль() string { return сам.конфиг.Пароль_ } // Пуск -- запускает бот в работу func (сам *Бот) Пуск() { if сам.еслиРаботает.Получ() { return } сам.ангар.Пуск() сам.еслиРаботает.Уст() } // Error -- возвращает финальную ошибку работы, если была func (сам *Бот) Error() error { return сам.errFinal } // Ангар -- возвращает ангар игры func (сам *Бот) Ангар() ИАренаАнгар { return сам.ангар } // Стата -- возвращает статистику танка func (сам *Бот) Стата() ИТанкСтат { return сам.стата } // Сеть -- возвращает ссылку на свой сетевой клиент func (сам *Бот) Сеть() ИБотСеть { return сам.сеть } // Автозапуск -- возвращает признак автоматического запуска бота func (сам *Бот) Автозапуск() ИБезопБулНаблюд { return сам.еслиАвтозапуск } // Обратный вызов автоматического запуска бота func (сам *Бот) автозапускИзм(знач bool) { сам.лог.Отладка("Бот.автозапускИзм()") // сам.еслиАвтозапуск.Уст() сам.конфиг.ЕслиАвтозапуск_ = знач сам.сохрКонфиг() } // Сохраняет конфиг бота func (сам *Бот) сохрКонфиг() { log.Printf("ВарБот.сохрКонфиг()") strConf := сам.конфиг.Marshall() стрНомер := fmt.Sprint(сам.Номер()) err := сам.хран.Set("/bots/"+стрНомер, strConf) сам.лог.Паника(err != nil, "ВарБот.сохрКонфиг(): err=\n\t%v\n", err) } // Контекст -- возвращает контекст бота func (сам *Бот) Контекст() context.Context { return сам.кнт } // Закончить -- отменяет контекст бота func (сам *Бот) Закончить() { сам.фтОтмена() } // КонтБот -- возвращает контекст бота func (сам *Бот) КонтБот() ИБотКонтекст { return сам.конт }