Фраги приходят в одно сообщение и добавляют цифру, если это тот же тип фрага. Сообщения не удаляются дольше, если недавно был сделан такой же фраг #1
							
								
								
									
										16
									
								
								context.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								context.go
									
									
									
									
									
								
							| @ -2,9 +2,10 @@ package main | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"github.com/sirupsen/logrus" |  | ||||||
| 	"os" | 	"os" | ||||||
|  |  | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  |  | ||||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -19,6 +20,7 @@ const ( | |||||||
| 	ctxKeyMessageCleaner | 	ctxKeyMessageCleaner | ||||||
| 	ctxKeyDataBase | 	ctxKeyDataBase | ||||||
| 	ctxKeyPlayersBoard | 	ctxKeyPlayersBoard | ||||||
|  | 	ctxKeyFragMessages | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func createLogger(debug bool) *logrus.Logger { | 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, cancelFunc := context.WithCancel(context.Background()) | ||||||
|  |  | ||||||
| 	ctx = context.WithValue(ctx, ctxKeyLogger, createLogger(true)) | 	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, ctxKeyCommandHandler, ch) | ||||||
| 	ctx = context.WithValue(ctx, ctxKeyDataBase, db) | 	ctx = context.WithValue(ctx, ctxKeyDataBase, db) | ||||||
| 	ctx = context.WithValue(ctx, ctxKeyPlayersBoard, pb) | 	ctx = context.WithValue(ctx, ctxKeyPlayersBoard, pb) | ||||||
|  | 	ctx = context.WithValue(ctx, ctxKeyFragMessages, fms) | ||||||
|  |  | ||||||
| 	return ctx, cancelFunc | 	return ctx, cancelFunc | ||||||
| } | } | ||||||
| @ -118,3 +121,12 @@ func getDPlayersBoard(ctx context.Context) *playersBoard { | |||||||
|  |  | ||||||
| 	panic("Failed to get players board from ctx") | 	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") | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										79
									
								
								fragMessages.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								fragMessages.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | |||||||
|  | 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 x *%d*", fm.playerName, fm.entityName, fm.fragCount)) | ||||||
|  | 			_, 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) { | func (c *killCommand) run(ctx context.Context) { | ||||||
| 	botApi := getBotApi(ctx) |  | ||||||
| 	cfg := getConfig(ctx) |  | ||||||
| 	mc := getMessageCleaner(ctx) |  | ||||||
| 	db := getDB(ctx) | 	db := getDB(ctx) | ||||||
| 	log := getLogger(ctx) | 	log := getLogger(ctx) | ||||||
| 	pb := getDPlayersBoard(ctx) | 	pb := getDPlayersBoard(ctx) | ||||||
|  | 	fms := getFragMessages(ctx) | ||||||
|  |  | ||||||
| 	mess := tgbotapi.NewMessage(cfg.ChatID, fmt.Sprintf("%s убил %s", c.name, c.entity)) | 	err := fms.addFrag(ctx, c.name, c.entity) | ||||||
| 	m, err := botApi.Send(mess) |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error(err) | 		log.Error(err) | ||||||
| 	} else { | 		return | ||||||
| 		mc.add(ctx, m.MessageID, cfg.ChatID, time.Second*30) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	p, err := db.getPlayerByName(ctx, c.name) | 	p, err := db.getPlayerByName(ctx, c.name) | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							| @ -61,7 +61,9 @@ func main() { | |||||||
|  |  | ||||||
| 	pb := newPlayersBoard() | 	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...") | 	getLogger(ctx).Infof("Run...") | ||||||
|  |  | ||||||
|  | |||||||
| @ -8,32 +8,84 @@ import ( | |||||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type messageToClean struct { | ||||||
|  | 	messID int | ||||||
|  | 	chatID int64 | ||||||
|  | 	timer  *time.Timer | ||||||
|  | } | ||||||
|  |  | ||||||
| type messageCleaner struct { | type messageCleaner struct { | ||||||
| 	botApi   *tgbotapi.BotAPI | 	botApi   *tgbotapi.BotAPI | ||||||
| 	wg       *sync.WaitGroup | 	wg       *sync.WaitGroup | ||||||
|  | 	messages []*messageToClean | ||||||
|  | 	mx       sync.Mutex | ||||||
| } | } | ||||||
|  |  | ||||||
| func newMessageCleaner(bot *tgbotapi.BotAPI, wg *sync.WaitGroup) *messageCleaner { | func newMessageCleaner(bot *tgbotapi.BotAPI, wg *sync.WaitGroup) *messageCleaner { | ||||||
| 	return &messageCleaner{ | 	return &messageCleaner{ | ||||||
| 		botApi:   bot, | 		botApi:   bot, | ||||||
| 		wg:       wg, | 		wg:       wg, | ||||||
|  | 		messages: make([]*messageToClean, 0), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (m *messageCleaner) add(ctx context.Context, messID int, chatID int64, d time.Duration) { | 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) | 	m.wg.Add(1) | ||||||
|  |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		defer m.wg.Done() | 		defer m.wg.Done() | ||||||
|  |  | ||||||
|  | 		ms := &messageToClean{ | ||||||
|  | 			messID: messID, | ||||||
|  | 			chatID: chatID, | ||||||
|  | 			timer:  time.NewTimer(d), | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		m.messages = append(m.messages, ms) | ||||||
|  |  | ||||||
| 		select { | 		select { | ||||||
| 		case <-time.NewTimer(d).C: | 		case <-ms.timer.C: | ||||||
| 		case <-ctx.Done(): | 		case <-ctx.Done(): | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		m.remove(messID, chatID) | ||||||
|  |  | ||||||
| 		_, _ = m.botApi.DeleteMessage(tgbotapi.DeleteMessageConfig{ | 		_, _ = m.botApi.DeleteMessage(tgbotapi.DeleteMessageConfig{ | ||||||
| 			MessageID: messID, | 			MessageID: messID, | ||||||
| 			ChatID:    chatID, | 			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