Spaces:
Paused
Paused
File size: 3,242 Bytes
49b198e f592c10 49b198e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | package bot
import (
"context"
"fmt"
"strings"
"time"
"github.com/celestix/gotgproto"
"github.com/celestix/gotgproto/sessionMaker"
"github.com/glebarez/sqlite"
"go.uber.org/zap"
)
// BotInfo contains information about a validated bot
type BotInfo struct {
ID int64 `json:"id"`
Username string `json:"username"`
FirstName string `json:"first_name"`
IsBot bool `json:"is_bot"`
}
// BotValidator handles bot token validation
type BotValidator struct {
log *zap.Logger
}
// NewBotValidator creates a new bot validator
func NewBotValidator(log *zap.Logger) *BotValidator {
return &BotValidator{
log: log.Named("BotValidator"),
}
}
// ValidateBotToken validates a bot token and returns bot information
func (bv *BotValidator) ValidateBotToken(token string) (*BotInfo, error) {
// Basic token format validation
if !bv.isValidTokenFormat(token) {
return nil, fmt.Errorf("invalid token format")
}
// Create a temporary client to test the token
_, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Use a temporary session file
tempSessionPath := fmt.Sprintf("/tmp/validate_%d.session", time.Now().UnixNano())
client, err := gotgproto.NewClient(
0, // We don't need API ID/Hash for bot validation
"",
gotgproto.ClientTypeBot(token),
&gotgproto.ClientOpts{
Session: sessionMaker.SqlSession(
sqlite.Open(tempSessionPath),
),
DisableCopyright: true,
},
)
if err != nil {
bv.log.Error("Failed to create validation client", zap.Error(err))
return nil, fmt.Errorf("invalid bot token: %w", err)
}
// Clean up the temporary session
defer func() {
if client != nil {
client.Stop()
}
}()
// Get bot information
self := client.Self
if self == nil {
return nil, fmt.Errorf("failed to get bot information")
}
if !self.Bot {
return nil, fmt.Errorf("token belongs to a user account, not a bot")
}
botInfo := &BotInfo{
ID: self.ID,
Username: self.Username,
FirstName: self.FirstName,
IsBot: self.Bot,
}
bv.log.Info("Successfully validated bot token",
zap.Int64("botID", botInfo.ID),
zap.String("username", botInfo.Username))
return botInfo, nil
}
// isValidTokenFormat checks if the token has the correct format
func (bv *BotValidator) isValidTokenFormat(token string) bool {
// Bot tokens have format: {bot_id}:{auth_token}
// Example: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz
if len(token) < 35 || len(token) > 50 {
return false
}
parts := strings.Split(token, ":")
if len(parts) != 2 {
return false
}
// First part should be numeric (bot ID)
botID := parts[0]
if len(botID) < 8 || len(botID) > 12 {
return false
}
for _, char := range botID {
if char < '0' || char > '9' {
return false
}
}
// Second part should be the auth token (alphanumeric + some special chars)
authToken := parts[1]
if len(authToken) < 25 || len(authToken) > 40 {
return false
}
return true
}
// TestBotPermissions tests if the bot has necessary permissions
func (bv *BotValidator) TestBotPermissions(token string) error {
// This could be extended to test specific permissions
// For now, just validate that we can create a client
_, err := bv.ValidateBotToken(token)
return err
} |