Rework architecture, fix env parsing

This commit is contained in:
2024-07-29 00:10:35 +03:00
parent e2af48ccd7
commit 8fa95db24b
7 changed files with 272 additions and 84 deletions
+51 -45
View File
@@ -1,66 +1,72 @@
package app
import (
"log"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
func NewAnonymousQuestionsService(bot *tgbotapi.BotAPI, ownerChatID int64) AnonymousMessagesService {
func NewAnonymousQuestionsService(api BotAPI, errorsChan chan error) AnonymousMessagesService {
return &anonymousMessagesService{
bot: bot,
ownerChatID: ownerChatID,
api: api,
errorsChan: errorsChan,
}
}
const (
messageSentReply = "*Сообщение отправлено!*"
newMessageNotification = "*Новое анонимное сообщение!*"
)
type AnonymousMessagesService interface {
ListenForMessages() error
ServeMessages() error
}
type anonymousMessagesService struct {
bot *tgbotapi.BotAPI
ownerChatID int64
api BotAPI
errorsChan chan error
}
func (s *anonymousMessagesService) ListenForMessages() error {
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := s.bot.GetUpdatesChan(u)
for update := range updates {
if update.Message == nil {
continue
func (s *anonymousMessagesService) ServeMessages() error {
return s.api.HandleUpdates(func(update MessageUpdate) {
if update.Command != nil {
err := s.handleCommand(update)
if err != nil {
s.errorsChan <- err
}
return
}
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
if update.Message.Text == "/start" {
reply := tgbotapi.NewMessage(update.Message.Chat.ID, "Жду твоих вопросов!")
s.bot.Send(reply)
continue
err := s.handleMessage(update.Message)
if err != nil {
s.errorsChan <- err
}
if len(update.Message.Photo) > 0 {
var photos []interface{}
photo := tgbotapi.NewInputMediaPhoto(tgbotapi.FileID(update.Message.Photo[0].FileID))
photo.Caption = "*Новое анонимное сообщение!*"
photo.ParseMode = tgbotapi.ModeMarkdown
photos = append(photos, photo)
mediaMsg := tgbotapi.NewMediaGroup(s.ownerChatID, photos)
s.bot.Send(mediaMsg)
} else {
msg := tgbotapi.NewMessage(s.ownerChatID, "*Новое анонимное сообщение!*\n\n"+update.Message.Text)
msg.ParseMode = tgbotapi.ModeMarkdown
s.bot.Send(msg)
err = s.pingClient(update.FromChatID)
if err != nil {
s.errorsChan <- err
}
})
}
reply := tgbotapi.NewMessage(update.Message.Chat.ID, "Сообщение отправлено!")
s.bot.Send(reply)
func (s *anonymousMessagesService) handleCommand(update MessageUpdate) error {
if update.Command == nil {
return nil
}
return nil
var msgText string
switch *update.Command {
case StartCommand:
msgText = "Жду твоих вопросов!"
case UnknownCommand:
msgText = "Неизвестная команда!"
}
return s.api.SendMessage(update.FromChatID, Message{Text: msgText})
}
func (s *anonymousMessagesService) pingClient(chatID int64) error {
return s.api.SendMessage(chatID, Message{Text: messageSentReply})
}
func (s *anonymousMessagesService) handleMessage(message Message) error {
msgText := newMessageNotification + "\n\n" + message.Text
return s.api.SendMessageToOwner(Message{
Text: msgText,
Image: message.Image,
})
}
+32
View File
@@ -0,0 +1,32 @@
package app
type BotAPI interface {
HandleUpdates(handler MessageUpdateHandler) error
SendMessage(chatID int64, message Message) error
SendMessageToOwner(message Message) error
}
type MessageUpdateHandler func(MessageUpdate)
type MessageUpdate struct {
Message
UpdateID int
FromChatID int64
Command *Command
}
type Message struct {
Text string
Image *Image
}
type Command int
const (
UnknownCommand Command = iota
StartCommand
)
type Image struct {
FileID string
}
+147
View File
@@ -0,0 +1,147 @@
package infrastructure
import (
"log"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/pkg/errors"
"github.com/nightnoryu/anon3anon/pkg/app"
)
const (
updateTimeoutInSeconds = 60
startCommand = "/start"
messageParseMode = tgbotapi.ModeMarkdown
)
type fileInfo struct {
FileID string
Size int
}
func NewBotAPI(bot *tgbotapi.BotAPI, ownerChatID int64) app.BotAPI {
return &botAPI{
bot: bot,
ownerChatID: ownerChatID,
}
}
type botAPI struct {
bot *tgbotapi.BotAPI
ownerChatID int64
}
func (api *botAPI) HandleUpdates(handler app.MessageUpdateHandler) error {
u := tgbotapi.NewUpdate(0)
u.Timeout = updateTimeoutInSeconds
updates := api.bot.GetUpdatesChan(u)
for update := range updates {
if update.Message == nil {
continue
}
log.Printf("%+v\n", update.Message)
messageUpdate := app.MessageUpdate{
Message: api.hydrateMessage(update.Message),
UpdateID: update.UpdateID,
FromChatID: update.FromChat().ID,
Command: api.hydrateCommand(update.Message),
}
handler(messageUpdate)
}
return nil
}
func (api *botAPI) SendMessage(chatID int64, message app.Message) error {
if message.Image != nil {
return api.sendPhotoMessage(chatID, message)
}
return api.sendTextMessage(chatID, message)
}
func (api *botAPI) SendMessageToOwner(message app.Message) error {
return api.SendMessage(api.ownerChatID, message)
}
func (api *botAPI) hydrateMessage(msg *tgbotapi.Message) app.Message {
text := msg.Text
if len(text) == 0 {
text = msg.Caption
}
return app.Message{
Text: text,
Image: api.hydrateImage(msg.Photo),
}
}
func (api *botAPI) sendTextMessage(chatID int64, message app.Message) error {
msg := tgbotapi.NewMessage(
chatID,
message.Text,
)
msg.ParseMode = messageParseMode
_, err := api.bot.Send(msg)
return errors.WithStack(err)
}
func (api *botAPI) sendPhotoMessage(chatID int64, message app.Message) error {
photos := api.preparePhotos(message)
mediaMsg := tgbotapi.NewMediaGroup(chatID, photos)
_, err := api.bot.Send(mediaMsg)
return errors.WithStack(err)
}
func (api *botAPI) hydrateCommand(msg *tgbotapi.Message) *app.Command {
if !msg.IsCommand() {
return nil
}
var cmd app.Command
switch msg.Command() {
case startCommand:
cmd = app.StartCommand
default:
cmd = app.UnknownCommand
}
return &cmd
}
func (api *botAPI) hydrateImage(photos []tgbotapi.PhotoSize) *app.Image {
if len(photos) == 0 {
return nil
}
var originalFileID string
var originalFileSize int
for _, photo := range photos {
if photo.FileSize > originalFileSize {
originalFileID = photo.FileID
originalFileSize = photo.FileSize
}
}
return &app.Image{
FileID: originalFileID,
}
}
func (api *botAPI) preparePhotos(message app.Message) []interface{} {
photo := tgbotapi.NewInputMediaPhoto(tgbotapi.FileID(message.Image.FileID))
photo.Caption = message.Text
photo.ParseMode = messageParseMode
var photos []interface{}
photos = append(photos, photo)
return photos
}