Skip to content

Commit

Permalink
switch to OvyFlash/telegram-bot-api (updated fork of the same lib)
Browse files Browse the repository at this point in the history
Everything left the same except
- "is_premium" flag about user is now known and logged
- username of the hidden user would be detected properly in more places
  • Loading branch information
paskal committed Nov 23, 2024
1 parent adc7198 commit 38b97cd
Show file tree
Hide file tree
Showing 26 changed files with 4,481 additions and 1,075 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data/ham-dynamic.txt
data/spam-dynamic.txt
data/tg-spam.db
data/tg-spam.db
docker-compose*.yml
94 changes: 71 additions & 23 deletions app/events/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"time"
"unicode/utf8"

tbapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
tbapi "github.com/OvyFlash/telegram-bot-api"
"github.com/hashicorp/go-multierror"

"github.com/umputun/tg-spam/app/bot"
Expand Down Expand Up @@ -64,15 +64,26 @@ func (a *admin) MsgHandler(update tbapi.Update) error {

// try to get the forwarded user ID, this is just for logging
var fwdID int64
if update.Message.ForwardFrom != nil {
fwdID = update.Message.ForwardFrom.ID
var username string
if update.Message.ForwardOrigin != nil {
if update.Message.ForwardOrigin.IsUser() {
fwdID = update.Message.ForwardOrigin.SenderUser.ID
username = update.Message.ForwardOrigin.SenderUser.UserName
}
if update.Message.ForwardOrigin.IsHiddenUser() {
username = update.Message.ForwardOrigin.SenderUserName
}
}

if update.Message.ForwardOrigin.IsChannel() {
log.Printf("[ERROR] sent from channel %d", update.Message.Chat.ID)
}

log.Printf("[DEBUG] message from admin chat: msg id: %d, update id: %d, from: %s, sender: %q (%d)",
update.Message.MessageID, update.UpdateID, update.Message.From.UserName,
update.Message.ForwardSenderName, fwdID)
username, fwdID)

if update.Message.ForwardSenderName == "" && update.Message.ForwardFrom == nil {
if username == "" && update.Message.ForwardOrigin == nil {
// this is a regular message from admin chat, not the forwarded one, ignore it
return nil
}
Expand Down Expand Up @@ -133,15 +144,20 @@ func (a *admin) MsgHandler(update tbapi.Update) error {
}

// delete message
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: info.MsgID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{
BaseChatMessage: tbapi.BaseChatMessage{
MessageID: info.MsgID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
},
}); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to delete message %d: %w", info.MsgID, err))
} else {
log.Printf("[INFO] message %d deleted", info.MsgID)
}

// ban user
banReq := banRequest{duration: bot.PermanentBanDuration, userID: info.UserID, chatID: a.primChatID,
tbAPI: a.tbAPI, dry: a.dry, training: a.trainingMode, userName: update.Message.ForwardSenderName}
tbAPI: a.tbAPI, dry: a.dry, training: a.trainingMode, userName: username}

if err := banUserOrChannel(banReq); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to ban user %d: %w", info.UserID, err))
Expand Down Expand Up @@ -182,14 +198,20 @@ func (a *admin) DirectWarnReport(update tbapi.Update) error {
}
errs := new(multierror.Error)
// delete original message
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: origMsg.MessageID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{BaseChatMessage: tbapi.BaseChatMessage{
MessageID: origMsg.MessageID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
}}); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to delete message %d: %w", origMsg.MessageID, err))
} else {
log.Printf("[INFO] warn message %d deleted", origMsg.MessageID)
}

// delete reply message
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: update.Message.MessageID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{BaseChatMessage: tbapi.BaseChatMessage{
MessageID: update.Message.MessageID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
}}); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to delete message %d: %w", update.Message.MessageID, err))
} else {
log.Printf("[INFO] admin warn reprot message %d deleted", update.Message.MessageID)
Expand Down Expand Up @@ -264,22 +286,38 @@ func (a *admin) directReport(update tbapi.Update, updateSamples bool) error {
}

// delete original message
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: origMsg.MessageID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{BaseChatMessage: tbapi.BaseChatMessage{
MessageID: origMsg.MessageID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
}}); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to delete message %d: %w", origMsg.MessageID, err))
} else {
log.Printf("[INFO] spam message %d deleted", origMsg.MessageID)
}

// delete reply message
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: update.Message.MessageID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{BaseChatMessage: tbapi.BaseChatMessage{
MessageID: update.Message.MessageID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
}}); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to delete message %d: %w", update.Message.MessageID, err))
} else {
log.Printf("[INFO] admin spam reprot message %d deleted", update.Message.MessageID)
}

