Rewrite everything with new framework

This commit is contained in:
2025-02-01 17:36:04 +03:00
parent 0a71122ba1
commit bb58f9bb7f
7 changed files with 56 additions and 442 deletions
-73
View File
@@ -1,73 +0,0 @@
package app
func NewAnonymousQuestionsService(
errorsChan chan error,
commandHandler CommandHandler,
api BotAPI,
) AnonymousMessagesService {
return &anonymousMessagesService{
errorsChan: errorsChan,
commandHandler: commandHandler,
api: api,
}
}
const (
messageSentReply = "*Сообщение отправлено!*"
unsupportedMessageReply = "*Такое сообщение не поддерживается :(*"
newMessageNotification = "Новое анонимное сообщение!"
)
type AnonymousMessagesService interface {
ServeMessages() error
}
type anonymousMessagesService struct {
errorsChan chan error
commandHandler CommandHandler
api BotAPI
}
func (s *anonymousMessagesService) ServeMessages() error {
return s.api.HandleUpdates(func(update MessageUpdate) {
if update.Command != nil {
err := s.commandHandler.HandleCommand(update)
if err != nil {
s.errorsChan <- err
}
return
}
if update.Message.Sticker != nil {
err := s.api.SendMessage(update.FromChatID, Message{
Text: unsupportedMessageReply,
UseMarkdown: true,
})
if err != nil {
s.errorsChan <- err
}
return
}
notificationText := newMessageNotification + "\n\n" + update.Message.Text
err := s.api.SendMessageToOwner(Message{
Text: notificationText,
Image: update.Message.Image,
Audio: update.Message.Audio,
Video: update.Message.Video,
Voice: update.Message.Voice,
})
if err != nil {
s.errorsChan <- err
}
err = s.api.SendMessage(update.FromChatID, Message{
Text: messageSentReply,
UseMarkdown: true,
})
if err != nil {
s.errorsChan <- err
}
})
}
-55
View File
@@ -1,55 +0,0 @@
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
UseMarkdown bool
Image *Image
Audio *Audio
Video *Video
Sticker *Sticker
Voice *Voice
}
type Image struct {
FileID string
}
type Audio struct {
FileID string
}
type Video struct {
FileID string
}
type Sticker struct {
FileID string
Emoji string
}
type Voice struct {
FileID string
}
type Command int
const (
UnknownCommand Command = iota
StartCommand
InfoCommand
)
-33
View File
@@ -1,33 +0,0 @@
package app
func NewCommandHandler(api BotAPI) CommandHandler {
return &commandHandler{
api: api,
}
}
type CommandHandler interface {
HandleCommand(update MessageUpdate) error
}
type commandHandler struct {
api BotAPI
}
func (h *commandHandler) HandleCommand(update MessageUpdate) error {
if update.Command == nil {
return nil
}
var msgText string
switch *update.Command {
case StartCommand:
msgText = "Жду твоих вопросов!!\nОтветы будут в канале @meme_me_a_meme (>ᴗ•)"
case InfoCommand:
msgText = "Бот привязан к каналу @meme_me_a_meme, так что ответы ищи там!!\nНа данный момент поддерживаются текст, фото и видео („• ᴗ •„)"
case UnknownCommand:
msgText = "Неизвестная команда!"
}
return h.api.SendMessage(update.FromChatID, Message{Text: msgText})
}
-258
View File
@@ -1,258 +0,0 @@
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"
infoCommand = "info"
)
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)
}
if message.Audio != nil {
return api.sendAudioMessage(chatID, message)
}
if message.Video != nil {
return api.sendVideoMessage(chatID, message)
}
if message.Voice != nil {
return api.sendVoiceMessage(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),
Audio: api.hydrateAudio(msg.Audio),
Video: api.hydrateVideo(msg.Video),
Sticker: api.hydrateSticker(msg.Sticker),
Voice: api.hydrateVoice(msg.Voice),
}
}
func (api *botAPI) sendTextMessage(chatID int64, message app.Message) error {
msg := tgbotapi.NewMessage(
chatID,
message.Text,
)
if message.UseMarkdown {
msg.ParseMode = tgbotapi.ModeMarkdown
}
_, 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) sendAudioMessage(chatID int64, message app.Message) error {
audios := api.prepareAudio(message)
mediaMsg := tgbotapi.NewMediaGroup(chatID, audios)
_, err := api.bot.Send(mediaMsg)
return errors.WithStack(err)
}
func (api *botAPI) sendVideoMessage(chatID int64, message app.Message) error {
video := api.prepareVideo(message)
mediaMsg := tgbotapi.NewMediaGroup(chatID, video)
_, err := api.bot.Send(mediaMsg)
return errors.WithStack(err)
}
func (api *botAPI) sendVoiceMessage(chatID int64, message app.Message) error {
voiceMsg := tgbotapi.NewVoice(chatID, tgbotapi.FileID(message.Voice.FileID))
voiceMsg.Caption = message.Text
if message.UseMarkdown {
voiceMsg.ParseMode = tgbotapi.ModeMarkdown
}
_, err := api.bot.Send(voiceMsg)
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
case infoCommand:
cmd = app.InfoCommand
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) hydrateAudio(audio *tgbotapi.Audio) *app.Audio {
if audio == nil {
return nil
}
return &app.Audio{
FileID: audio.FileID,
}
}
func (api *botAPI) hydrateVideo(video *tgbotapi.Video) *app.Video {
if video == nil {
return nil
}
return &app.Video{
FileID: video.FileID,
}
}
func (api *botAPI) hydrateSticker(sticker *tgbotapi.Sticker) *app.Sticker {
if sticker == nil {
return nil
}
return &app.Sticker{
FileID: sticker.FileID,
Emoji: sticker.Emoji,
}
}
func (api *botAPI) hydrateVoice(voice *tgbotapi.Voice) *app.Voice {
if voice == nil {
return nil
}
return &app.Voice{
FileID: voice.FileID,
}
}
func (api *botAPI) preparePhotos(message app.Message) []interface{} {
photo := tgbotapi.NewInputMediaPhoto(tgbotapi.FileID(message.Image.FileID))
photo.Caption = message.Text
if message.UseMarkdown {
photo.ParseMode = tgbotapi.ModeMarkdown
}
var photos []interface{}
photos = append(photos, photo)
return photos
}
func (api *botAPI) prepareAudio(message app.Message) []interface{} {
audio := tgbotapi.NewInputMediaAudio(tgbotapi.FileID(message.Audio.FileID))
audio.Caption = message.Text
if message.UseMarkdown {
audio.ParseMode = tgbotapi.ModeMarkdown
}
return []interface{}{audio}
}
func (api *botAPI) prepareVideo(message app.Message) []interface{} {
video := tgbotapi.NewInputMediaVideo(tgbotapi.FileID(message.Video.FileID))
video.Caption = message.Text
if message.UseMarkdown {
video.ParseMode = tgbotapi.ModeMarkdown
}
return []interface{}{video}
}