Compare commits
	
		
			4 Commits
		
	
	
		
			feature_te
			...
			5d86159900
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5d86159900 | |||
| 3f2980a922 | |||
| fe30690724 | |||
| b7463efb45 | 
							
								
								
									
										16
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								.drone.yml
									
									
									
									
									
								
							| @ -7,6 +7,14 @@ platform: | ||||
|   os: linux | ||||
|   arch: amd64 | ||||
|  | ||||
| trigger: | ||||
|   branch: | ||||
|     - master | ||||
|   event: | ||||
|     include: | ||||
|       - push | ||||
|       - pull_request | ||||
|  | ||||
| steps: | ||||
|   - name: build | ||||
|     commands: | ||||
| @ -16,12 +24,12 @@ steps: | ||||
|     commands: | ||||
|       - make install | ||||
|     when: | ||||
|       branch: | ||||
|         - master | ||||
|       event: | ||||
|         - push | ||||
|  | ||||
|   - name: restart | ||||
|     commands: | ||||
|       - systemctl restart craft-bot | ||||
|     when: | ||||
|       branch: | ||||
|         - master | ||||
|       event: | ||||
|         - push | ||||
|  | ||||
							
								
								
									
										26
									
								
								context.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								context.go
									
									
									
									
									
								
							| @ -20,7 +20,7 @@ const ( | ||||
| 	ctxKeyMessageCleaner | ||||
| 	ctxKeyDataBase | ||||
| 	ctxKeyPlayersBoard | ||||
| 	ctxKeyFragMessages | ||||
| 	ctxKeyMessageStorage | ||||
| ) | ||||
|  | ||||
| func createLogger(debug bool) *logrus.Logger { | ||||
| @ -44,17 +44,16 @@ func createLogger(debug bool) *logrus.Logger { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func createContext(config *Config, bot *tgbotapi.BotAPI, mc *messageCleaner, ch *commandHandler, db *dbLayer, pb *playersBoard, fms *fragMessages) (context.Context, func()) { | ||||
| func createContext(config *Config, bot *tgbotapi.BotAPI, ch *commandHandler, db *dbLayer, pb *playersBoard, ms *messageStorage) (context.Context, func()) { | ||||
| 	ctx, cancelFunc := context.WithCancel(context.Background()) | ||||
|  | ||||
| 	ctx = context.WithValue(ctx, ctxKeyLogger, createLogger(true)) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyBotApi, bot) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyConfig, config) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyMessageCleaner, mc) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyCommandHandler, ch) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyDataBase, db) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyPlayersBoard, pb) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyFragMessages, fms) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyMessageStorage, ms) | ||||
|  | ||||
| 	return ctx, cancelFunc | ||||
| } | ||||
| @ -86,15 +85,6 @@ func getConfig(ctx context.Context) *Config { | ||||
| 	panic("Failed to get config from ctx") | ||||
| } | ||||
|  | ||||
| func getMessageCleaner(ctx context.Context) *messageCleaner { | ||||
| 	v := ctx.Value(ctxKeyMessageCleaner) | ||||
| 	if mc, ok := v.(*messageCleaner); ok { | ||||
| 		return mc | ||||
| 	} | ||||
|  | ||||
| 	panic("Failed to get message cleaner from ctx") | ||||
| } | ||||
|  | ||||
| func getCommandHandler(ctx context.Context) *commandHandler { | ||||
| 	v := ctx.Value(ctxKeyCommandHandler) | ||||
| 	if ch, ok := v.(*commandHandler); ok { | ||||
| @ -122,11 +112,11 @@ func getDPlayersBoard(ctx context.Context) *playersBoard { | ||||
| 	panic("Failed to get players board from ctx") | ||||
| } | ||||
|  | ||||
| func getFragMessages(ctx context.Context) *fragMessages { | ||||
| 	v := ctx.Value(ctxKeyFragMessages) | ||||
| 	if fms, ok := v.(*fragMessages); ok { | ||||
| 		return fms | ||||
| func getMessageStorage(ctx context.Context) *messageStorage { | ||||
| 	v := ctx.Value(ctxKeyMessageStorage) | ||||
| 	if ms, ok := v.(*messageStorage); ok { | ||||
| 		return ms | ||||
| 	} | ||||
|  | ||||
| 	panic("Failed to get frag messages from ctx") | ||||
| 	panic("Failed to get message storage from ctx") | ||||
| } | ||||
|  | ||||
| @ -1,90 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| type fragMessage struct { | ||||
| 	playerName     string | ||||
| 	entityName     string | ||||
| 	chatID         int64 | ||||
| 	messageID      int | ||||
| 	fragCount      int | ||||
| 	latestFragTime time.Time | ||||
| } | ||||
|  | ||||
| type fragMessages struct { | ||||
| 	mx       sync.Mutex | ||||
| 	messages []*fragMessage | ||||
| } | ||||
|  | ||||
| func (f *fragMessage) increaseFrag() *fragMessage { | ||||
| 	f.fragCount += 1 | ||||
| 	f.latestFragTime = time.Now() | ||||
| 	return f | ||||
| } | ||||
|  | ||||
| func newFragMessages() *fragMessages { | ||||
| 	return &fragMessages{ | ||||
| 		messages: make([]*fragMessage, 0), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (fms *fragMessages) addFrag(ctx context.Context, playerName string, entityName string) error { | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	cfg := getConfig(ctx) | ||||
| 	mc := getMessageCleaner(ctx) | ||||
|  | ||||
| 	fms.mx.Lock() | ||||
| 	defer fms.mx.Unlock() | ||||
|  | ||||
| 	for _, fm := range fms.messages { | ||||
| 		if fm.playerName == playerName && fm.entityName == entityName { | ||||
| 			mc.resetTimer(fm.messageID, fm.chatID, time.Second*30) | ||||
| 			fm.increaseFrag() | ||||
| 			mess := tgbotapi.NewEditMessageText( | ||||
| 				fm.chatID, | ||||
| 				fm.messageID, | ||||
| 				fmt.Sprintf("%s убил %s ✗ *%d*", fm.playerName, fm.entityName, fm.fragCount), | ||||
| 			) | ||||
| 			mess.ParseMode = tgbotapi.ModeMarkdown | ||||
| 			m, err := botApi.Send(mess) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			if m.MessageID != fm.messageID { | ||||
| 				m.MessageID = fm.messageID | ||||
| 				getLogger(ctx).Info("message id was changed") | ||||
| 			} | ||||
|  | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s убил %s", playerName, entityName)) | ||||
| 	m, err := botApi.Send(mess) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	mc.add(ctx, m.MessageID, cfg.ChatID, time.Second*30) | ||||
|  | ||||
| 	fm := &fragMessage{ | ||||
| 		playerName:     playerName, | ||||
| 		entityName:     entityName, | ||||
| 		chatID:         cfg.ChatID, | ||||
| 		messageID:      m.MessageID, | ||||
| 		fragCount:      1, | ||||
| 		latestFragTime: time.Now(), | ||||
| 	} | ||||
|  | ||||
| 	fms.messages = append(fms.messages, fm) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										69
									
								
								handlers.go
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								handlers.go
									
									
									
									
									
								
							| @ -4,8 +4,6 @@ import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| type command interface { | ||||
| @ -42,19 +40,21 @@ type joinCommand struct { | ||||
| } | ||||
|  | ||||
| func (c *joinCommand) run(ctx context.Context) { | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	cfg := getConfig(ctx) | ||||
| 	mc := getMessageCleaner(ctx) | ||||
| 	db := getDB(ctx) | ||||
| 	log := getLogger(ctx) | ||||
| 	pb := getDPlayersBoard(ctx) | ||||
| 	ms := getMessageStorage(ctx) | ||||
|  | ||||
| 	err := ms.apply(ctx, fmt.Sprintf("join:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) { | ||||
| 		if v, _ := d.(bool); v { | ||||
| 			return fmt.Sprintf("%s подключился снова", c.name), true | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Sprintf("%s подключился", c.name), true | ||||
| 	}) | ||||
|  | ||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s подключился", c.name)) | ||||
| 	m, err := botApi.Send(mess) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} else { | ||||
| 		mc.add(ctx, m.MessageID, cfg.ChatID, time.Second*30) | ||||
| 	} | ||||
|  | ||||
| 	p, err := db.getPlayerByName(ctx, c.name) | ||||
| @ -90,19 +90,21 @@ type quitCommand struct { | ||||
| } | ||||
|  | ||||
| func (c *quitCommand) run(ctx context.Context) { | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	cfg := getConfig(ctx) | ||||
| 	mc := getMessageCleaner(ctx) | ||||
| 	db := getDB(ctx) | ||||
| 	log := getLogger(ctx) | ||||
| 	pb := getDPlayersBoard(ctx) | ||||
| 	ms := getMessageStorage(ctx) | ||||
|  | ||||
| 	err := ms.apply(ctx, fmt.Sprintf("quit:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) { | ||||
| 		if v, _ := d.(bool); v { | ||||
| 			return fmt.Sprintf("%s отключился снова", c.name), true | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Sprintf("%s отключился", c.name), true | ||||
| 	}) | ||||
|  | ||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s отключился", c.name)) | ||||
| 	m, err := botApi.Send(mess) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} else { | ||||
| 		mc.add(ctx, m.MessageID, cfg.ChatID, time.Second*30) | ||||
| 	} | ||||
|  | ||||
| 	p, err := db.getPlayerByName(ctx, c.name) | ||||
| @ -138,6 +140,19 @@ func (c *deathCommand) run(ctx context.Context) { | ||||
| 	db := getDB(ctx) | ||||
| 	log := getLogger(ctx) | ||||
| 	pb := getDPlayersBoard(ctx) | ||||
| 	ms := getMessageStorage(ctx) | ||||
|  | ||||
| 	err := ms.apply(ctx, fmt.Sprintf("death:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) { | ||||
| 		if v, _ := d.(bool); v { | ||||
| 			return fmt.Sprintf("%s умудрился опять помереть от %s", c.name, c.deathType), true | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Sprintf("%s пал смертью храбрых от %s", c.name, c.deathType), true | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	p, err := db.getPlayerByName(ctx, c.name) | ||||
| 	if err != nil { | ||||
| @ -165,12 +180,7 @@ func (c *killCommand) run(ctx context.Context) { | ||||
| 	db := getDB(ctx) | ||||
| 	log := getLogger(ctx) | ||||
| 	pb := getDPlayersBoard(ctx) | ||||
| 	fms := getFragMessages(ctx) | ||||
|  | ||||
| 	err := fms.addFrag(ctx, c.name, c.entity) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} | ||||
| 	ms := getMessageStorage(ctx) | ||||
|  | ||||
| 	p, err := db.getPlayerByName(ctx, c.name) | ||||
| 	if err != nil { | ||||
| @ -183,6 +193,21 @@ func (c *killCommand) run(ctx context.Context) { | ||||
| 		log.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	f := func(d interface{}) (string, interface{}) { | ||||
| 		if fragsNum, ok := d.(int); ok { | ||||
| 			fragsNum++ | ||||
|  | ||||
| 			return fmt.Sprintf("%s убил %s ✗ *%d*", p.name, c.entity, fragsNum), fragsNum | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Sprintf("%s убил %s", p.name, c.entity), 1 | ||||
| 	} | ||||
|  | ||||
| 	err = ms.apply(ctx, fmt.Sprintf("kill:%s:%s", p.id, c.entity), time.Minute/2, f) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	err = pb.update(ctx, achievementMaxFrags, achievementPeaceable) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
|  | ||||
							
								
								
									
										32
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								main.go
									
									
									
									
									
								
							| @ -55,15 +55,11 @@ func main() { | ||||
| 		os.Exit(5) | ||||
| 	} | ||||
|  | ||||
| 	mc := newMessageCleaner(bot, &wg) | ||||
|  | ||||
| 	ch := newCommandHandler() | ||||
|  | ||||
| 	pb := newPlayersBoard() | ||||
| 	ms := NewMessageStorage() | ||||
|  | ||||
| 	fms := newFragMessages() | ||||
|  | ||||
| 	ctx, cancelFunc := createContext(&cfg, bot, mc, ch, db, pb, fms) | ||||
| 	ctx, cancelFunc := createContext(&cfg, bot, ch, db, pb, ms) | ||||
|  | ||||
| 	getLogger(ctx).Infof("Run...") | ||||
|  | ||||
| @ -73,24 +69,16 @@ func main() { | ||||
| 		os.Exit(5) | ||||
| 	} | ||||
|  | ||||
| 	runPlayerBoard(ctx, pb, &wg) | ||||
| 	runCommandHandler(ctx, ch, &wg) | ||||
| 	runMessageStorage(ctx, ms, &wg) | ||||
| 	runHttpServer(ctx, cfg.Http, &wg) | ||||
| 	runSignalHandler(ctx, cancelFunc) | ||||
|  | ||||
| 	getLogger(ctx).Infof("Running") | ||||
|  | ||||
| 	wg.Wait() | ||||
| } | ||||
|  | ||||
| func runPlayerBoard(ctx context.Context, pb *playersBoard, wg *sync.WaitGroup) { | ||||
| 	wg.Add(1) | ||||
|  | ||||
| 	go func() { | ||||
| 		defer wg.Done() | ||||
|  | ||||
| 		pb.run(ctx) | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func runCommandHandler(ctx context.Context, ch *commandHandler, wg *sync.WaitGroup) { | ||||
| 	wg.Add(1) | ||||
|  | ||||
| @ -101,6 +89,16 @@ func runCommandHandler(ctx context.Context, ch *commandHandler, wg *sync.WaitGro | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func runMessageStorage(ctx context.Context, ms *messageStorage, wg *sync.WaitGroup) { | ||||
| 	wg.Add(1) | ||||
|  | ||||
| 	go func() { | ||||
| 		defer wg.Done() | ||||
|  | ||||
| 		ms.run(ctx) | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func runHttpServer(ctx context.Context, addr string, wg *sync.WaitGroup) { | ||||
| 	server := http.Server{ | ||||
| 		Addr:    addr, | ||||
|  | ||||
| @ -1,91 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| type messageToClean struct { | ||||
| 	messID int | ||||
| 	chatID int64 | ||||
| 	timer  *time.Timer | ||||
| } | ||||
|  | ||||
| type messageCleaner struct { | ||||
| 	botApi   *tgbotapi.BotAPI | ||||
| 	wg       *sync.WaitGroup | ||||
| 	messages []*messageToClean | ||||
| 	mx       sync.Mutex | ||||
| } | ||||
|  | ||||
| func newMessageCleaner(bot *tgbotapi.BotAPI, wg *sync.WaitGroup) *messageCleaner { | ||||
| 	return &messageCleaner{ | ||||
| 		botApi:   bot, | ||||
| 		wg:       wg, | ||||
| 		messages: make([]*messageToClean, 0), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *messageCleaner) add(ctx context.Context, messID int, chatID int64, d time.Duration) { | ||||
| 	m.mx.Lock() | ||||
| 	defer m.mx.Unlock() | ||||
|  | ||||
| 	for _, ms := range m.messages { | ||||
| 		if ms.chatID == chatID && ms.messID == messID { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	m.wg.Add(1) | ||||
|  | ||||
| 	go func() { | ||||
| 		defer m.wg.Done() | ||||
|  | ||||
| 		ms := &messageToClean{ | ||||
| 			messID: messID, | ||||
| 			chatID: chatID, | ||||
| 			timer:  time.NewTimer(d), | ||||
| 		} | ||||
|  | ||||
| 		m.messages = append(m.messages, ms) | ||||
|  | ||||
| 		select { | ||||
| 		case <-ms.timer.C: | ||||
| 		case <-ctx.Done(): | ||||
| 		} | ||||
|  | ||||
| 		m.remove(messID, chatID) | ||||
|  | ||||
| 		_, _ = m.botApi.DeleteMessage(tgbotapi.DeleteMessageConfig{ | ||||
| 			MessageID: messID, | ||||
| 			ChatID:    chatID, | ||||
| 		}) | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func (m *messageCleaner) remove(messID int, chatID int64) { | ||||
| 	m.mx.Lock() | ||||
| 	defer m.mx.Unlock() | ||||
|  | ||||
| 	for i, ms := range m.messages { | ||||
| 		if ms.chatID == chatID && ms.messID == messID { | ||||
| 			m.messages = append(m.messages[:i], m.messages[i+1:]...) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *messageCleaner) resetTimer(messID int, chatID int64, d time.Duration) { | ||||
| 	m.mx.Lock() | ||||
| 	defer m.mx.Unlock() | ||||
|  | ||||
| 	for _, ms := range m.messages { | ||||
| 		if ms.chatID == chatID && ms.messID == messID { | ||||
| 			ms.timer.Reset(d) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										131
									
								
								messageStorage.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								messageStorage.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| type messageData struct { | ||||
| 	key    string | ||||
| 	messID int | ||||
| 	chatID int64 | ||||
| 	data   interface{} | ||||
| 	timer  *time.Timer | ||||
| } | ||||
|  | ||||
| type messageStorage struct { | ||||
| 	m        sync.Mutex | ||||
| 	messages []*messageData | ||||
| } | ||||
|  | ||||
| func NewMessageStorage() *messageStorage { | ||||
| 	return &messageStorage{ | ||||
| 		messages: make([]*messageData, 0, 20), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func deleteMessageFromTelegram(ctx context.Context, messID int, chatID int64) { | ||||
| 	botApi := getBotApi(ctx) | ||||
|  | ||||
| 	_, err := botApi.DeleteMessage(tgbotapi.DeleteMessageConfig{ | ||||
| 		MessageID: messID, | ||||
| 		ChatID:    chatID, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		getLogger(ctx).Error(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (ms *messageStorage) run(ctx context.Context) { | ||||
| 	<-ctx.Done() | ||||
|  | ||||
| 	ms.m.Lock() | ||||
| 	defer ms.m.Unlock() | ||||
|  | ||||
| 	for _, m := range ms.messages { | ||||
| 		deleteMessageFromTelegram(ctx, m.messID, m.chatID) | ||||
| 	} | ||||
|  | ||||
| 	ms.messages = ms.messages[:] | ||||
| } | ||||
|  | ||||
| func (ms *messageStorage) runTimeCleaner(ctx context.Context, md *messageData, d time.Duration) { | ||||
| 	if d <= 0 { | ||||
| 		md.timer = nil | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	t := time.NewTimer(d) | ||||
| 	md.timer = t | ||||
|  | ||||
| 	go func() { | ||||
| 		<-t.C | ||||
|  | ||||
| 		ms.m.Lock() | ||||
| 		defer ms.m.Unlock() | ||||
|  | ||||
| 		if md.timer == t { | ||||
| 			for i, m := range ms.messages { | ||||
| 				if m == md { | ||||
| 					deleteMessageFromTelegram(ctx, m.messID, m.chatID) | ||||
| 					ms.messages = append(ms.messages[:i], ms.messages[i+1:]...) | ||||
|  | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| type messageChanger func(interface{}) (string, interface{}) | ||||
|  | ||||
| func (ms *messageStorage) apply(ctx context.Context, key string, d time.Duration, mc messageChanger) error { | ||||
| 	ms.m.Lock() | ||||
| 	defer ms.m.Unlock() | ||||
|  | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	cfg := getConfig(ctx) | ||||
|  | ||||
| 	for _, md := range ms.messages { | ||||
| 		if md.key == key { | ||||
| 			text, data := mc(md.data) | ||||
|  | ||||
| 			mess := tgbotapi.NewEditMessageText(md.chatID, md.messID, text) | ||||
| 			mess.ParseMode = tgbotapi.ModeMarkdown | ||||
| 			_, err := botApi.Send(mess) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			md.data = data | ||||
| 			ms.runTimeCleaner(ctx, md, d) | ||||
|  | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	text, data := mc(nil) | ||||
|  | ||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, text) | ||||
| 	mess.ParseMode = tgbotapi.ModeMarkdown | ||||
| 	m, err := botApi.Send(mess) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	md := &messageData{ | ||||
| 		key:    key, | ||||
| 		messID: m.MessageID, | ||||
| 		chatID: cfg.ChatID, | ||||
| 		data:   data, | ||||
| 	} | ||||
|  | ||||
| 	ms.messages = append(ms.messages, md) | ||||
| 	ms.runTimeCleaner(ctx, md, d) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| @ -7,9 +7,7 @@ import ( | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| 	"github.com/hako/durafmt" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| type achievement uint8 | ||||
| @ -54,7 +52,6 @@ var allAchievement = []achievement{ | ||||
|  | ||||
| type playerInfo struct { | ||||
| 	playerID     string | ||||
| 	playerMessageID int | ||||
| 	isOnline     bool | ||||
| 	achievements []achievement | ||||
| 	messageText  string | ||||
| @ -74,8 +71,6 @@ const ( | ||||
| ) | ||||
|  | ||||
| func (p *playerInfo) updatePlayerInfo(ctx context.Context) error { | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	conf := getConfig(ctx) | ||||
| 	db := getDB(ctx) | ||||
|  | ||||
| 	lines := make([]string, 0, 10) | ||||
| @ -132,46 +127,21 @@ func (p *playerInfo) updatePlayerInfo(ctx context.Context) error { | ||||
| 	text := strings.Join(lines, "\n") | ||||
|  | ||||
| 	if text != p.messageText { | ||||
| 		messStorage := getMessageStorage(ctx) | ||||
| 		err := messStorage.apply(ctx, fmt.Sprintf("playerBoard:%s", p.playerID), 0, func(interface{}) (string, interface{}) { | ||||
| 			return text, nil | ||||
| 		}) | ||||
|  | ||||
| 		var c tgbotapi.Chattable | ||||
|  | ||||
| 		if p.playerMessageID == 0 { | ||||
| 			mess := tgbotapi.NewMessage(conf.ChatID, text) | ||||
| 			mess.ParseMode = tgbotapi.ModeMarkdown | ||||
|  | ||||
| 			c = mess | ||||
| 		} else { | ||||
| 			mess := tgbotapi.NewEditMessageText(conf.ChatID, p.playerMessageID, text) | ||||
| 			mess.ParseMode = tgbotapi.ModeMarkdown | ||||
|  | ||||
| 			c = mess | ||||
| 		} | ||||
|  | ||||
| 		m, err := botApi.Send(c) | ||||
| 		if err != nil { | ||||
| 			return errors.Wrap(err, "Failed to send message") | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		p.playerMessageID = m.MessageID | ||||
| 		p.messageText = text | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| func (p *playerInfo) setAchievement(ach achievement) { | ||||
| 	for _, a := range p.achievements { | ||||
| 		if a == ach { | ||||
| @ -249,11 +219,13 @@ func (pb *playersBoard) getPlayerBoard(playerID string) *playerInfo { | ||||
| 	pb.mx.Lock() | ||||
| 	defer pb.mx.Unlock() | ||||
|  | ||||
| 	pb.players = append(pb.players, &playerInfo{ | ||||
| 	pi := &playerInfo{ | ||||
| 		playerID: playerID, | ||||
| 	}) | ||||
| 	} | ||||
|  | ||||
| 	return pb.players[len(pb.players)-1] | ||||
| 	pb.players = append(pb.players, pi) | ||||
|  | ||||
| 	return pi | ||||
| } | ||||
|  | ||||
| func (pb *playersBoard) updateAchievements(ctx context.Context, ach achievement) error { | ||||
| @ -347,19 +319,3 @@ func (pb *playersBoard) update(ctx context.Context, as ...achievement) error { | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| 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) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	