var username string
if update.Message.ForwardOrigin != nil {
if update.Message.ForwardOrigin.IsUser() {
username = update.Message.ForwardOrigin.SenderUser.UserName
}
if update.Message.ForwardOrigin.IsHiddenUser() {
username = update.Message.ForwardOrigin.SenderUserName
}
}

// ban user
banReq := banRequest{duration: bot.PermanentBanDuration, userID: origMsg.From.ID, chatID: a.primChatID,
tbAPI: a.tbAPI, dry: a.dry, training: a.trainingMode, userName: update.Message.ForwardSenderName}
tbAPI: a.tbAPI, dry: a.dry, training: a.trainingMode, userName: username}

if err := banUserOrChannel(banReq); err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed to ban user %d: %w", origMsg.From.ID, err))
Expand Down Expand Up @@ -485,15 +523,22 @@ func (a *admin) callbackUnbanConfirmed(query *tbapi.CallbackQuery) error {
func (a *admin) unban(userID int64) error {
if a.softBan { // soft ban, just drop restrictions
_, err := a.tbAPI.Request(tbapi.RestrictChatMemberConfig{
ChatMemberConfig: tbapi.ChatMemberConfig{UserID: userID, ChatID: a.primChatID},
ChatMemberConfig: tbapi.ChatMemberConfig{UserID: userID, ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID}},
Permissions: &tbapi.ChatPermissions{
CanSendMessages: true,
CanSendMediaMessages: true,
CanSendOtherMessages: true,
CanSendPolls: true,
CanChangeInfo: true,
CanInviteUsers: true,
CanPinMessages: true,
CanSendMessages: true,
CanSendAudios: true,
CanSendDocuments: true,
CanSendPhotos: true,
CanSendVideos: true,
CanSendVideoNotes: true,
CanSendVoiceNotes: true,
CanSendPolls: true,
CanSendOtherMessages: true,
CanAddWebPagePreviews: true,
CanChangeInfo: true,
CanInviteUsers: true,
CanPinMessages: true,
CanManageTopics: true,
},
})
if err != nil {
Expand All @@ -504,7 +549,7 @@ func (a *admin) unban(userID int64) error {

// hard ban, unban the user for real
_, err := a.tbAPI.Request(tbapi.UnbanChatMemberConfig{
ChatMemberConfig: tbapi.ChatMemberConfig{UserID: userID, ChatID: a.primChatID}, OnlyIfBanned: true})
ChatMemberConfig: tbapi.ChatMemberConfig{UserID: userID, ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID}}, OnlyIfBanned: true})
// onlyIfBanned seems to prevent user from being removed from the chat according to this confusing doc:
// https://core.telegram.org/bots/api#unbanchatmember
if err != nil {
Expand Down Expand Up @@ -575,7 +620,10 @@ func (a *admin) deleteAndBan(query *tbapi.CallbackQuery, userID int64, msgID int
}

// we allow deleting messages from supers. This can be useful if super is training the bot by adding spam messages
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{ChatID: a.primChatID, MessageID: msgID}); err != nil {
if _, err := a.tbAPI.Request(tbapi.DeleteMessageConfig{BaseChatMessage: tbapi.BaseChatMessage{
MessageID: msgID,
ChatConfig: tbapi.ChatConfig{ChatID: a.primChatID},
}}); err != nil {
return fmt.Errorf("failed to delete message %d: %w", query.Message.MessageID, err)
}

Expand Down Expand Up @@ -637,7 +685,7 @@ func (a *admin) sendWithUnbanMarkup(text, action string, user bot.User, msgID in
log.Printf("[DEBUG] action response %q: user %+v, msgID:%d, text: %q", action, user, msgID, strings.ReplaceAll(text, "\n", "\\n"))
tbMsg := tbapi.NewMessage(chatID, text)
tbMsg.ParseMode = tbapi.ModeMarkdown
tbMsg.DisableWebPagePreview = true
tbMsg.LinkPreviewOptions = tbapi.LinkPreviewOptions{IsDisabled: true}

tbMsg.ReplyMarkup = tbapi.NewInlineKeyboardMarkup(
tbapi.NewInlineKeyboardRow(
Expand Down
2 changes: 1 addition & 1 deletion app/events/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package events
import (
"testing"

tbapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
tbapi "github.com/OvyFlash/telegram-bot-api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down
50 changes: 30 additions & 20 deletions app/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strings"
"time"

tbapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
tbapi "github.com/OvyFlash/telegram-bot-api"

"github.com/umputun/tg-spam/app/bot"
"github.com/umputun/tg-spam/app/storage"
Expand All @@ -22,7 +22,7 @@ type TbAPI interface {
GetUpdatesChan(config tbapi.UpdateConfig) tbapi.UpdatesChannel
Send(c tbapi.Chattable) (tbapi.Message, error)
Request(c tbapi.Chattable) (*tbapi.APIResponse, error)
GetChat(config tbapi.ChatInfoConfig) (tbapi.Chat, error)
GetChat(config tbapi.ChatInfoConfig) (tbapi.ChatFullInfo, error)
GetChatAdministrators(config tbapi.ChatAdministratorsConfig) ([]tbapi.ChatMember, error)
}

Expand Down Expand Up @@ -73,11 +73,11 @@ func send(tbMsg tbapi.Chattable, tbAPI TbAPI) error {
switch msg := tbMsg.(type) {
case tbapi.MessageConfig:
msg.ParseMode = parseMode
msg.DisableWebPagePreview = true
msg.LinkPreviewOptions = tbapi.LinkPreviewOptions{IsDisabled: true}
return msg
case tbapi.EditMessageTextConfig:
msg.ParseMode = parseMode
msg.DisableWebPagePreview = true
msg.LinkPreviewOptions = tbapi.LinkPreviewOptions{IsDisabled: true}
return msg
case tbapi.EditMessageReplyMarkupConfig:
return msg
Expand Down Expand Up @@ -122,13 +122,17 @@ func banUserOrChannel(r banRequest) error {
// In practice BanDuration is equal to ten minutes,
// so this `if` statement is unlikely to be evaluated to true.

bannedEntity := fmt.Sprintf("user %d", r.userID)
if r.channelID != 0 {
bannedEntity = fmt.Sprintf("channel %d", r.channelID)
}
if r.dry {
log.Printf("[INFO] dry run: ban %d for %v", r.userID, r.duration)
log.Printf("[INFO] dry run: ban %s for %v", bannedEntity, r.duration)
return nil
}

if r.training {
log.Printf("[INFO] training mode: ban %d for %v", r.userID, r.duration)
log.Printf("[INFO] training mode: ban %s for %v", bannedEntity, r.duration)
return nil
}

Expand All @@ -139,17 +143,25 @@ func banUserOrChannel(r banRequest) error {
if r.restrict { // soft ban mode
resp, err := r.tbAPI.Request(tbapi.RestrictChatMemberConfig{
ChatMemberConfig: tbapi.ChatMemberConfig{
ChatID: r.chatID,
UserID: r.userID,
ChatConfig: tbapi.ChatConfig{ChatID: r.chatID},
UserID: r.userID,
},
UntilDate: time.Now().Add(r.duration).Unix(),
Permissions: &tbapi.ChatPermissions{
CanSendMessages: false,
CanSendMediaMessages: false,
CanSendOtherMessages: false,
CanChangeInfo: false,
CanInviteUsers: false,
CanPinMessages: false,
CanSendMessages: false,
CanSendAudios: false,
CanSendDocuments: false,
CanSendPhotos: false,
CanSendVideos: false,
CanSendVideoNotes: false,
CanSendVoiceNotes: false,
CanSendPolls: false,
CanSendOtherMessages: false,
CanAddWebPagePreviews: false,
CanChangeInfo: false,
CanInviteUsers: false,
CanPinMessages: false,
CanManageTopics: false,
},
})
if err != nil {
Expand All @@ -164,7 +176,7 @@ func banUserOrChannel(r banRequest) error {

if r.channelID != 0 {
resp, err := r.tbAPI.Request(tbapi.BanChatSenderChatConfig{
ChatID: r.chatID,
ChatConfig: tbapi.ChatConfig{ChatID: r.chatID},
SenderChatID: r.channelID,
UntilDate: int(time.Now().Add(r.duration).Unix()),
})
Expand All @@ -180,8 +192,8 @@ func banUserOrChannel(r banRequest) error {

resp, err := r.tbAPI.Request(tbapi.BanChatMemberConfig{
ChatMemberConfig: tbapi.ChatMemberConfig{
ChatID: r.chatID,
UserID: r.userID,
ChatConfig: tbapi.ChatConfig{ChatID: r.chatID},
UserID: r.userID,
},
UntilDate: time.Now().Add(r.duration).Unix(),
})
Expand Down Expand Up @@ -229,9 +241,7 @@ func transform(msg *tbapi.Message) *bot.Message {
Text: msg.Text,
}

if msg.Chat != nil {
message.ChatID = msg.Chat.ID
}
message.ChatID = msg.Chat.ID

if msg.From != nil {
message.From = bot.User{
Expand Down
Loading

0 comments on commit 38b97cd

Please sign in to comment.