package main import ( "context" "fmt" "sync" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/pkg/errors" ) type playerInfo struct { playerID string playerMessageID int isOnline bool } func (p *playerInfo) setOnline(v bool) *playerInfo { p.isOnline = v return p } const ( emojiUp = "\xE2\xAC\x86" emojiDeaths = "\xF0\x9F\x92\x80" emojiTime = "\xF0\x9F\x95\x90" emojiGun = "\xF0\x9F\x94\xAB" ) func (p *playerInfo) updatePlayerInfo(ctx context.Context) error { botApi := getBotApi(ctx) conf := getConfig(ctx) db := getDB(ctx) player, err := db.getPlayerByID(ctx, p.playerID) if err != nil { return err } kills, err := db.getKillsByOPlayerID(ctx, player.id) if err != nil { return err } test := `*%s* | %s %s Уровень: *%s* %s Смертей: *%d* %s Время в игре: %s %s Фрагов: %d ` access := "\xE2\x9D\x8C offLine" if p.isOnline { access = "\xE2\x9C\x85 onLine" } level := "-" if player.level >= 0 { level = fmt.Sprintf("%d", player.level) } test = fmt.Sprintf(test, player.name, access, emojiUp, level, emojiDeaths, player.deaths, emojiTime, player.onlineDuration.String(), emojiGun, kills, ) if p.playerMessageID != 0 { mess := tgbotapi.NewEditMessageText(conf.ChatID, p.playerMessageID, test) mess.ParseMode = tgbotapi.ModeMarkdown ikm := tgbotapi.NewInlineKeyboardMarkup( tgbotapi.NewInlineKeyboardRow( tgbotapi.NewInlineKeyboardButtonData("Подробнее", "additional"), ), ) mess.ReplyMarkup = &ikm _, err := botApi.Send(mess) if err != nil { return errors.Wrap(err, "Failed to update message") } return nil } mess := tgbotapi.NewMessage(conf.ChatID, test) mess.ParseMode = tgbotapi.ModeMarkdown m, err := botApi.Send(mess) if err != nil { return errors.Wrap(err, "Failed to send message") } p.playerMessageID = m.MessageID return nil } func (p *playerInfo) deletePlayerInfo(ctx context.Context) error { botApi := getBotApi(ctx) conf := getConfig(ctx) mess := tgbotapi.NewDeleteMessage(conf.ChatID, p.playerMessageID) _, err := botApi.Send(mess) if err != nil { return errors.Wrap(err, "Failed to send message") } return nil } type playersBoard struct { mx sync.Mutex players []playerInfo } func newPlayersBoard() *playersBoard { return &playersBoard{ players: make([]playerInfo, 0), } } func (pb *playersBoard) load(ctx context.Context) error { pb.mx.Lock() defer pb.mx.Unlock() db := getDB(ctx) players, err := db.getPlayers(ctx) if err != nil { return err } pb.players = make([]playerInfo, 0, len(players)) for _, p := range players { pi := playerInfo{ playerID: p.id, } err := pi.updatePlayerInfo(ctx) if err != nil { return err } pb.players = append(pb.players, pi) } return nil } func (pb *playersBoard) getPlayerBoard(playerID string) *playerInfo { for i := range pb.players { if pb.players[i].playerID == playerID { return &pb.players[i] } } pb.mx.Lock() defer pb.mx.Unlock() pb.players = append(pb.players, playerInfo{ playerID: playerID, }) return &pb.players[len(pb.players)-1] } func (pb *playersBoard) run(ctx context.Context) { log := getLogger(ctx) <-ctx.Done() pb.mx.Lock() defer pb.mx.Unlock() for _, p := range pb.players { err := p.deletePlayerInfo(ctx) if err != nil { log.Error(err) } } }