mirror of
https://github.com/HugeFrog24/go-telegram-bot.git
synced 2026-03-02 00:14:34 +00:00
md formatting doesnt work yet Started implementing owner feature Add .gitattributes to enforce LF line endings Temporary commit before merge Updated owner management Updated json and gitignore Proceed with role management Again, CI Fix some lint errors Implemented screening Per-bot API keys implemented Use getRoleByName func Fix unused imports Upgrade actions rm unused function Upgrade action Fix unaddressed errors
190 lines
5.6 KiB
Go
190 lines
5.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"strings"
|
|
|
|
"github.com/go-telegram/bot"
|
|
"github.com/go-telegram/bot/models"
|
|
"github.com/liushuangls/go-anthropic/v2"
|
|
)
|
|
|
|
func (b *Bot) handleUpdate(ctx context.Context, tgBot *bot.Bot, update *models.Update) {
|
|
var message *models.Message
|
|
|
|
if update.Message != nil {
|
|
message = update.Message
|
|
} else if update.BusinessMessage != nil {
|
|
message = update.BusinessMessage
|
|
} else {
|
|
// No message to process
|
|
return
|
|
}
|
|
|
|
// Extract businessConnectionID if available
|
|
var businessConnectionID string
|
|
if update.BusinessConnection != nil {
|
|
businessConnectionID = update.BusinessConnection.ID
|
|
} else if message.BusinessConnectionID != "" {
|
|
businessConnectionID = message.BusinessConnectionID
|
|
}
|
|
|
|
chatID := message.Chat.ID
|
|
userID := message.From.ID
|
|
username := message.From.Username
|
|
text := message.Text
|
|
|
|
// Pass the incoming message through the centralized screen for storage
|
|
_, err := b.screenIncomingMessage(message)
|
|
if err != nil {
|
|
log.Printf("Error storing user message: %v", err)
|
|
return
|
|
}
|
|
|
|
// Check if the message is a command
|
|
if message.Entities != nil {
|
|
for _, entity := range message.Entities {
|
|
if entity.Type == "bot_command" {
|
|
command := strings.TrimSpace(message.Text[entity.Offset : entity.Offset+entity.Length])
|
|
switch command {
|
|
case "/stats":
|
|
b.sendStats(ctx, chatID, userID, username, businessConnectionID)
|
|
return
|
|
case "/whoami":
|
|
b.sendWhoAmI(ctx, chatID, userID, username, businessConnectionID)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if the message contains a sticker
|
|
if message.Sticker != nil {
|
|
b.handleStickerMessage(ctx, chatID, userID, message, businessConnectionID)
|
|
return
|
|
}
|
|
|
|
// Rate limit check
|
|
if !b.checkRateLimits(userID) {
|
|
b.sendRateLimitExceededMessage(ctx, chatID, businessConnectionID)
|
|
return
|
|
}
|
|
|
|
// Proceed only if the message contains text
|
|
if text == "" {
|
|
log.Printf("Received a non-text message from user %d in chat %d", userID, chatID)
|
|
return
|
|
}
|
|
|
|
// Determine if the user is the owner
|
|
var isOwner bool
|
|
err = b.db.Where("telegram_id = ? AND bot_id = ? AND is_owner = ?", userID, b.botID, true).First(&User{}).Error
|
|
if err == nil {
|
|
isOwner = true
|
|
}
|
|
|
|
user, err := b.getOrCreateUser(userID, username, isOwner)
|
|
if err != nil {
|
|
log.Printf("Error getting or creating user: %v", err)
|
|
return
|
|
}
|
|
|
|
// Update the username if it's empty or has changed
|
|
if user.Username != username {
|
|
user.Username = username
|
|
if err := b.db.Save(&user).Error; err != nil {
|
|
log.Printf("Error updating user username: %v", err)
|
|
}
|
|
}
|
|
|
|
// Determine if the text contains only emojis
|
|
isEmojiOnly := isOnlyEmojis(text)
|
|
|
|
// Prepare context messages for Anthropic
|
|
chatMemory := b.getOrCreateChatMemory(chatID)
|
|
b.addMessageToChatMemory(chatMemory, b.createMessage(chatID, userID, username, user.Role.Name, text, true))
|
|
contextMessages := b.prepareContextMessages(chatMemory)
|
|
|
|
// Get response from Anthropic
|
|
response, err := b.getAnthropicResponse(ctx, contextMessages, b.isNewChat(chatID), isOwner, isEmojiOnly)
|
|
if err != nil {
|
|
log.Printf("Error getting Anthropic response: %v", err)
|
|
response = "I'm sorry, I'm having trouble processing your request right now."
|
|
}
|
|
|
|
// Send the response through the centralized screen
|
|
if err := b.sendResponse(ctx, chatID, response, businessConnectionID); err != nil {
|
|
log.Printf("Error sending response: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (b *Bot) sendRateLimitExceededMessage(ctx context.Context, chatID int64, businessConnectionID string) {
|
|
if err := b.sendResponse(ctx, chatID, "Rate limit exceeded. Please try again later.", businessConnectionID); err != nil {
|
|
log.Printf("Error sending rate limit exceeded message: %v", err)
|
|
}
|
|
}
|
|
|
|
func (b *Bot) handleStickerMessage(ctx context.Context, chatID, userID int64, message *models.Message, businessConnectionID string) {
|
|
username := message.From.Username
|
|
|
|
// Create the user message (without storing it manually)
|
|
userMessage := b.createMessage(chatID, userID, username, "user", "Sent a sticker.", true)
|
|
userMessage.StickerFileID = message.Sticker.FileID
|
|
|
|
// Safely store the Thumbnail's FileID if available
|
|
if message.Sticker.Thumbnail != nil {
|
|
userMessage.StickerPNGFile = message.Sticker.Thumbnail.FileID
|
|
}
|
|
|
|
// Update chat memory with the user message
|
|
chatMemory := b.getOrCreateChatMemory(chatID)
|
|
b.addMessageToChatMemory(chatMemory, userMessage)
|
|
|
|
// Generate AI response about the sticker
|
|
response, err := b.generateStickerResponse(ctx, userMessage)
|
|
if err != nil {
|
|
log.Printf("Error generating sticker response: %v", err)
|
|
// Provide a fallback dynamic response based on sticker type
|
|
if message.Sticker.IsAnimated {
|
|
response = "Wow, that's a cool animated sticker!"
|
|
} else if message.Sticker.IsVideo {
|
|
response = "Interesting video sticker!"
|
|
} else {
|
|
response = "That's a cool sticker!"
|
|
}
|
|
}
|
|
|
|
// Send the response through the centralized screen
|
|
if err := b.sendResponse(ctx, chatID, response, businessConnectionID); err != nil {
|
|
log.Printf("Error sending response: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (b *Bot) generateStickerResponse(ctx context.Context, message Message) (string, error) {
|
|
// Example: Use the sticker type to generate a response
|
|
if message.StickerFileID != "" {
|
|
// Prepare context with information about the sticker
|
|
contextMessages := []anthropic.Message{
|
|
{
|
|
Role: anthropic.RoleUser,
|
|
Content: []anthropic.MessageContent{
|
|
anthropic.NewTextMessageContent("User sent a sticker."),
|
|
},
|
|
},
|
|
}
|
|
|
|
// Since this is a sticker message, isEmojiOnly is false
|
|
response, err := b.getAnthropicResponse(ctx, contextMessages, false, false, false)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
return "Hmm, that's interesting!", nil
|
|
}
|