// newBot Создать нового бота и запомнить его в map func newBot() (int, error) { var err error mlog.Trace("Функция: newBot") // найти новый незанятый id id := 0 mlog.Trace("Функция: newBot. Поиск нового незанятого id") for i := 1; i < 10000; i++ { _, ok := mbot[i] if !ok { id = i break } } if id == 0 { // превышен индекс err = errors.New("Превышено количество индексов ботов. id > 999") mlog.Error(err) } else { b := bot{} // инициализировать бота b.ID = id b.Name = fmt.Sprintf("Бот %s", strconv.Itoa(id)) mlog.Trace("Функция: newBot. Новый бот.", b) mbot[id] = b } return id, err }
// delBot Найти бота по идентификатору и удалить func delBot(id int) error { mlog.Trace("Функция: delBot") _, ok := mbot[id] if ok { delete(mbot, id) mlog.Trace("Функция: delBot. Бот с id = %d удален.", id) } return nil }
// createBot Создать бота и вернуть присвоенный ему ID func createBot(c *echo.Context) error { mlog.Trace("Функция: createBot") id, err := newBot() if err != nil { mlog.Trace("Функция newBot вернула ошибку.") return c.String(http.StatusOK, "0") } mlog.Trace("Функция: createBot. id =", id) return c.String(http.StatusOK, strconv.Itoa(id)) }
// listBot сформировать и выдать в формате json список текущих ботов func listBot(c *echo.Context) error { mlog.Trace("Функция: listBot") var err error list, err := lstBot() // запросить список ботов mlog.Trace(fmt.Sprintf("Функция: listBot. list = %v, err = %v", list, err)) if err != nil { mlog.Error(err) return c.JSON(http.StatusConflict, nil) } return c.JSON(http.StatusOK, list) }
// disconnectBotFromServer Функция отключает бота от игрового сервера func disconnectBotFromServer(id int) error { mlog.Trace("Функция: disconnectBotFromServer") var err error bot, ok := mbot[id] if !ok { err = errors.New(fmt.Sprintf("В mbot нет бота с указанным индексом. id = %d", id)) mlog.Error(err) return err } if !bot.Connected { mlog.Warning("Бот уже отключен от сервера.") return nil } bot.Connected = false mbot[id] = bot mlog.Trace("Функция: disconnectBotFromServer. Бот отключен от сервера.") return nil }
func main() { mlog.Start(mlog.LevelTrace, "log.txt") mlog.Trace("-------------------------------------------------") mlog.Trace(" Start program ") mlog.Trace("-------------------------------------------------") chWeb := CreateWeb() mlog.Trace("chWeb", chWeb) // временное решение. Нажатие Enter закрывает программу var response string fmt.Println("Press Enter") _, _ = fmt.Scanln(&response) // Stop program mlog.Trace("Stop program\n\n") }
func updateBot(c *echo.Context) error { mlog.Trace("Функция: updateBot") id, err := strconv.Atoi(c.Param("id")) // преобразовать в int if err != nil { mlog.Error(err) } else { inf := make(map[string]interface{}) // TODO перед заполнением проверить наличие переданных значений. И заполнять только те, которые пришли с запросом inf["id"] = id inf["name"] = c.Form("name") inf["login"] = c.Form("login") inf["password"] = c.Form("password") mlog.Trace("Функция: updateBot. Получены данные ", inf) if err := updBot(id, inf); err != nil { mlog.Error(err) } } return c.String(http.StatusOK, "ok") // сообщить, что бот изменен }
// updBot Функция обновляет информацию бота по указанному идентификатору func updBot(id int, inf map[string]interface{}) error { mlog.Trace("Функция: updBot") var err error bot, ok := mbot[id] if !ok { err = errors.New("В mbot нет бота с указанным индексом.") mlog.Error(err) return err } for key, value := range inf { switch key { case "name": valueStr, ok := value.(string) if ok { bot.Name = valueStr } else { mlog.Trace("Ошибка при приведении значения к строке") } case "login": valueStr, ok := value.(string) if ok { bot.Login = valueStr } else { mlog.Trace("Ошибка при приведении значения к строке") } case "password": valueStr, ok := value.(string) if ok { bot.Password = valueStr } else { mlog.Trace("Ошибка при приведении значения к строке") } } } mbot[id] = bot mlog.Trace("Функция: updBot. Обновлена информация бота с id = %d.", id) return nil }
func connectToServer(c *echo.Context) error { mlog.Trace("Функция: connectToServer") id, err := strconv.Atoi(c.Param("id")) // преобразовать в int if err != nil { mlog.Error(err) } else { if err := connectBotToServer(id); err != nil { mlog.Error(err) } } return c.String(http.StatusOK, "ok") // сообщить, что бот изменен }
// deleteBot Получить из контехта ID и передать функции удаления. По завершению уведомить, что бот удален func deleteBot(c *echo.Context) error { mlog.Trace("Функция: deleteBot") id, err := strconv.Atoi(c.Param("id")) // преобразовать в int if err != nil { mlog.Error(err) } else { err = delBot(id) // передать в функцию удаления if err != nil { mlog.Error(err) } } return c.String(http.StatusOK, "ok") // сообщить, что бот удален }
// lstBot Функция подготавливает и возвращает массив с информацией по текущим ботам func lstBot() ([]map[string]string, error) { mlog.Trace("Функция: lstBot") list := make([]map[string]string, len(mbot)) i := 0 for id, bot := range mbot { inf := make(map[string]string) inf["id"] = strconv.Itoa(id) inf["name"] = bot.Name inf["login"] = bot.Login inf["password"] = bot.Password list[i] = inf i++ } return list, nil }
// connectBotToServer Функция получает uid и token с сайта mail.ru и подключается к игровому серверу func connectBotToServer(id int) error { mlog.Trace("Функция: connectBotToServer") var err error bot, ok := mbot[id] if !ok { err = errors.New(fmt.Sprintf("В mbot нет бота с указанным индексом. id = %d", id)) mlog.Error(err) return err } if bot.Connected { mlog.Warning("Бот уже подключен к серверу.") return nil } uid, uid2, token, err := getUidAndToken(bot.Login, bot.Password) if err != nil { mlog.Error(err) return err } mlog.Trace("Функция: connectBotToServer. uid = %v, uid2 = %v, token = %v", uid, uid2, token) bot.Connected = true mbot[id] = bot mlog.Trace("Функция: connectBotToServer. Бот подключен к серверу.") return nil }
// getUidAndToken Функция передает на сервер mail.ru логин и пароль и получает uid и token для авторизации на игровом сервере func getUidAndToken(login, password string) ([]byte, []byte, []byte, error) { mlog.Trace("Функция: getUidAndToken") var err error // проверить корректность логина split := strings.Split(login, "@") if len(split) < 2 { err = errors.New("Неправильный логин. Должен быть указан e-mail.") mlog.Error(err) return nil, nil, nil, err } domain := split[1] mailDomains := []string{"mail.ru", "inbox.ru", "bk.ru", "list.ru"} foundMailDomain := false for _, v := range mailDomains { if v == domain { foundMailDomain = true break } } var uid, uid2, token string if foundMailDomain { mlog.Trace("Логин от mail.ru") // TODO обработка ситуации, когда e-mail заведен в mail.ru err = errors.New("Отсутствует обработка получения uid и токена по email-у от mail.ru") mlog.Error(err) return nil, nil, nil, err } else { apiURL := "http://authdl.mail.ru" resource := "/sz.php" data := url.Values{} params := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?><AutoLogin ProjectId="61" SubProjectId="0" ShardId="0" Username="******" Password="******"/>`, login, password) u, _ := url.ParseRequestURI(apiURL) u.Path = resource urlStr := fmt.Sprintf("%v", u) client := &http.Client{} r, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(params)) // <-- URL-encoded payload r.Header.Add("User-Agent", "Downloader/4260") r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode()))) r.Header.Add("Accept-Encoding", "identity") resp, _ := client.Do(r) body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, nil, nil, err } type AuthPers struct { XMLName xml.Name `xml:"AutoLogin"` UID2 string `xml:"PersId,attr"` Token string `xml:"Key,attr"` } var q AuthPers xml.Unmarshal(body, &q) uid2 = q.UID2 token = q.Token // params = fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?><PersList ProjectId="61" SubProjectId="0" ShardId="0" Username="******" Password="******"/>`, login, password) r, _ = http.NewRequest("POST", urlStr, bytes.NewBufferString(params)) // <-- URL-encoded payload r.Header.Add("User-Agent", "Downloader/4260") r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode()))) r.Header.Add("Accept-Encoding", "identity") resp, _ = client.Do(r) body, err = ioutil.ReadAll(resp.Body) //fmt.Println(string(body)) type Pers struct { XMLName xml.Name `xml:"Pers"` ID string `xml:"Id,attr"` Title string `xml:"Title,attr"` Cli string `xml:"Cli,attr"` } type PersList struct { XMLName xml.Name `xml:"PersList"` PersID string `xml:"PersId,attr"` PersList []Pers `xml:"Pers"` } var q1 PersList xml.Unmarshal(body, &q1) if len(q1.PersList) == 0 { err = errors.New("У учетной записи нет игровых аккаунтов.") mlog.Error(err) return nil, nil, nil, err } uid = q1.PersList[0].ID } return []byte(uid), []byte(uid2), []byte(token), nil }