Фраги приходят в одно сообщение и добавляют цифру, если это тот же тип фрага. Сообщения не удаляются дольше, если недавно был сделан такой же фраг #1
| @ -15,7 +15,13 @@ steps: | ||||
|   - name: install | ||||
|     commands: | ||||
|       - make install | ||||
|     when: | ||||
|       branch: | ||||
|         - master | ||||
|  | ||||
|   - name: restart | ||||
|     commands: | ||||
|       - systemctl restart craft-bot | ||||
|     when: | ||||
|       branch: | ||||
|         - master | ||||
|  | ||||
							
								
								
									
										16
									
								
								context.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								context.go
									
									
									
									
									
								
							| @ -2,9 +2,10 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/sirupsen/logrus" | ||||
|  | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| @ -19,6 +20,7 @@ const ( | ||||
| 	ctxKeyMessageCleaner | ||||
| 	ctxKeyDataBase | ||||
| 	ctxKeyPlayersBoard | ||||
| 	ctxKeyFragMessages | ||||
| ) | ||||
|  | ||||
| func createLogger(debug bool) *logrus.Logger { | ||||
| @ -42,7 +44,7 @@ func createLogger(debug bool) *logrus.Logger { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func createContext(config *Config, bot *tgbotapi.BotAPI, mc *messageCleaner, ch *commandHandler, db *dbLayer, pb *playersBoard) (context.Context, func()) { | ||||
| func createContext(config *Config, bot *tgbotapi.BotAPI, mc *messageCleaner, ch *commandHandler, db *dbLayer, pb *playersBoard, fms *fragMessages) (context.Context, func()) { | ||||
| 	ctx, cancelFunc := context.WithCancel(context.Background()) | ||||
|  | ||||
| 	ctx = context.WithValue(ctx, ctxKeyLogger, createLogger(true)) | ||||
| @ -52,6 +54,7 @@ func createContext(config *Config, bot *tgbotapi.BotAPI, mc *messageCleaner, ch | ||||
| 	ctx = context.WithValue(ctx, ctxKeyCommandHandler, ch) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyDataBase, db) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyPlayersBoard, pb) | ||||
| 	ctx = context.WithValue(ctx, ctxKeyFragMessages, fms) | ||||
|  | ||||
| 	return ctx, cancelFunc | ||||
| } | ||||
| @ -118,3 +121,12 @@ 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 | ||||
| 	} | ||||
|  | ||||
| 	panic("Failed to get frag messages from ctx") | ||||
| } | ||||
|  | ||||
							
								
								
									
										84
									
								
								fragMessages.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								fragMessages.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| 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 | ||||
| 			_, err := botApi.Send(mess) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			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:      0, | ||||
| 		latestFragTime: time.Now(), | ||||
| 	} | ||||
|  | ||||
| 	fms.messages = append(fms.messages, fm) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										10
									
								
								handlers.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								handlers.go
									
									
									
									
									
								
							| @ -165,19 +165,15 @@ type killCommand struct { | ||||
| } | ||||
|  | ||||
| func (c *killCommand) run(ctx context.Context) { | ||||
| 	botApi := getBotApi(ctx) | ||||
| 	cfg := getConfig(ctx) | ||||
| 	mc := getMessageCleaner(ctx) | ||||
| 	db := getDB(ctx) | ||||
| 	log := getLogger(ctx) | ||||
| 	pb := getDPlayersBoard(ctx) | ||||
| 	fms := getFragMessages(ctx) | ||||
|  | ||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s убил %s", c.name, c.entity)) | ||||
| 	m, err := botApi.Send(mess) | ||||
| 	err := fms.addFrag(ctx, c.name, c.entity) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} else { | ||||
| 		mc.add(ctx, m.MessageID, cfg.ChatID, time.Second*30) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p, err := db.getPlayerByName(ctx, c.name) | ||||
|  | ||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							| @ -61,7 +61,9 @@ func main() { | ||||
|  | ||||
| 	pb := newPlayersBoard() | ||||
|  | ||||
| 	ctx, cancelFunc := createContext(&cfg, bot, mc, ch, db, pb) | ||||
| 	fms := newFragMessages() | ||||
|  | ||||
| 	ctx, cancelFunc := createContext(&cfg, bot, mc, ch, db, pb, fms) | ||||
|  | ||||
| 	getLogger(ctx).Infof("Run...") | ||||
|  | ||||
|  | ||||
| @ -8,32 +8,84 @@ import ( | ||||
| 	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 <-time.NewTimer(d).C: | ||||
| 		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 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user