ParsRubika

package module
v0.0.0-...-c71df16 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2025 License: MIT Imports: 17 Imported by: 0

README

🤖 ParsRubika - کتابخانه کامل Go برای ربات‌های روبیکا

Rubika Bot Go Version License Stars


🔗 مخزن گیت‌هاب:
https://github.com/Abolfazl-Zarei/ParsRubika-bot-go

👤 توسعه‌دهنده: ابوالفضل زارعی
📧 ایمیل: ninjacode.ir@gmail.com
🆔 روبیکا: NinjaCode
📢 چنل روبیکا: Ninja_code

📚 فهرست جامع

  1. 🎯 معرفی کامل
  2. ⚡ نصب و راه‌اندازی
  3. 🏗 مفاهیم پایه
  4. 🚀 شروع سریع
  5. 🛠 آموزش قدم به قدم
  6. 📡 API Reference
  7. 🎛 مدیریت وضعیت
  8. ⌨ کیبوردهای پویا
  9. 📁 مدیریت فایل‌ها
  10. 🌐 Webhook & Polling
  11. 🚀 مثال‌های پیشرفته
  12. ☁ استقرار و دیپلوی
  13. 🔧 عیب‌یابی
  14. 📞 پشتیبانی

🎯 معرفی کامل

✨ پارس روبیکا چیست؟

ParsRubika یک کتابخانه کاملاً فارسی و قدرتمند برای ساخت ربات‌های پیام‌رسان روبیکا با زبان Go است. این کتابخانه با معماری مدرن و امکانات پیشرفته، توسعه ربات‌های حرفه‌ای را برای شما ساده می‌کند.

🌟 چرا ParsRubika؟
ویژگی 🎯 توضیح
✅ پشتیبانی کامل API تمام متدهای رسمی روبیکا
🔄 دو روش دریافت Polling و Webhook
🎛 مدیریت وضعیت State Management پیشرفته
📁 آپلود/دانلود پشتیبانی از تمام فرمت‌ها
⌨ کیبوردهای پویا انواع دکمه و اینترفیس
🛡 خطایابی هوشمند مدیریت خودکار خطاها
⚡ Performance بالا بهینه‌شده برای سرعت
📚 مستندات کامل آموزش‌های قدم به قدم
🔄 Hot-Reload بارگذاری مجدد کد بدون توقف
🛡️ Anti-Spam جلوگیری از اسپم کاربران
🌐 Network Stability مدیریت پایداری شبکه
🏗 معماری کتابخانه
📦 ParsRubika/
├── 📄 client.go          # 🎯 کلاینت اصلی و منطق کسب‌وکار
├── 🏷️ models.go          # 📊 مدل‌های داده و ساختارها
├── 🔢 enums.go           # 🎮 انواع شمارشی و ثابت‌ها
├── ❌ errors.go          # 🚨 مدیریت خطاها
├── 🔄 polling.go         # 📡 سیستم پولینگ
├── 🌐 webhook.go         # 🌍 سیستم وب‌هوک
├── 💾 state.go           # 💡 مدیریت وضعیت کاربران
├── 🛡️ antispam.go        # 🔒 سیستم ضد اسپم
├── 🔄 reload.go          # 🔄 مدیریت Hot-Reload
├── 🌐 network.go         # 🌐 مدیریت پایداری شبکه
├── 📝 formatting.go      # 📝 فرمت‌بندی پیام‌ها و کیبوردها
└── 📋 go.mod            # 📦 وابستگی‌های پروژه

⚡ نصب و راه‌اندازی

📋 پیش‌نیازها
1. نصب Go
# 🐧 اوبونتی/دبیان
sudo apt update && sudo apt install golang-go

# 🍎 مک
brew install go

# 🪟 ویندوز
# از سایت https://golang.org/dl دانلود کنید
2. بررسی نسخه Go
go version
# خروجی باید باشد: go version go1.21.x یا بالاتر
3. دریافت توکن ربات
  1. در روبیکا به @BotFather مراجعه کنید
  2. دستور /newbot را ارسال کنید
  3. نام ربات را وارد کنید (مثال: MyAwesomeBot)
  4. یوزرنیم ربات را وارد کنید (مثال: my_awesome_bot)
  5. توکن دریافتی را ذخیره کنید
📥 نصب کتابخانه
روش 1: نصب مستقیم از گیت‌هاب
go get github.com/Abolfazl-Zarei/ParsRubika-bot-go
روش 2: کلون کردن مخزن
git clone https://github.com/Abolfazl-Zarei/ParsRubika-bot-go.git
cd ParsRubika-bot-go
روش 3: استفاده در پروژه جدید
mkdir my-rubika-bot
cd my-rubika-bot
go mod init my-rubika-bot
go get github.com/Abolfazl-Zarei/ParsRubika-bot-go

🏗 مفاهیم پایه

🎮 ساختار اصلی آپدیت‌ها
// 📨 ساختار Update - اصلی‌ترین بخش کتابخانه
type Update struct {
    Type             UpdateTypeEnum `json:"type"`              // 🏷️ نوع آپدیت
    ChatID           string         `json:"chat_id"`           // 💬 شناسه چت
    RemovedMessageID *string        `json:"removed_message_id"`// 🗑️ شناسه پیام حذف شده
    NewMessage       *Message       `json:"new_message"`       // 📩 پیام جدید
    UpdatedMessage   *Message       `json:"updated_message"`   // ✏️ پیام ویرایش شده
    UpdatedPayment   *PaymentStatus `json:"updated_payment"`   // 💰 وضعیت پرداخت
}
📧 انواع آپدیت‌ها
// 🎯 انواع مختلف آپدیت‌هایی که ربات دریافت می‌کند
const (
    UpdatedMessage UpdateTypeEnum = "UpdatedMessage"  // ✏️ ویرایش پیام
    NewMessage     UpdateTypeEnum = "NewMessage"      // 📩 پیام جدید
    RemovedMessage UpdateTypeEnum = "RemovedMessage"  // 🗑️ حذف پیام
    StartedBot     UpdateTypeEnum = "StartedBot"      // 🚀 شروع بات
    StoppedBot     UpdateTypeEnum = "StoppedBot"      // 🛑 توقف بات
    CallbackQuery  UpdateTypeEnum = "CallbackQuery"   // 🔘 کوئری دکمه
    InlineQuery    UpdateTypeEnum = "InlineQuery"     // 🔍 کوئری اینلاین
)
💌 ساختار پیام
// 📝 ساختار کامل یک پیام
type Message struct {
    MessageID        string            `json:"message_id"`         // 🔢 شناسه پیام
    Text             string            `json:"text"`               // 📄 متن پیام
    Time             string            `json:"time"`               // ⏰ زمان ارسال
    IsEdited         bool              `json:"is_edited"`          // ✏️ آیا ویرایش شده
    SenderType       MessageSenderEnum `json:"sender_type"`        // 👤 نوع فرستنده
    SenderID         string            `json:"sender_id"`          // 🆔 شناسه فرستنده
    AuxData          *AuxData          `json:"aux_data"`           // 🔗 داده‌های کمکی
    File             *File             `json:"file"`               // 📁 فایل پیام
    ReplyToMessageID string            `json:"reply_to_message_id"`// ↩️ پاسخ به پیام
    ForwardedFrom    *ForwardedFrom    `json:"forwarded_from"`     // ↪️ اطلاعات فوروارد
    Location         *Location         `json:"location"`           // 📍 موقعیت مکانی
    Sticker          *Sticker          `json:"sticker"`            // 🎨 استیکر
    ContactMessage   *ContactMessage   `json:"contact_message"`    // 👥 مخاطب
    Poll             *Poll             `json:"poll"`               // 📊 نظرسنجی
    Payment          *PaymentStatus    `json:"payment"`            // 💰 وضعیت پرداخت
}
🤖 ساختار کلاینت
// 🤖 ساختار اصلی کلاینت بات
type BotClient struct {
    token        string
    baseURL      string
    httpClient   *http.Client
    botID        string
    mu           sync.RWMutex
    lastSentTime time.Time

    // مدیریت وضعیت
    isRunning bool
    stopChan  chan struct{}

    // هندلرها و میدلورها
    handlers      []Handler
    middlewares   []MiddlewareFunc
    updateFilters []FilterFunc

    // نرخ محدودیت
    rateLimitDuration time.Duration
    maxRetries        int

    // قابلیت‌های جدید
    antiSpam                *AntiSpam
    hotReloadEnabled        bool
    stateManager            *StateManager
    ignoreTimeout           bool
    metadata                map[string]interface{}
    reloadManager           *ReloadManager
    networkStabilityManager *NetworkStabilityManager
}

🚀 شروع سریع

🎯 اولین ربات شما در 5 دقیقه!
1. ایجاد فایل اصلی
// 📄 main.go
package main

import (
    "context"
    "log"
    "os"
    
    // 📦 ایمپورت کتابخانه ParsRubika
    ParsRubika "github.com/Abolfazl-Zarei/ParsRubika-bot-go"
)

func main() {
    // 🔑 دریافت توکن از متغیر محیطی
    botToken := os.Getenv("RUBIKA_BOT_TOKEN")
    if botToken == "" {
        log.Fatal("❌ توکن ربات یافت نشد! لطفا متغیر محیطی RUBIKA_BOT_TOKEN را تنظیم کنید.")
    }
    
    // 🤖 ایجاد نمونه ربات با گزینه‌های پیشرفته
    bot := ParsRubika.NewClient(botToken,
        ParsRubika.WithRateLimitDelay(1*time.Second), // تأخیر بین درخواست‌ها
        ParsRubika.WithMaxRetries(3),                 // حداکثر تلاش مجدد
        ParsRubika.WithIgnoreTimeout(true),           // نادیده گرفتن خطاهای timeout
        ParsRubika.WithHotReload(true),               // فعال‌سازی Hot-Reload
    )
    
    // 🎯 تنظیم هندلر برای پیام‌ها
    bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage != nil {
            // 📨 پاسخ به پیام کاربر
            _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
                ChatID: update.ChatID,
                Text:   "👋 سلام! من با ParsRubika ساخته شده‌ام! 🚀",
            })
            return err
        }
        return nil
    })
    
    // 🚀 اجرای ربات
    ctx := context.Background()
    log.Println("🤖 ربات در حال راه‌اندازی...")
    if err := bot.Run(ctx); err != nil {
        log.Fatal("💥 خطا در اجرای ربات:", err)
    }
}
2. اجرای ربات
# 🔑 تنظیم توکن
export RUBIKA_BOT_TOKEN="your_bot_token_here"

# 🚀 اجرا
go run main.go
3. خروجی مورد انتظار
🤖 ربات در حال راه‌اندازی...
✅ بات با شناسه [BOT_ID] مقداردهی اولیه شد
🚀 بات شروع به کار کرد
📡 شروع پولینگ...

🛠 آموزش قدم به قدم

📁 قدم 1: ایجاد ساختار پروژه
# 📂 ایجاد پوشه پروژه
mkdir my-advanced-bot
cd my-advanced-bot

# 📦 مقداردهی اولیه پروژه Go
go mod init my-advanced-bot

# 📥 نصب کتابخانه ParsRubika
go get github.com/Abolfazl-Zarei/ParsRubika-bot-go

# 📄 ایجاد فایل‌های پروژه
touch main.go handlers.go utils.go
📄 قدم 2: فایل اصلی (main.go)
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "strings"
    "time"
    
    ParsRubika "github.com/Abolfazl-Zarei/ParsRubika-bot-go"
)

func main() {
    // 🔐 دریافت توکن ربات
    token := os.Getenv("RUBIKA_BOT_TOKEN")
    if token == "" {
        log.Fatal(`
        ❌ خطا: توکن ربات تنظیم نشده است!
        
        📝 راه‌حل:
        1. توکن ربات خود را از @rubika_bot دریافت کنید
        2. متغیر محیطی تنظیم کنید:
           export RUBIKA_BOT_TOKEN="your_token_here"
        3. یا مستقیماً در کد قرار دهید (غیرامن)
        `)
    }
    
    // 🤖 ایجاد نمونه ربات با تمام قابلیت‌ها
    bot := ParsRubika.NewClient(token,
        ParsRubika.WithRateLimitDelay(1*time.Second),
        ParsRubika.WithMaxRetries(3),
        ParsRubika.WithIgnoreTimeout(true),
        ParsRubika.WithHotReload(true),
    )
    
    // ⚙️ تنظیم هندلرها
    setupHandlers(bot)
    
    // 🚀 اجرای ربات
    ctx := context.Background()
    log.Println(`
    🎉 ربات در حال راه‌اندازی...
    📍 برای توقف: Ctrl+C
    📱 برای تست: به ربات پیام بدهید!
    `)
    
    if err := bot.Run(ctx); err != nil {
        log.Fatalf("💥 خطا در اجرای ربات: %v", err)
    }
}

// ⚙️ تنظیم تمام هندلرها
func setupHandlers(bot *ParsRubika.BotClient) {
    // 📨 هندلر اصلی پیام‌ها
    bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage == nil {
            return nil
        }
        
        msg := update.NewMessage
        chatID := update.ChatID
        userID := msg.SenderID
        
        // 🛡️ بررسی ضد اسپم
        if !bot.CheckAntiSpam(userID) {
            _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
                ChatID: chatID,
                Text:   "⚠️ لطفاً کمی صبر کنید و درخواست‌های خود را با فاصله ارسال کنید.",
            })
            return err
        }
        
        // 🎯 مسیریابی دستورات
        switch {
        case msg.Text == "/start":
            return handleStart(ctx, bot, chatID)
        case msg.Text == "/help":
            return handleHelp(ctx, bot, chatID)
        case strings.HasPrefix(msg.Text, "/echo"):
            return handleEcho(ctx, bot, chatID, msg.Text)
        case msg.Text == "/info":
            return handleInfo(ctx, bot, update)
        case msg.Text == "/state":
            return handleStateDemo(ctx, bot, chatID, userID)
        default:
            return handleDefault(ctx, bot, chatID, msg.Text)
        }
    })
    
    // 🔔 هندلر شروع رات
    bot.OnStart(func(ctx context.Context, update *ParsRubika.Update) error {
        log.Println("✅ ربات با موفقیت راه‌اندازی شد!")
        return nil
    })
    
    // 🎨 هندلر برای پیام‌های عکس
    bot.OnPhoto(func(ctx context.Context, update *ParsRubika.Update) error {
        _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: update.ChatID,
            Text:   "🖼️ عکس زیبایی ارسال کردید! 📸",
        })
        return err
    })
    
    // 🎵 هندلر برای پیام‌های صوتی
    bot.OnAudio(func(ctx context.Context, update *ParsRubika.Update) error {
        _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: update.ChatID,
            Text:   "🎵 موسیقی زیبایی است! 🎶",
        })
        return err
    })
    
    // 📍 هندلر برای پیام‌های موقعیت مکانی
    bot.OnLocation(func(ctx context.Context, update *ParsRubika.Update) error {
        _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: update.ChatID,
            Text:   "📍 مکان شما دریافت شد! 🗺️",
        })
        return err
    })
}
📄 قدم 3: هندلرها (handlers.go)
package main

import (
    "context"
    "fmt"
    "strings"
    
    ParsRubika "github.com/Abolfazl-Zarei/ParsRubika-bot-go"
)

// 🎯 هندلر دستور /start
func handleStart(ctx context.Context, bot *ParsRubika.BotClient, chatID string) error {
    welcomeText := `🎉 **به ربات خوش آمدید!**

🤖 **من یک ربات روبیکا هستم که با ParsRubika ساخته شده‌ام**

📋 **دستورات موجود:**
/start - نمایش این پیام
/help - راهنمای کامل ربات  
/echo [متن] - تکرار متن شما
/info - اطلاعات کاربر
/state - نمایش وضعیت فعلی شما

🔧 **ساخته شده با:** 
• زبان Go 🦫
• کتابخانه ParsRubika 🚀
• توسط NinjaCode 👨‍💻

💡 **شروع کنید:** یک دستور ارسال کنید یا پیام دلخواه بفرستید!`
    
    // 📨 ارسال پیام با کیبورد
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   welcomeText,
        ReplyKeyboardMarkup: createMainMenuKeyboard(),
    })
    return err
}

// 🆘 هندلر دستور /help
func handleHelp(ctx context.Context, bot *ParsRubika.BotClient, chatID string) error {
    helpText := `📚 **راهنمای کامل ربات**

🎯 **دستورات اصلی:**
🔹 /start - شروع کار با ربات
🔹 /help - نمایش این راهنما  
🔹 /echo [متن] - ارسال متن به ربات
🔹 /info - دریافت اطلاعات کاربر
🔹 /state - نمایش وضعیت فعلی

🛠 **امکانات پیشرفته:**
• 📨 ارسال پیام‌های متنی
• 🖼 ارسال عکس و مدیا
• 📍 ارسال موقعیت مکانی
• 📊 ایجاد نظرسنجی
• ⌨️ کیبوردهای تعاملی
• 🛡️ سیستم ضد اسپم
• 💾 مدیریت وضعیت

💡 **نکات:**
• شما می‌توانید هر متنی را برای ربات ارسال کنید
• ربات به تمام پیام‌ها پاسخ می‌دهد
• از دستورات برای قابلیت‌های خاص استفاده کنید

🔗 **پشتیبانی:** 
برای گزارش مشکل یا پیشنهاد به @NinjaCode پیام دهید`
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   helpText,
    })
    return err
}

// 🔄 هندلر دستور /echo
func handleEcho(ctx context.Context, bot *ParsRubika.BotClient, chatID, text string) error {
    // حذف "/echo" از متن
    echoText := strings.TrimSpace(strings.TrimPrefix(text, "/echo"))
    
    if echoText == "" {
        echoText = "📝 لطفا متنی برای تکرار وارد کنید.\n\n💡 **مثال:**\n/echo سلام دنیا!"
    }
    
    response := fmt.Sprintf("🔊 **تکرار متن شما:**\n\n%s", echoText)
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   response,
    })
    return err
}

// ℹ️ هندلر دستور /info
func handleInfo(ctx context.Context, bot *ParsRubika.BotClient, update *ParsRubika.Update) error {
    userInfo, err := bot.GetUserInfo(ctx, update.NewMessage.SenderID)
    if err != nil {
        // ❌ در صورت خطا، پیام مناسب ارسال کنید
        _, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: update.ChatID,
            Text:   "❌ خطا در دریافت اطلاعات کاربر. لطفا بعدا تلاش کنید.",
        })
        return err
    }
    
    infoText := fmt.Sprintf(`👤 **اطلاعات کاربر**

🆔 **شناسه:** %s
👤 **نام:** %s %s
📛 **یوزرنیم:** @%s
📝 **بیو:** %s
✅ **تأیید شده:** %v
🔒 **خصوصی:** %v`,
        userInfo.UserID,
        userInfo.FirstName,
        userInfo.LastName,
        userInfo.Username,
        userInfo.Bio,
        userInfo.IsVerified,
        userInfo.IsPrivate,
    )
    
    _, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: update.ChatID,
        Text:   infoText,
    })
    return err
}

// 💾 هندلر دستور /state
func handleStateDemo(ctx context.Context, bot *ParsRubika.BotClient, chatID, userID string) error {
    // 💾 ذخیره وضعیت کاربر
    bot.SetState(userID, "last_command", "/state")
    bot.SetState(userID, "visit_count", 1)
    
    // 🔍 بازیابی وضعیت کاربر
    lastCmd, _ := bot.GetState(userID, "last_command")
    visitCount, _ := bot.GetState(userID, "visit_count")
    
    // 🔄 افزایش تعداد بازدید
    if count, ok := visitCount.(int); ok {
        bot.SetState(userID, "visit_count", count+1)
        visitCount = count + 1
    }
    
    infoText := fmt.Sprintf(`💾 **وضعیت فعلی شما**

🔧 **آخرین دستور:** %s
🔢 **تعداد بازدید:** %v
⏰ **زمان آخرین فعالیت:** %s

💡 **این اطلاعات در سرور ذخیره شده‌اند و در جلسات بعدی باقی می‌مانند.**`,
        lastCmd,
        visitCount,
        time.Now().Format("2006/01/02 15:04:05"),
    )
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   infoText,
    })
    return err
}

// 💬 هندلر پیام‌های معمولی
func handleDefault(ctx context.Context, bot *ParsRubika.BotClient, chatID, text string) error {
    response := fmt.Sprintf(`💬 **پیام شما دریافت شد!**

📝 **متن شما:** %s

💡 **راهنما:** 
از دستور /help برای مشاهده امکانات استفاده کنید.`, text)
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   response,
    })
    return err
}
📄 قدم 4: ابزارهای کمکی (utils.go)
package main

import (
    "context"
    "fmt"
    
    ParsRubika "github.com/Abolfazl-Zarei/ParsRubika-bot-go"
)

// 🔧 ایجاد کیبورد اصلی
func createMainMenuKeyboard() *ParsRubika.ReplyKeyboardMarkup {
    return &ParsRubika.ReplyKeyboardMarkup{
        Keyboard: [][]*ParsRubika.KeyboardButton{
            {
                {
                    Text: "📚 راهنما",
                },
                {
                    Text: "👤 اطلاعات",
                },
            },
            {
                {
                    Text: "🔊 تکرار متن",
                },
                {
                    Text: "💾 وضعیت",
                },
            },
        },
        ResizeKeyboard:  true,
        OneTimeKeyboard: false,
    }
}

// 🎯 ارسال پیام با کیبورد
func sendMessageWithKeyboard(ctx context.Context, bot *ParsRubika.BotClient, chatID, text string) error {
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID:              chatID,
        Text:                text,
        ReplyKeyboardMarkup: createMainMenuKeyboard(),
    })
    return err
}

// 📊 نمایش اطلاعات ربات
func displayBotInfo(ctx context.Context, bot *ParsRubika.BotClient, chatID string) error {
    botInfo, err := bot.GetMe(ctx)
    if err != nil {
        return err
    }
    
    infoText := fmt.Sprintf(`🤖 **اطلاعات ربات**

🏷️ **نام:** %s
📛 **یوزرنیم:** @%s
🆔 **شناسه:** %s
📝 **توضیحات:** %s
🔗 **لینک اشتراک:** %s`,
        botInfo.BotTitle,
        botInfo.Username,
        botInfo.BotID,
        botInfo.Description,
        botInfo.ShareURL,
    )
    
    _, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   infoText,
    })
    return err
}

// 📨 ارسال پیام با فرمت‌بندی
func sendFormattedMessage(ctx context.Context, bot *ParsRubika.BotClient, chatID, text string) error {
    // 🎨 استفاده از فرمت‌بندی Markdown
    formattedText := ParsRubika.Bold("پیام مهم") + "\n\n" +
        ParsRubika.Italic("این یک متن کج است") + "\n" +
        ParsRubika.Code("کد نمونه") + "\n" +
        ParsRubika.Link("کلیک کنید", "https://github.com/Abolfazl-Zarei/ParsRubika-bot-go")
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   formattedText,
    })
    return err
}
🚀 قدم 5: اجرای نهایی
# 1. 🔑 تنظیم توکن
export RUBIKA_BOT_TOKEN="your_actual_bot_token_here"

# 2. 📦 دانلود وابستگی‌ها
go mod tidy

# 3. 🏗 ساخت پروژه
go build -o my-bot

# 4. 🚀 اجرای ربات
./my-bot

# یا برای اجرای مستقیم:
go run main.go handlers.go utils.go

📡 API Reference کامل

💬 مدیریت پیام‌ها
📨 ارسال پیام متنی
messageID, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:               "CHAT_ID",              // 💬 شناسه چت مقصد
    Text:                 "متن پیام شما",         // 📝 متن پیام
    ReplyToMessageID:     "MSG_ID",              // ↩️ پاسخ به پیام خاص (اختیاری)
    InlineKeyboardMarkup:  inlineKeyboard,        // ⌨️ کیبورد اینلاین (اختیاری)
    ReplyKeyboardMarkup:  replyKeyboard,         // ⌨️ کیبورد پاسخ (اختیاری)
    DisableNotification:  false,                 // 🔕 بی‌صدا کردن (اختیاری)
})
⌨️ ارسال پیام با کیبورد اینلاین
// 🎮 ایجاد کیبورد اینلاین
inlineKeyboard := &ParsRubika.InlineKeyboardMarkup{
    InlineKeyboard: [][]*ParsRubika.InlineKeyboardButton{
        {
            {
                Text:         "🎯 دکمه ۱",
                CallbackData: "btn1",
            },
            {
                Text:         "🚀 دکمه ۲",
                CallbackData: "btn2",
            },
        },
        {
            {
                Text: "🌐 وب‌سایت",
                URL:  "https://github.com/Abolfazl-Zarei/ParsRubika-bot-go",
            },
        },
    },
}

// 📨 ارسال پیام با کیبورد اینلاین
messageID, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:              "CHAT_ID",
    Text:                "پیام با کیبورد تعاملی 🎮",
    InlineKeyboardMarkup: inlineKeyboard,
})
⌨️ ارسال پیام با کیبورد پاسخ
// 🎮 ایجاد کیبورد پاسخ
replyKeyboard := &ParsRubika.ReplyKeyboardMarkup{
    Keyboard: [][]*ParsRubika.KeyboardButton{
        {
            {
                Text: "📚 راهنما",
            },
            {
                Text: "👤 اطلاعات",
            },
        },
        {
            {
                Text:            "📞 شماره تماس",
                RequestContact:  true,
            },
            {
                Text:            "📍 موقعیت مکانی",
                RequestLocation: true,
            },
        },
    },
    ResizeKeyboard:  true,   // 📱 تنظیم سایز برای موبایل
    OneTimeKeyboard: false,  // 🔁 نمایش دائمی
}

// 📨 ارسال پیام با کیبورد پاسخ
messageID, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:             "CHAT_ID",
    Text:               "پیام با کیبورد پاسخ ⌨️",
    ReplyKeyboardMarkup: replyKeyboard,
})
✏️ ویرایش پیام
err := bot.EditMessageText(ctx, &ParsRubika.EditMessageTextRequest{
    ChatID:              "CHAT_ID",      // 💬 شناسه چت
    MessageID:           "MESSAGE_ID",   // 🔢 شناسه پیام
    Text:                "متن جدید",     // 📝 متن جدید
    InlineKeyboardMarkup: newKeyboard,    // ⌨️ کیبورد جدید (اختیاری)
})
✏️ ویرایش کیبورد پیام
err := bot.EditInlineKeypad(ctx, &ParsRubika.EditMessageKeypadRequest{
    ChatID:              "CHAT_ID",      // 💬 شناسه چت
    MessageID:           "MESSAGE_ID",   // 🔢 شناسه پیام
    InlineKeyboardMarkup: newKeyboard,    // ⌨️ کیبورد جدید
})
🗑️ حذف پیام
err := bot.DeleteMessage(ctx, &ParsRubika.DeleteMessageRequest{
    ChatID:    "CHAT_ID",      // 💬 شناسه چت
    MessageID: "MESSAGE_ID",   // 🔢 شناسه پیام
})
📌 پین کردن پیام
err := bot.PinChatMessage(ctx, &ParsRubika.PinChatMessageRequest{
    ChatID:              "CHAT_ID",      // 💬 شناسه چت
    MessageID:           "MESSAGE_ID",   // 🔢 شناسه پیام
    DisableNotification:  false,          // 🔕 بی‌صدا کردن (اختیاری)
})
📌 آنپین کردن پیام
err := bot.UnpinChatMessage(ctx, &ParsRubika.UnpinChatMessageRequest{
    ChatID:    "CHAT_ID",      // 💬 شناسه چت
    MessageID: "MESSAGE_ID",   // 🔢 شناسه پیام
})
📌 آنپین کردن همه پیام‌ها
err := bot.UnpinAllChatMessages(ctx, "CHAT_ID")  // 💬 شناسه چت
🖼 ارسال مدیا
🖼️ ارسال عکس
messageID, err := bot.SendPhoto(ctx, "CHAT_ID", "path/to/image.jpg", "عنوان عکس")
🎬 ارسال ویدیو
messageID, err := bot.SendVideo(ctx, "CHAT_ID", "path/to/video.mp4", "عنوان ویدیو")
🎵 ارسال موسیقی
messageID, err := bot.SendMusic(ctx, "CHAT_ID", "path/to/music.mp3", "عنوان موسیقی")
📄 ارسال فایل
messageID, err := bot.SendDocument(ctx, "CHAT_ID", "path/to/file.pdf", "عنوان فایل")
🎙️ ارسال پیام صوتی
messageID, err := bot.SendVoice(ctx, "CHAT_ID", "path/to/voice.ogg", "عنوان پیام صوتی")
🎨 ارسال گیف
messageID, err := bot.SendGif(ctx, "CHAT_ID", "path/to/animation.gif", "عنوان گیف")
🎨 ارسال استیکر
messageID, err := bot.SendSticker(ctx, "CHAT_ID", "path/to/sticker.webp")
📍 ارسال موقعیت
messageID, err := bot.SendLocation(ctx, &ParsRubika.SendLocationRequest{
    ChatID:              "CHAT_ID",
    Latitude:            "35.6892",   // 📍 عرض جغرافیایی
    Longitude:           "51.3890",   // 📍 طول جغرافیایی
    ReplyToMessageID:    "MSG_ID",    // ↩️ پاسخ به پیام (اختیاری)
    InlineKeyboardMarkup: keyboard,    // ⌨️ کیبورد (اختیاری)
    DisableNotification: false,       // 🔕 بی‌صدا کردن (اختیاری)
})
👥 ارسال مخاطب
messageID, err := bot.SendContact(ctx, &ParsRubika.SendContactRequest{
    ChatID:              "CHAT_ID",
    FirstName:           "نام",
    LastName:            "نام خانوادگی", 
    PhoneNumber:         "09123456789",
    ReplyToMessageID:    "MSG_ID",    // ↩️ پاسخ به پیام (اختیاری)
    InlineKeyboardMarkup: keyboard,    // ⌨️ کیبورد (اختیاری)
    DisableNotification: false,       // 🔕 بی‌صدا کردن (اختیاری)
})
📊 ارسال نظرسنجی
messageID, err := bot.SendPoll(ctx, &ParsRubika.SendPollRequest{
    ChatID:              "CHAT_ID",
    Question:            "سوال نظرسنجی",
    Options:             []string{"گزینه اول", "گزینه دوم", "گزینه سوم"},
    ReplyToMessageID:    "MSG_ID",    // ↩️ پاسخ به پیام (اختیاری)
    InlineKeyboardMarkup: keyboard,    // ⌨️ کیبورد (اختیاری)
    DisableNotification: false,       // 🔕 بی‌صدا کردن (اختیاری)
})
📝 ارسال فعالیت چت
err := bot.SendChatActivity(ctx, "CHAT_ID", "typing")  // 📝 در حال تایپ
err = bot.SendChatActivity(ctx, "CHAT_ID", "upload_photo")  // 📷 در حال آپلود عکس
err = bot.SendChatActivity(ctx, "CHAT_ID", "record_video")  // 🎬 در حال ضبط ویدیو
🔄 فوروارد پیام‌ها
📤 فوروارد یک پیام
newMessageID, err := bot.ForwardMessage(ctx, &ParsRubika.ForwardMessageRequest{
    FromChatID:          "SOURCE_CHAT_ID",  // 📤 شناسه چت مبدا
    MessageID:           "MESSAGE_ID",      // 🔢 شناسه پیام
    ToChatID:            "TARGET_CHAT_ID",  // 📥 شناسه چت مقصد
    DisableNotification: false,             // 🔕 بی‌صدا کردن (اختیاری)
})
📤 فوروارد چندین پیام
messageIDs := []string{"MSG_ID_1", "MSG_ID_2", "MSG_ID_3"}
newMessageIDs, err := bot.ForwardMessages(ctx, "SOURCE_CHAT_ID", messageIDs, "TARGET_CHAT_ID")
💬 مدیریت چت و کاربران
💬 اطلاعات چت
chat, err := bot.GetChat(ctx, "CHAT_ID")
fmt.Printf("نام چت: %s\n", chat.Title)
fmt.Printf("نوع چت: %s\n", chat.ChatType)
👤 اطلاعات کاربر
user, err := bot.GetUserInfo(ctx, "USER_ID")
fmt.Printf("نام کاربر: %s %s\n", user.FirstName, user.LastName)
fmt.Printf("یوزرنیم: @%s\n", user.Username)
fmt.Printf("تأیید شده: %v\n", user.IsVerified)
👥 لیست اعضا
members, err := bot.GetMembers(ctx, "CHAT_ID")
for _, member := range members {
    fmt.Printf("عضو: %s\n", member.User.FirstName)
}
👤 اطلاعات عضو خاص
member, err := bot.GetChatMember(ctx, &ParsRubika.GetChatMemberRequest{
    ChatID: "CHAT_ID",
    UserID: "USER_ID",
})
fmt.Printf("وضعیت عضو: %s\n", member.Status)
🔢 تعداد اعضا
count, err := bot.GetChatMemberCount(ctx, &ParsRubika.GetChatMemberCountRequest{
    ChatID: "CHAT_ID",
})
fmt.Printf("تعداد اعضا: %d\n", count.Count)
👥 مدیران چت
admins, err := bot.GetChatAdministrators(ctx, &ParsRubika.GetChatAdministratorsRequest{
    ChatID: "CHAT_ID",
})
for _, admin := range admins.Administrators {
    fmt.Printf("مدیر: %s (%s)\n", admin.User.FirstName, admin.Status)
}
🛡️ مدیریت دسترسی اعضا
// 🚫 مسدود کردن عضو
err := bot.BanChatMember(ctx, &ParsRubika.BanChatMemberRequest{
    ChatID: "CHAT_ID",
    UserID: "USER_ID",
})

// ✅ رفع مسدودیت عضو
err = bot.UnbanChatMember(ctx, &ParsRubika.UnbanChatMemberRequest{
    ChatID: "CHAT_ID",
    UserID: "USER_ID",
})

// 📈 ارتقای عضو به مدیر
err = bot.PromoteChatMember(ctx, &ParsRubika.PromoteChatMemberRequest{
    ChatID:          "CHAT_ID",
    UserID:          "USER_ID",
    IsAdministrator: &[]bool{true}[0],  // 📌 تبدیل به مدیر
    CanChangeInfo:   &[]bool{true}[0],  // ✏️ امکان تغییر اطلاعات
    CanDeleteMessages: &[]bool{true}[0], // 🗑️ امکان حذف پیام‌ها
    CanInviteUsers:  &[]bool{true}[0],  // 👥 امکان دعوت کاربران
    CanPinMessages:  &[]bool{true}[0],  // 📌 امکان پین کردن پیام‌ها
})
⚙️ تنظیم مجوزهای چت
permissions := map[string]bool{
    "can_send_messages":       true,
    "can_send_media_messages": true,
    "can_send_polls":          false,
    "can_add_web_page_previews": false,
}

err := bot.SetChatPermissions(ctx, "CHAT_ID", permissions)
📊 نظرسنجی‌ها
📊 ایجاد نظرسنجی
messageID, err := bot.CreatePoll(ctx, "CHAT_ID", "سوال نظرسنجی", []string{
    "گزینه اول",
    "گزینه دوم", 
    "گزینه سوم",
})
🗳️ رأی دادن
err := bot.VotePoll(ctx, "CHAT_ID", "MESSAGE_ID", 0) // 0 = گزینه اول
📈 وضعیت نظرسنجی
status, err := bot.GetPollStatus(ctx, "CHAT_ID", "MESSAGE_ID")
fmt.Printf("وضعیت: %s\n", status.State)
fmt.Printf("تعداد آراء: %d\n", status.TotalVote)
fmt.Printf("درصد آراء: %v\n", status.PercentVoteOptions)
🤖 اطلاعات بات
🤖 اطلاعات بات
bot, err := bot.GetMe(ctx)
fmt.Printf("نام بات: %s\n", bot.BotTitle)
fmt.Printf("یوزرنیم: @%s\n", bot.Username)
fmt.Printf("شناسه: %s\n", bot.BotID)
fmt.Printf("توضیحات: %s\n", bot.Description)
fmt.Printf("لینک اشتراک: %s\n", bot.ShareURL)
⚙️ تنظیم دستورات بات
commands := []ParsRubika.BotCommand{
    {
        Command:     "start",
        Description: "شروع کار با ربات",
    },
    {
        Command:     "help",
        Description: "راهنمای ربات",
    },
    {
        Command:     "info",
        Description: "اطلاعات کاربر",
    },
}

err := bot.SetCommands(ctx, &ParsRubika.SetCommandsRequest{
    BotCommands: commands,
})
🔄 به‌روزرسانی endpointهای بات
err := bot.UpdateBotEndpoints(ctx, "https://your-domain.com/webhook", ParsRubika.ReceiveUpdate)
📁 مدیریت فایل‌ها
📤 درخواست آدرس آپلود
uploadResp, err := bot.RequestSendFile(ctx, ParsRubika.ImageType)
fmt.Printf("آدرس آپلود: %s\n", uploadResp.UploadURL)
📤 آپلود فایل
uploadResp, err := bot.UploadFile("https://upload.url", "path/to/file.jpg")
fmt.Printf("شناسه فایل: %s\n", uploadResp.FileID)
📄 اطلاعات فایل
fileInfo, err := bot.GetFile(ctx, "FILE_ID")
fmt.Printf("نام فایل: %s\n", fileInfo.FileName)
fmt.Printf("سایز: %d\n", fileInfo.Size)
fmt.Printf("آدرس دانلود: %s\n", fileInfo.DownloadURL)
📥 دانلود فایل
err := bot.Download(ctx, "FILE_ID", "path/to/save/file.jpg")
🖼️ دانلود عکس پروفایل
err := bot.DownloadProfilePicture(ctx, "USER_ID", "path/to/save/avatar.jpg")
📤 آپلود فایل مستقیم
file, err := bot.UploadFileDirectly(ctx, "path/to/file.jpg", ParsRubika.ImageType)
fmt.Printf("شناسه فایل: %s\n", file.FileID)
fmt.Printf("نام فایل: %s\n", file.FileName)
fmt.Printf("سایز: %d\n", file.Size)
🎛 مدیریت وضعیت کاربر
💾 ذخیره وضعیت
// 🎯 ذخیره وضعیت‌های مختلف کاربر
bot.SetState(userID, "current_menu", "main")
bot.SetState(userID, "selected_item", "item_123")
bot.SetState(userID, "step", "2")
bot.SetState(userID, "form_data", map[string]string{
    "name": "John",
    "age":  "30",
})
🔍 بازیابی وضعیت
// 🔍 بازیابی وضعیت کاربر
menu, exists := bot.GetState(userID, "current_menu")
if exists {
    switch menu {
    case "main":
        // 🏠 نمایش منوی اصلی
    case "settings":
        // ⚙️ نمایش تنظیمات
    case "profile":
        // 👤 نمایش پروفایل
    }
}

step, exists := bot.GetState(userID, "step")
if exists {
    // 🔄 ادامه فرآیند از مرحله ذخیره شده
}
🗑️ مدیریت وضعیت
// 🗑️ حذف یک کلید خاص
bot.DeleteState(userID, "selected_item")

// 🗑️ حذف تمام وضعیت‌های کاربر
bot.DeleteUserState(userID)
🛡️ سیستم ضد اسپم
⚙️ تنظیمات ضد اسپم
// 🛡️ دریافت مدیر ضد اسپم
antiSpam := bot.GetAntiSpam()

// ⏰ تنظیم زمان کول‌داون (پیش‌فرض: 3 ثانیه)
antiSpam.SetCooldown(5 * time.Second)
🔍 بررسی ضد اسپم
// 🛡️ بررسی اینکه آیا کاربر اسپم می‌کند یا خیر
if bot.CheckAntiSpam(userID) {
    // ✅ کاربر اسپم نمی‌کند، پردازش ادامه می‌یابد
    processUserMessage(ctx, update)
} else {
    // ⚠️ کاربر در حال اسپم کردن است
    bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: update.ChatID,
        Text:   "⚠️ لطفاً کمی صبر کنید و درخواست‌های خود را با فاصله ارسال کنید.",
    })
}
🔄 بازنشانی ضد اسپم
// 🔄 بازنشانی وضعیت ضد اسپم برای یک کاربر خاص
bot.ResetAntiSpam(userID)
🔄 قابلیت Hot-Reload
⚙️ فعال‌سازی Hot-Reload
// 🔄 ایجاد نمونه ربات با Hot-Reload فعال
bot := ParsRubika.NewClient(token, ParsRubika.WithHotReload(true))

// 🔄 یا فعال‌سازی پس از ساخت
bot.EnableHotReload()
🔍 بررسی وضعیت Hot-Reload
// 🔍 بررسی اینکه آیا Hot-Reload فعال است یا خیر
if bot.IsHotReloadEnabled() {
    fmt.Println("Hot-Reload فعال است")
} else {
    fmt.Println("Hot-Reload غیرفعال است")
}
🔄 مدیریت Hot-Reload
// 🔄 دریافت مدیر Hot-Reload
reloadManager := bot.GetReloadManager()

// 🎯 ثبت تابع برای اجرا پس از بارگذاری مجدد
reloadManager.OnReload(func() {
    fmt.Println("بارگذاری مجدد انجام شد!")
})

// 🔄 شروع نظارت بر تغییرات فایل‌ها
reloadManager.StartWatching()

// 🛑 توقف نظارت بر تغییرات فایل‌ها
reloadManager.StopWatching()

// 🔄 اجرای دستی بارگذاری مجدد
reloadManager.TriggerReload()
🌐 مدیریت پایداری شبکه
🌐 دریافت مدیر پایداری شبکه
// 🌐 دریافت مدیر پایداری شبکه
networkManager := bot.networkStabilityManager
⏰ محاسبه تأخیر برای تلاش مجدد
// ⏰ محاسبه تأخیر برای تلاش مجدد با الگوریتم نمایی و Jitter
delay := networkManager.CalculateBackoffDelay(retryCount)
fmt.Printf("تأخیر برای تلاش مجدد: %v\n", delay)
🔍 بررسی خطای قابل تلاش مجدد
// 🔍 بررسی اینکه آیا یک خطا قابل تلاش مجدد است یا خیر
if networkManager.IsRetryableError(err) {
    fmt.Println("خطا قابل تلاش مجدد است")
} else {
    fmt.Println("خطا قابل تلاش مجدد نیست")
}

🎛 مدیریت وضعیت (State Management)

💾 ایجاد State Manager
// 🆕 ایجاد مدیر وضعیت
stateManager := ParsRubika.NewStateManager()

// 🔄 استفاده در هندلرها
bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
    userID := update.NewMessage.SenderID
    
    // 💾 ذخیره وضعیت کاربر
    stateManager.SetState(userID, "current_menu", "main")
    stateManager.SetState(userID, "selected_item", "item_123")
    stateManager.SetState(userID, "step", "2")
    
    return nil
})
💽 ذخیره وضعیت کاربر
// 💾 ذخیره داده‌های مختلف کاربر
stateManager.SetState(userID, "current_menu", "main")
stateManager.SetState(userID, "selected_item", "item_123")
stateManager.SetState(userID, "step", "2")
stateManager.SetState(userID, "form_data", map[string]string{
    "name": "John",
    "age":  "30",
})
🔍 بازیابی وضعیت
// 🔍 بازیابی وضعیت کاربر
menu, exists := stateManager.GetState(userID, "current_menu")
if exists {
    switch menu {
    case "main":
        // 🏠 نمایش منوی اصلی
    case "settings":
        // ⚙️ نمایش تنظیمات
    case "profile":
        // 👤 نمایش پروفایل
    }
}

step, exists := stateManager.GetState(userID, "step")
if exists {
    // 🔄 ادامه فرآیند از مرحله ذخیره شده
}
🗑️ مدیریت وضعیت
// 🗑️ حذف یک کلید خاص
stateManager.DeleteState(userID, "selected_item")

// 🗑️ حذف تمام وضعیت‌های کاربر
stateManager.DeleteUserState(userID)
🎯 مثال کامل State Management
func setupStatefulHandlers(bot *ParsRubika.BotClient) {
    stateManager := ParsRubika.NewStateManager()
    
    bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage == nil {
            return nil
        }
        
        userID := update.NewMessage.SenderID
        text := update.NewMessage.Text
        chatID := update.ChatID
        
        // 🔍 بررسی وضعیت فعلی کاربر
        currentState, _ := stateManager.GetState(userID, "state")
        
        switch currentState {
        case "awaiting_name":
            return handleNameInput(ctx, bot, chatID, userID, stateManager, text)
        case "awaiting_age":
            return handleAgeInput(ctx, bot, chatID, userID, stateManager, text)
        case "awaiting_email":
            return handleEmailInput(ctx, bot, chatID, userID, stateManager, text)
        default:
            return handleInitialState(ctx, bot, chatID, userID, stateManager, text)
        }
    })
}

// 🏠 وضعیت اولیه
func handleInitialState(ctx context.Context, bot *ParsRubika.BotClient, chatID, userID string, stateManager *ParsRubika.StateManager, text string) error {
    if text == "/register" {
        // 💾 ذخیره وضعیت جدید
        stateManager.SetState(userID, "state", "awaiting_name")
        
        _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "👤 لطفا نام خود را وارد کنید:",
        })
        return err
    }
    return nil
}

// 👤 دریافت نام
func handleNameInput(ctx context.Context, bot *ParsRubika.BotClient, chatID, userID string, stateManager *ParsRubika.StateManager, name string) error {
    // 💾 ذخیره نام
    stateManager.SetState(userID, "name", name)
    stateManager.SetState(userID, "state", "awaiting_age")
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   "🎂 لطفا سن خود را وارد کنید:",
    })
    return err
}

// 🎂 دریافت سن
func handleAgeInput(ctx context.Context, bot *ParsRubika.BotClient, chatID, userID string, stateManager *ParsRubika.StateManager, age string) error {
    // 💾 ذخیره سن
    stateManager.SetState(userID, "age", age)
    stateManager.SetState(userID, "state", "awaiting_email")
    
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   "📧 لطفا ایمیل خود را وارد کنید:",
    })
    return err
}

// 📧 دریافت ایمیل
func handleEmailInput(ctx context.Context, bot *ParsRubika.BotClient, chatID, userID string, stateManager *ParsRubika.StateManager, email string) error {
    // 💾 ذخیره ایمیل
    stateManager.SetState(userID, "email", email)
    
    // 🔍 بازیابی تمام اطلاعات
    name, _ := stateManager.GetState(userID, "name")
    age, _ := stateManager.GetState(userID, "age")
    
    // 🗑️ پاک کردن وضعیت
    stateManager.DeleteUserState(userID)
    
    // ✅ ارسال نتیجه نهایی
    _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text: fmt.Sprintf(`✅ **ثبت نام کامل شد!**

👤 نام: %s
🎂 سن: %s
📧 ایمیل: %s

🎉 از عضویت شما متشکریم!`, name, age, email),
    })
    return err
}

⌨ کیبوردهای پویا

🎮 ایجاد کیبورد ساده
func createMainMenuKeyboard() *ParsRubika.ReplyKeyboardMarkup {
    return &ParsRubika.ReplyKeyboardMarkup{
        Keyboard: [][]*ParsRubika.KeyboardButton{
            {
                {
                    Text: "📚 راهنما",
                },
                {
                    Text: "👤 اطلاعات",
                },
            },
            {
                {
                    Text: "🔊 تکرار متن",
                },
                {
                    Text: "💾 وضعیت",
                },
            },
        },
        ResizeKeyboard:  true,   // 📱 تنظیم سایز برای موبایل
        OneTimeKeyboard: false,  // 🔁 نمایش دائمی
    }
}
🎯 کیبوردهای پیشرفته
🔘 دکمه انتخاب (Selection)
selectionBtn := ParsRubika.KeyboardButton{
    Text: "📁 انتخاب آیتم",
    Type: ParsRubika.ButtonTypeSelection,
    // در پیاده‌سازی کامل، باید فیلدهای مربوط به ButtonSelection تنظیم شوند
}

// 📨 ارسال پیام با دکمه انتخاب
_, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:             chatID,
    Text:               "لطفا یک آیتم انتخاب کنید:",
    ReplyKeyboardMarkup: &ParsRubika.ReplyKeyboardMarkup{
        Keyboard: [][]*ParsRubika.KeyboardButton{
            {&selectionBtn},
        },
    },
})
📅 دکمه تقویم
calendarBtn := ParsRubika.KeyboardButton{
    Text: "📅 انتخاب تاریخ",
    Type: ParsRubika.ButtonTypeCalendar,
    // در پیاده‌سازی کامل، باید فیلدهای مربوط به ButtonCalendar تنظیم شوند
}

// 📨 ارسال پیام با دکمه تقویم
_, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:             chatID,
    Text:               "تاریخ مورد نظر را انتخاب کنید:",
    ReplyKeyboardMarkup: &ParsRubika.ReplyKeyboardMarkup{
        Keyboard: [][]*ParsRubika.KeyboardButton{
            {&calendarBtn},
        },
    },
})
🔢 دکمه انتخاب عدد
numberPickerBtn := ParsRubika.KeyboardButton{
    Text: "🔢 انتخاب عدد",
    Type: ParsRubika.ButtonTypeNumberPicker,
    // در پیاده‌سازی کامل، باید فیلدهای مربوط به ButtonNumberPicker تنظیم شوند
}

// 📨 ارسال پیام با دکمه انتخاب عدد
_, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:             chatID,
    Text:               "عدد مورد نظر را انتخاب کنید:",
    ReplyKeyboardMarkup: &ParsRubika.ReplyKeyboardMarkup{
        Keyboard: [][]*ParsRubika.KeyboardButton{
            {&numberPickerBtn},
        },
    },
})
🎨 استفاده از کیبوردها
// 📨 ارسال پیام با کیبورد اصلی
_, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:             chatID,
    Text:               "🎮 **منوی اصلی ربات**\n\nلطفا یک گزینه انتخاب کنید:",
    ReplyKeyboardMarkup: createMainMenuKeyboard(),
})

// ✏️ ویرایش کیبورد پیام موجود
err := bot.EditChatKeypad(ctx, &ParsRubika.EditChatKeypadRequest{
    ChatID:             chatID,
    ReplyKeyboardMarkup: createNewKeyboard(),
    ChatKeypadType:     ParsRubika.NewKeypad,
})

// 🗑️ حذف کیبورد
err = bot.EditChatKeypad(ctx, &ParsRubika.EditChatKeypadRequest{
    ChatID:         chatID,
    RemoveKeyboard: &ParsRubika.ReplyKeyboardRemove{
        RemoveKeyboard: true,
    },
    ChatKeypadType: ParsRubika.RemoveKeypad,
})
🎨 کیبوردهای اینلاین (Inline)
// 🎮 ایجاد کیبورد اینلاین
inlineKeyboard := &ParsRubika.InlineKeyboardMarkup{
    InlineKeyboard: [][]*ParsRubika.InlineKeyboardButton{
        {
            {
                Text:         "🎯 دکمه ۱",
                CallbackData: "btn1",
            },
            {
                Text:         "🚀 دکمه ۲",
                CallbackData: "btn2",
            },
        },
        {
            {
                Text: "🌐 وب‌سایت",
                URL:  "https://github.com/Abolfazl-Zarei/ParsRubika-bot-go",
            },
            {
                Text:              "🔍 جستجو",
                SwitchInlineQuery: "search_query",
            },
        },
    },
}

// 📨 ارسال پیام با کیبورد اینلاین
_, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID:              chatID,
    Text:                "پیام با کیبورد تعاملی 🎮",
    InlineKeyboardMarkup: inlineKeyboard,
})

// ✏️ ویرایش کیبورد اینلاین پیام موجود
err = bot.EditInlineKeypad(ctx, &ParsRubika.EditMessageKeypadRequest{
    ChatID:              chatID,
    MessageID:           messageID,
    InlineKeyboardMarkup: newInlineKeyboard,
})
🎨 توابع کمکی برای ساخت کیبوردها
// 🎮 ایجاد کیبورد اینلاین
func NewInlineKeyboard(rows ...[]*ParsRubika.InlineKeyboardButton) *ParsRubika.InlineKeyboardMarkup {
    keyboard := &ParsRubika.InlineKeyboardMarkup{
        InlineKeyboard: make([][]*ParsRubika.InlineKeyboardButton, len(rows)),
    }

    for i, row := range rows {
        keyboard.InlineKeyboard[i] = make([]*ParsRubika.InlineKeyboardButton, len(row))
        copy(keyboard.InlineKeyboard[i], row)
    }

    return keyboard
}

// 🎮 ایجاد دکمه کیبورد اینلاین
func NewInlineKeyboardButton(text string) *ParsRubika.InlineKeyboardButton {
    return &ParsRubika.InlineKeyboardButton{Text: text}
}

// 🔗 تنظیم URL برای دکمه
func (b *ParsRubika.InlineKeyboardButton) WithURL(url string) *ParsRubika.InlineKeyboardButton {
    b.URL = url
    return b
}

// 🔗 تنظیم داده callback برای دکمه
func (b *ParsRubika.InlineKeyboardButton) WithCallbackData(data string) *ParsRubika.InlineKeyboardButton {
    b.CallbackData = data
    return b
}

// 🔍 تنظیم سوئیچ اینلاین کوئری برای دکمه
func (b *ParsRubika.InlineKeyboardButton) WithSwitchInlineQuery(query string) *ParsRubika.InlineKeyboardButton {
    b.SwitchInlineQuery = query
    return b
}

// 🎮 ایجاد کیبورد پاسخ
func NewReplyKeyboard(rows ...[]*ParsRubika.KeyboardButton) *ParsRubika.ReplyKeyboardMarkup {
    keyboard := &ParsRubika.ReplyKeyboardMarkup{
        Keyboard:       make([][]*ParsRubika.KeyboardButton, len(rows)),
        ResizeKeyboard: true,
    }

    for i, row := range rows {
        keyboard.Keyboard[i] = make([]*ParsRubika.KeyboardButton, len(row))
        copy(keyboard.Keyboard[i], row)
    }

    return keyboard
}

// 🎮 ایجاد دکمه کیبورد پاسخ
func NewReplyKeyboardButton(text string) *ParsRubika.KeyboardButton {
    return &ParsRubika.KeyboardButton{Text: text}
}

// 📞 تنظیم درخواست شماره تلفن برای دکمه
func (b *ParsRubika.KeyboardButton) WithRequestContact() *ParsRubika.KeyboardButton {
    b.RequestContact = true
    return b
}

// 📍 تنظیم درخواست موقعیت مکانی برای دکمه
func (b *ParsRubika.KeyboardButton) WithRequestLocation() *ParsRubika.KeyboardButton {
    b.RequestLocation = true
    return b
}

// 📱 تنظیم تغییر اندازه کیبورد
func (kb *ParsRubika.ReplyKeyboardMarkup) WithResizeKeyboard(resize bool) *ParsRubika.ReplyKeyboardMarkup {
    kb.ResizeKeyboard = resize
    return kb
}

// 🔁 تنظیم کیبورد یکبار مصرف
func (kb *ParsRubika.ReplyKeyboardMarkup) WithOneTimeKeyboard(oneTime bool) *ParsRubika.ReplyKeyboardMarkup {
    kb.OneTimeKeyboard = oneTime
    return kb
}

// 🗑️ ایجاد دستور برای حذف کیبورد
func NewRemoveKeyboard() *ParsRubika.ReplyKeyboardRemove {
    return &ParsRubika.ReplyKeyboardRemove{
        RemoveKeyboard: true,
    }
}

📁 مدیریت فایل‌ها

📤 آپلود فایل‌ها
🖼️ آپلود عکس
fileID, err := bot.uploadFile(ctx, "path/to/image.jpg", ParsRubika.ImageType)
🎬 آپلود ویدیو
fileID, err := bot.uploadFile(ctx, "path/to/video.mp4", ParsRubika.VideoType)
🎵 آپلود صدا
fileID, err := bot.uploadFile(ctx, "path/to/audio.mp3", ParsRubika.VoiceType)
🎨 آپلود استیکر
fileID, err := bot.uploadFile(ctx, "path/to/sticker.webp", ParsRubika.StickerType)
📄 آپلود فایل معمولی
fileID, err := bot.uploadFile(ctx, "path/to/document.pdf", ParsRubika.FileType)
📥 دانلود فایل‌ها
💾 دانلود فایل معمولی
err := bot.Download(ctx, "file_id", "path/to/save/file")
🖼️ دانلود عکس پروفایل
err := bot.DownloadProfilePicture(ctx, "user_id", "path/to/save/avatar.jpg")
🎯 مثال کامل آپلود و دانلود
// 📤 آپلود فایل و دریافت اطلاعات کامل
func uploadAndSendFile(ctx context.Context, bot *ParsRubika.BotClient, chatID, filePath string, fileType ParsRubika.FileTypeEnum) error {
    // 📤 آپلود فایل
    file, err := bot.UploadFileDirectly(ctx, filePath, fileType)
    if err != nil {
        return fmt.Errorf("❌ خطا در آپلود فایل: %w", err)
    }
    
    // 📨 ارسال پیام با اطلاعات فایل
    infoText := fmt.Sprintf(`📁 **فایل آپلود شد!**

🏷️ نام: %s
📊 سایز: %s
🆔 شناسه: %s`, file.FileName, file.Size, file.FileID)
    
    _, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   infoText,
    })
    return err
}

// 📥 دانلود و ذخیره فایل
func downloadAndSaveFile(ctx context.Context, bot *ParsRubika.BotClient, fileID, savePath string) error {
    // ℹ️ دریافت اطلاعات فایل
    fileInfo, err := bot.GetFile(ctx, fileID)
    if err != nil {
        return fmt.Errorf("❌ خطا در دریافت اطلاعات فایل: %w", err)
    }
    
    // 📥 دانلود فایل
    err = bot.Download(ctx, fileID, savePath)
    if err != nil {
        return fmt.Errorf("❌ خطا در دانلود فایل: %w", err)
    }
    
    log.Printf("✅ فایل با موفقیت دانلود شد: %s", savePath)
    return nil
}
📤 آپلود آواتار
// 🖼️ آپلود آواتار
avatar, err := bot.UploadAvatar(ctx, "path/to/avatar.jpg")
if err != nil {
    return fmt.Errorf("❌ خطا در آپلود آواتار: %w", err)
}

// 📨 ارسال پیام با اطلاعات آواتار
infoText := fmt.Sprintf(`🖼️ **آواتار آپلود شد!**

🏷️ نام: %s
📊 سایز: %s
🆔 شناسه: %s`, avatar.FileName, avatar.Size, avatar.FileID)

_, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID: chatID,
    Text:   infoText,
})
🗑️ حذف آواتار
// 🗑️ حذف آواتار
err := bot.DeleteAvatar(ctx)
if err != nil {
    return fmt.Errorf("❌ خطا در حذف آواتار: %w", err)
}

_, err = bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
    ChatID: chatID,
    Text:   "✅ آواتار با موفقیت حذف شد!",
})

🌐 Webhook & Polling

📡 پولینگ (Polling)
⚙️ تنظیمات پیشرفته پولینگ
err := bot.StartPolling(ctx, ParsRubika.PollingOptions{
    Handler:           customHandler,      // 🎯 هندلر سفارشی
    RetryTimeout:      10 * time.Second,   // ⏰ زمان انتظار برای تلاش مجدد
    Limit:             100,                // 📨 حداکثر تعداد آپدیت در هر درخواست
    AllowEmptyUpdates: false,              // ❌ عدم دریافت آپدیت‌های خالی
    PollInterval:      2 * time.Second,    // ⏱️ فاصله بین درخواست‌ها
    Timeout:           30 * time.Second,   // ⏳ تایم‌اوت درخواست
})
🎯 مثال کامل پولینگ
func startAdvancedPolling(bot *ParsRubika.BotClient) error {
    ctx := context.Background()
    
    pollingOpts := ParsRubika.PollingOptions{
        Handler: func(ctx context.Context, update *ParsRubika.Update) error {
            log.Printf("📨 آپدیت دریافت شد - نوع: %s", update.Type)
            
            // 🎯 پردازش آپدیت
            if update.NewMessage != nil {
                return handleMessage(ctx, bot, update)
            }
            return nil
        },
        RetryTimeout:      15 * time.Second,
        Limit:             50,
        PollInterval:      1 * time.Second,
        Timeout:           60 * time.Second,
    }
    
    return bot.StartPolling(ctx, pollingOpts)
}
🌐 وب‌هوک (Webhook)
⚙️ تنظیمات وب‌هوک
webhookOpts := ParsRubika.WebhookOptions{
    Port:    8443,                           // 🚪 پورت سرور
    Path:    "/webhook",                     // 🌐 مسیر وب‌هوک
    Handler: customHandler,                  // 🎯 هندلر سفارشی
    Secret:  "your_webhook_secret",          // 🔐 کلید امنیتی
}

err := bot.StartWebhook(ctx, webhookOpts)
🎯 مثال کامل وب‌هوک
func startWebhookServer(bot *ParsRubika.BotClient) error {
    ctx := context.Background()
    
    webhookOpts := ParsRubika.WebhookOptions{
        Port:    8080,
        Path:    "/bot-webhook",
        Handler: handleWebhookUpdate,
        Secret:  "my_super_secret_key_123",
    }
    
    log.Println("🌐 سرور وب‌هوک در حال راه‌اندازی...")
    return bot.StartWebhook(ctx, webhookOpts)
}

func handleWebhookUpdate(ctx context.Context, update *ParsRubika.Update) error {
    log.Printf("🌐 وب‌هوک دریافت شد - نوع: %s", update.Type)
    
    // 🎯 پردازش آپدیت وب‌هوک
    if update.NewMessage != nil {
        return processWebhookMessage(ctx, update)
    }
    return nil
}
🔄 مقایسه Polling و Webhook
ویژگی 📡 Polling 🌐 Webhook
سادگی ✅ بسیار ساده ⚠️ نیاز به سرور
Performance ⚠️ متوسط ✅ بسیار بالا
Real-time ❌ تأخیر دارد ✅ فوری
مصرف منابع ❌ بالا ✅ پایین
پیکربندی ✅ آسان ⚠️ پیچیده
مقیاس‌پذیری ⚠️ محدود ✅ نامحدود

🚀 مثال‌های پیشرفته

🏪 ربات فروشگاهی
type Product struct {
    ID          string
    Name        string
    Description string
    Price       int
    ImagePath   string
    Category    string
}

type ShopBot struct {
    bot          *ParsRubika.BotClient
    stateManager *ParsRubika.StateManager
    products     map[string]Product
    carts        map[string][]string // userID -> productIDs
    orders       map[string]Order    // orderID -> Order
}

type Order struct {
    ID        string
    UserID    string
    Products  []string
    Total     int
    Status    string
    CreatedAt time.Time
}

func NewShopBot(token string) *ShopBot {
    bot := &ShopBot{
        bot:          ParsRubika.NewClient(token),
        stateManager: ParsRubika.NewStateManager(),
        products:     make(map[string]Product),
        carts:        make(map[string][]string),
        orders:       make(map[string]Order),
    }
    
    bot.initializeProducts()
    bot.setupHandlers()
    return bot
}

func (sb *ShopBot) initializeProducts() {
    // 📦 محصولات نمونه
    sb.products["1"] = Product{
        ID:          "1",
        Name:        "لپ‌تاپ گیمینگ",
        Description: "لپ‌تاپ گیمینگ با کارت گرافیک RTX 4060",
        Price:       45000000,
        ImagePath:   "images/laptop.jpg",
        Category:    "الکترونی
        

```go
    sb.products["2"] = Product{
        ID:          "2", 
        Name:        "هدفون بی‌سیم",
        Description: "هدفون بی‌سیم با نویزکنسلینگ",
        Price:       3500000,
        ImagePath:   "images/headphone.jpg",
        Category:    "الکترونیک",
    }
    
    sb.products["3"] = Product{
        ID:          "3",
        Name:        "کتاب Go Programming",
        Description: "کتاب جامع برنامه‌نویسی Go",
        Price:       150000,
        ImagePath:   "images/book.jpg", 
        Category:    "کتاب",
    }
}

func (sb *ShopBot) setupHandlers() {
    sb.bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage == nil {
            return nil
        }
        
        userID := update.NewMessage.SenderID
        text := update.NewMessage.Text
        
        switch {
        case text == "/start":
            return sb.showMainMenu(ctx, update.ChatID)
        case text == "/products":
            return sb.showProducts(ctx, update.ChatID)
        case text == "/cart":
            return sb.showCart(ctx, update.ChatID, userID)
        case text == "/orders":
            return sb.showOrders(ctx, update.ChatID, userID)
        case strings.HasPrefix(text, "/add_"):
            productID := strings.TrimPrefix(text, "/add_")
            return sb.addToCart(ctx, update.ChatID, userID, productID)
        case text == "/checkout":
            return sb.startCheckout(ctx, update.ChatID, userID)
        default:
            return sb.showMainMenu(ctx, update.ChatID)
        }
    })
}

func (sb *ShopBot) showMainMenu(ctx context.Context, chatID string) error {
    menuText := `🛍️ **فروشگاه آنلاین**

🎯 **دستورات اصلی:**
/products - مشاهده محصولات
/cart - سبد خرید
/orders - سفارشات من
/help - راهنما

💡 **برای شروع خرید از /products استفاده کنید**`
    
    _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   menuText,
    })
    return err
}

func (sb *ShopBot) showProducts(ctx context.Context, chatID string) error {
    var productsText strings.Builder
    productsText.WriteString("🛍️ **محصولات موجود**\n\n")
    
    for id, product := range sb.products {
        productsText.WriteString(fmt.Sprintf(
            "📦 **%s**\n💵 قیمت: %s تومان\n🔹 %s\n\n🛒 اضافه به سبد: /add_%s\n\n%s\n",
            product.Name,
            humanize.Comma(int64(product.Price)),
            product.Description,
            id,
            strings.Repeat("─", 30),
        ))
    }
    
    _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   productsText.String(),
    })
    return err
}

func (sb *ShopBot) addToCart(ctx context.Context, chatID, userID, productID string) error {
    product, exists := sb.products[productID]
    if !exists {
        _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "❌ محصول مورد نظر یافت نشد!",
        })
        return err
    }
    
    if sb.carts[userID] == nil {
        sb.carts[userID] = []string{}
    }
    sb.carts[userID] = append(sb.carts[userID], productID)
    
    _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   fmt.Sprintf("✅ **%s** به سبد خرید اضافه شد! 🛒", product.Name),
    })
    return err
}

func (sb *ShopBot) showCart(ctx context.Context, chatID, userID string) error {
    cartItems := sb.carts[userID]
    if len(cartItems) == 0 {
        _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "🛒 سبد خرید شما خالی است!",
        })
        return err
    }
    
    var cartText strings.Builder
    cartText.WriteString("🛒 **سبد خرید شما**\n\n")
    
    total := 0
    itemCount := make(map[string]int)
    
    for _, productID := range cartItems {
        itemCount[productID]++
    }
    
    for productID, count := range itemCount {
        product := sb.products[productID]
        itemTotal := product.Price * count
        total += itemTotal
        
        cartText.WriteString(fmt.Sprintf(
            "📦 %s (تعداد: %d)\n💵 %s تومان\n\n",
            product.Name,
            count,
            humanize.Comma(int64(itemTotal)),
        ))
    }
    
    cartText.WriteString(fmt.Sprintf(
        "💰 **جمع کل: %s تومان**\n\n💳 برای تسویه حساب: /checkout",
        humanize.Comma(int64(total)),
    ))
    
    _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   cartText.String(),
    })
    return err
}

func (sb *ShopBot) startCheckout(ctx context.Context, chatID, userID string) error {
    cartItems := sb.carts[userID]
    if len(cartItems) == 0 {
        _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "❌ سبد خرید شما خالی است!",
        })
        return err
    }
    
    // 🧮 محاسبه جمع کل
    total := 0
    for _, productID := range cartItems {
        product := sb.products[productID]
        total += product.Price
    }
    
    // 📝 ایجاد سفارش
    orderID := fmt.Sprintf("ORD-%d", time.Now().Unix())
    order := Order{
        ID:        orderID,
        UserID:    userID,
        Products:  cartItems,
        Total:     total,
        Status:    "pending",
        CreatedAt: time.Now(),
    }
    sb.orders[orderID] = order
    
    // 🗑️ خالی کردن سبد خرید
    delete(sb.carts, userID)
    
    // ✅ ارسال تأیید سفارش
    _, err := sb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text: fmt.Sprintf(`✅ **سفارش شما ثبت شد!**

🆔 کد سفارش: %s
💰 مبلغ قابل پرداخت: %s تومان
📦 تعداد آیتم: %d
📞 برای پیگیری با پشتیبانی تماس بگیرید.`,
            orderID,
            humanize.Comma(int64(total)),
            len(cartItems),
        ),
    })
    return err
}
📊 ربات نظرسنجی و آمار
type PollBot struct {
    bot          *ParsRubika.BotClient
    stateManager *ParsRubika.StateManager
    activePolls  map[string]*PollData    // messageID -> PollData
    userVotes    map[string]map[string]int // userID -> map[pollID]optionIndex
}

type PollData struct {
    ID       string
    Question string
    Options  []string
    Votes    map[int]int // optionIndex -> voteCount
    Creator  string
    CreatedAt time.Time
}

func NewPollBot(token string) *PollBot {
    bot := &PollBot{
        bot:          ParsRubika.NewClient(token),
        stateManager: ParsRubika.NewStateManager(),
        activePolls:  make(map[string]*PollData),
        userVotes:    make(map[string]map[string]int),
    }
    
    bot.setupHandlers()
    return bot
}

func (pb *PollBot) setupHandlers() {
    pb.bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage == nil {
            return nil
        }
        
        text := update.NewMessage.Text
        chatID := update.ChatID
        userID := update.NewMessage.SenderID
        
        switch {
        case strings.HasPrefix(text, "/create_poll"):
            return pb.handleCreatePoll(ctx, chatID, userID, text)
        case strings.HasPrefix(text, "/poll_stats"):
            return pb.handlePollStats(ctx, chatID, text)
        case update.NewMessage.Poll != nil:
            return pb.handleVote(ctx, update)
        default:
            return pb.showPollMenu(ctx, chatID)
        }
    })
}

func (pb *PollBot) handleCreatePoll(ctx context.Context, chatID, userID, text string) error {
    // 📝 پارس کردن دستور: /create_poll سوال | گزینه۱ | گزینه۲ | گزینه۳
    parts := strings.Split(strings.TrimPrefix(text, "/create_poll "), "|")
    if len(parts) < 3 {
        _, err := pb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "❌ فرمت دستور نامعتبر!\n\n💡 مثال:\n/create_poll بهترین زبان برنامه‌نویسی؟ | Go | Python | JavaScript",
        })
        return err
    }
    
    question := strings.TrimSpace(parts[0])
    options := make([]string, len(parts)-1)
    
    for i, part := range parts[1:] {
        options[i] = strings.TrimSpace(part)
    }
    
    // 📊 ایجاد نظرسنجی
    messageID, err := pb.bot.CreatePoll(ctx, chatID, question, options)
    if err != nil {
        return err
    }
    
    // 💾 ذخیره اطلاعات نظرسنجی
    pb.activePolls[messageID] = &PollData{
        ID:        messageID,
        Question:  question,
        Options:   options,
        Votes:     make(map[int]int),
        Creator:   userID,
        CreatedAt: time.Now(),
    }
    
    _, err = pb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   fmt.Sprintf("✅ نظرسنجی با موفقیت ایجاد شد!\n\n📊 برای مشاهده آمار: /poll_stats_%s", messageID),
    })
    return err
}

func (pb *PollBot) handleVote(ctx context.Context, update *ParsRubika.Update) error {
    if update.NewMessage.Poll == nil {
        return nil
    }
    
    userID := update.NewMessage.SenderID
    messageID := strconv.FormatInt(update.NewMessage.MessageID, 10)
    
    poll, exists := pb.activePolls[messageID]
    if !exists {
        return nil
    }
    
    // 🗳️ ثبت رأی کاربر
    selectedOption := update.NewMessage.Poll.SelectionIndex
    
    if pb.userVotes[userID] == nil {
        pb.userVotes[userID] = make(map[string]int)
    }
    
    // 🔄 اگر کاربر قبلاً رأی داده، رأی قبلی را حذف کن
    if prevVote, exists := pb.userVotes[userID][messageID]; exists {
        poll.Votes[prevVote]--
    }
    
    // ➕ ثبت رأی جدید
    poll.Votes[selectedOption]++
    pb.userVotes[userID][messageID] = selectedOption
    
    log.Printf("✅ کاربر %s به گزینه %d رأی داد", userID, selectedOption)
    return nil
}

func (pb *PollBot) handlePollStats(ctx context.Context, chatID, text string) error {
    messageID := strings.TrimPrefix(text, "/poll_stats_")
    
    poll, exists := pb.activePolls[messageID]
    if !exists {
        _, err := pb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "❌ نظرسنجی مورد نظر یافت نشد!",
        })
        return err
    }
    
    // 📈 محاسبه آمار
    totalVotes := 0
    for _, count := range poll.Votes {
        totalVotes += count
    }
    
    var statsText strings.Builder
    statsText.WriteString(fmt.Sprintf("📊 **آمار نظرسنجی**\n\n❓ %s\n\n", poll.Question))
    
    for i, option := range poll.Options {
        voteCount := poll.Votes[i]
        percentage := 0
        if totalVotes > 0 {
            percentage = (voteCount * 100) / totalVotes
        }
        
        // 📊 ایجاد نمودار پیشرفت
        progressBar := createProgressBar(percentage, 20)
        
        statsText.WriteString(fmt.Sprintf(
            "🔹 %s\n%s %d%% (%d رأی)\n\n",
            option,
            progressBar,
            percentage,
            voteCount,
        ))
    }
    
    statsText.WriteString(fmt.Sprintf("👥 **کل آراء:** %d\n⏰ **زمان ایجاد:** %s", 
        totalVotes, 
        poll.CreatedAt.Format("2006/01/02 15:04"),
    ))
    
    _, err := pb.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   statsText.String(),
    })
    return err
}

func createProgressBar(percentage, length int) string {
    filled := (percentage * length) / 100
    empty := length - filled
    
    bar := "🟦" + strings.Repeat("🟦", filled) + strings.Repeat("⬜", empty)
    return bar
}
🔧 ربات مدیریت کانال
type ChannelManagerBot struct {
    bot          *ParsRubika.BotClient
    stateManager *ParsRubika.StateManager
    adminUsers   map[string]bool
    channelStats map[string]ChannelStats
}

type ChannelStats struct {
    MemberCount  int
    MessageCount int
    ActiveUsers  map[string]int
    LastActivity time.Time
}

func NewChannelManagerBot(token string) *ChannelManagerBot {
    bot := &ChannelManagerBot{
        bot:          ParsRubika.NewClient(token),
        stateManager: ParsRubika.NewStateManager(),
        adminUsers:   make(map[string]bool),
        channelStats: make(map[string]ChannelStats),
    }
    
    // 👥 تنظیم ادمین‌ها
    bot.adminUsers["ADMIN_USER_ID_1"] = true
    bot.adminUsers["ADMIN_USER_ID_2"] = true
    
    bot.setupHandlers()
    return bot
}

func (cm *ChannelManagerBot) setupHandlers() {
    cm.bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage == nil {
            return nil
        }
        
        userID := update.NewMessage.SenderID
        chatID := update.ChatID
        text := update.NewMessage.Text
        
        // 🔐 بررسی دسترسی ادمین
        if !cm.adminUsers[userID] {
            _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
                ChatID: chatID,
                Text:   "⛔ شما دسترسی لازم برای استفاده از این ربات را ندارید!",
            })
            return err
        }
        
        // 🎯 مسیریابی دستورات ادمین
        switch {
        case strings.HasPrefix(text, "/broadcast"):
            return cm.handleBroadcast(ctx, chatID, userID, text)
        case text == "/stats":
            return cm.handleStats(ctx, chatID)
        case strings.HasPrefix(text, "/post"):
            return cm.handlePost(ctx, chatID, text)
        case strings.HasPrefix(text, "/pin"):
            return cm.handlePinMessage(ctx, chatID, text)
        case strings.HasPrefix(text, "/ban"):
            return cm.handleBanUser(ctx, chatID, text)
        default:
            return cm.showAdminMenu(ctx, chatID)
        }
    })
}

func (cm *ChannelManagerBot) showAdminMenu(ctx context.Context, chatID string) error {
    menuText := `🛠️ **پنل مدیریت کانال**

🎯 **دستورات مدیریتی:**
/broadcast [متن] - ارسال پیام همگانی
/stats - آمار کانال
/post [متن] - ارسال پست در کانال
/pin [message_id] - پین کردن پیام
/ban [user_id] - مسدود کردن کاربر

💡 **برای استفاده، دستور مورد نظر را وارد کنید.**`
    
    _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   menuText,
    })
    return err
}

func (cm *ChannelManagerBot) handleBroadcast(ctx context.Context, chatID, userID, text string) error {
    broadcastText := strings.TrimSpace(strings.TrimPrefix(text, "/broadcast"))
    
    if broadcastText == "" {
        _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: chatID,
            Text:   "❌ لطفا متن پیام همگانی را وارد کنید!\n\n💡 مثال:\n/broadcast سلام به همه کاربران عزیز! 👋",
        })
        return err
    }
    
    // 📨 ارسال پیام همگانی به کاربران
    // در اینجا باید لیست کاربران از دیتابیس خوانده شود
    users := []string{"USER_1", "USER_2", "USER_3"} // کاربران نمونه
    
    successCount := 0
    for _, userID := range users {
        _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: userID,
            Text:   fmt.Sprintf("📢 **پیام همگانی:**\n\n%s", broadcastText),
        })
        
        if err != nil {
            log.Printf("❌ خطا در ارسال به کاربر %s: %v", userID, err)
        } else {
            successCount++
        }
        
        // ⏳ تأخیر برای جلوگیری از محدودیت rate
        time.Sleep(100 * time.Millisecond)
    }
    
    // 📊 گزارش نتیجه
    _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text: fmt.Sprintf("✅ **گزارش ارسال همگانی**

📤 ارسال شده به: %d کاربر
❌ ناموفق: %d کاربر
📝 متن پیام: %s",
            successCount,
            len(users)-successCount,
            broadcastText,
        ),
    })
    return err
}

func (cm *ChannelManagerBot) handleStats(ctx context.Context, chatID string) error {
    // 📊 جمع‌آوری آمار از کانال‌ها
    var statsText strings.Builder
    statsText.WriteString("📊 **آمار کانال‌ها**\n\n")
    
    for channelID, stats := range cm.channelStats {
        channelInfo, err := cm.bot.GetChat(ctx, channelID)
        if err != nil {
            continue
        }
        
        statsText.WriteString(fmt.Sprintf(
            "📢 **%s**\n👥 اعضا: %d\n💬 پیام‌ها: %d\n🕒 آخرین فعالیت: %s\n\n%s\n",
            channelInfo.Title,
            stats.MemberCount,
            stats.MessageCount,
            stats.LastActivity.Format("15:04"),
            strings.Repeat("─", 30),
        ))
    }
    
    _, err := cm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
        ChatID: chatID,
        Text:   statsText.String(),
    })
    return err
}

☁ استقرار و دیپلوی

🐳 داکرایز کردن
Dockerfile
FROM golang:1.21-alpine AS builder

WORKDIR /app

# 📦 کپی فایل‌های وابستگی
COPY go.mod go.sum ./
RUN go mod download

# 🏗 کپی سورس کد و ساخت
COPY . .
RUN go build -o rubika-bot .

FROM alpine:latest

RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/

# 📋 کپی باینری ساخته شده
COPY --from=builder /app/rubika-bot .

# 🔑 کپی فایل‌های پیکربندی
COPY config.yaml ./

# 🚪 اکسپوز پورت
EXPOSE 8080

# 🚀 اجرای ربات
CMD ["./rubika-bot"]
docker-compose.yml
version: '3.8'

services:
  rubika-bot:
    build: .
    ports:
      - "8080:8080"
    environment:
      - RUBIKA_BOT_TOKEN=${RUBIKA_BOT_TOKEN}
      - DATABASE_URL=${DATABASE_URL}
    volumes:
      - ./logs:/app/logs
      - ./data:/app/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # 🗄️ دیتابیس اختیاری (PostgreSQL)
  postgres:
    image: postgres:15-alpine
    container_name: rubika-bot-db
    environment:
      - POSTGRES_DB=rubika_bot
      - POSTGRES_USER=bot_user
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U bot_user -d rubika_bot"]
      interval: 10s
      timeout: 5s
      retries: 5

  # 📊 Redis برای کش و State Management
  redis:
    image: redis:7-alpine
    container_name: rubika-bot-redis
    volumes:
      - redis_data:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  postgres_data:
  redis_data:
🚀 استقرار روی سرور
1. تنظیمات systemd
# /etc/systemd/system/rubika-bot.service
[Unit]
Description=Rubika Bot Service
After=network.target postgresql.service redis.service
Wants=network.target

[Service]
Type=simple
User=botuser
Group=botuser
WorkingDirectory=/opt/rubika-bot
Environment="RUBIKA_BOT_TOKEN=your_bot_token_here"
Environment="DATABASE_URL=postgresql://bot_user:password@localhost:5432/rubika_bot"
Environment="REDIS_URL=redis://localhost:6379"
ExecStart=/opt/rubika-bot/rubika-bot
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=rubika-bot

# 🔒 امنیت
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/rubika-bot/data /opt/rubika-bot/logs

[Install]
WantedBy=multi-user.target
2. اسکریپت استقرار
#!/bin/bash
# deploy.sh - اسکریپت استقرار خودکار

set -e

echo "🚀 شروع استقرار ربات..."

# 🔄 توقف سرویس فعلی
echo "🛑 توقف سرویس ربات..."
sudo systemctl stop rubika-bot || true

# 📥 دریافت آخرین تغییرات
echo "📥 دریافت آخرین نسخه از گیت‌هاب..."
git pull origin main

# 📦 ساخت پروژه
echo "🏗 ساخت باینری پروژه..."
go build -ldflags="-s -w" -o rubika-bot .

# 🔒 تنظیم مجوزها
echo "🔒 تنظیم مجوزهای فایل‌ها..."
chmod +x rubika-bot
sudo chown botuser:botuser rubika-bot

# 🗄️ اجرای Migrations دیتابیس (اگر نیاز باشد)
# echo "🗄️ اجرای Migrations دیتابیس..."
# ./rubika-bot migrate up

# 🚀 راه‌اندازی سرویس
echo "🚀 راه‌اندازی مجدد سرویس..."
sudo systemctl daemon-reload
sudo systemctl start rubika-bot
sudo systemctl enable rubika-bot

# ✅ بررسی وضعیت
echo "✅ بررسی وضعیت سرویس..."
sleep 5
if sudo systemctl is-active --quiet rubika-bot; then
    echo "🎉 استقرار با موفقیت انجام شد!"
    sudo systemctl status rubika-bot --no-pager -l
else
    echo "❌ خطا در راه‌اندازی سرویس!"
    sudo journalctl -u rubika-bot -n 20 --no-pager
    exit 1
fi
☁️ استقرار ابری (AWS/GCP/Azure)
Kubernetes Deployment
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rubika-bot
  labels:
    app: rubika-bot
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: rubika-bot
  template:
    metadata:
      labels:
        app: rubika-bot
    spec:
      containers:
      - name: rubika-bot
        image: your-registry/rubika-bot:latest
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: RUBIKA_BOT_TOKEN
          valueFrom:
            secretKeyRef:
              name: bot-secrets
              key: token
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: bot-secrets
              key: database-url
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "100m"
        livenessProbe:
          httpGet:
            path: /health
            port: http
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: http
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: rubika-bot-service
spec:
  selector:
    app: rubika-bot
  ports:
    - protocol: TCP
      port: 80
      targetPort: http
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: rubika-bot-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - bot.yourdomain.com
    secretName: rubika-bot-tls
  rules:
  - host: bot.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: rubika-bot-service
            port:
              number: 80
GitHub Actions CI/CD
# .github/workflows/deploy.yml
name: Build and Deploy

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Go
      uses: actions/setup-go@v3
      with:
        go-version: 1.21
    
    - name: Cache Go modules
      uses: actions/cache@v3
      with:
        path: ~/go/pkg/mod
        key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
        restore-keys: |
          ${{ runner.os }}-go-
    
    - name: Download dependencies
      run: go mod download
    
    - name: Run tests
      run: go test -v -race -coverprofile=coverage.out ./...
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage.out

  build-and-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}
    
    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: your-registry/rubika-bot
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha,prefix={{branch}}-
    
    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

  deploy:
    needs: build-and-push
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'v1.24.0'
    
    - name: Configure kubectl
      run: |
        echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
        export KUBECONFIG=kubeconfig
    
    - name: Deploy to Kubernetes
      run: |
        export KUBECONFIG=kubeconfig
        kubectl set image deployment/rubika-bot rubika-bot=your-registry/rubika-bot:main -n rubika-bot
        kubectl rollout status deployment/rubika-bot -n rubika-bot

🔧 عیب‌یابی

🚨 خطاهای رایج
1. خطای اتصال
// 🔌 مشکل: عدم اتصال به API روبیکا
func handleConnectionError(err error) {
    if strings.Contains(err.Error(), "connection refused") {
        log.Println("❌ خطای اتصال: سرور روبیکا در دسترس نیست")
        log.Println("💡 راه‌حل: اینترنت و فایروال را بررسی کنید")
    } else if strings.Contains(err.Error(), "timeout") {
        log.Println("⏰ خطای تایم‌اوت: پاسخ سرور طولانی شد")
        log.Println("💡 راه‌حل: تایم‌اوت را افزایش دهید یا شبکه را بررسی کنید")
    } else if strings.Contains(err.Error(), "no such host") {
        log.Println("🌐 خطای DNS: نام دامنه پیدا نشد")
        log.Println("💡 راه‌حل: تنظیمات DNS و فایل hosts را بررسی کنید")
    }
}
2. خطای توکن
// 🔑 مشکل: توکن نامعتبر
func handleTokenError(err error) {
    if strings.Contains(err.Error(), "unauthorized") || strings.Contains(err.Error(), "401") {
        log.Println("❌ خطای احراز هویت: توکن نامعتبر است")
        log.Println("💡 راه‌حل:")
        log.Println("  1. توکن را از @rubika_bot دریافت کنید")
        log.Println("  2. مطمئن شوید ربات فعال است")
        log.Println("  3. توکن را درست کپی کنید (فضاهای خالی را حذف کنید)")
        log.Println("  4. از صحیح بودن متغیر محیطی RUBIKA_BOT_TOKEN اطمینان حاصل کنید")
    }
}
3. محدودیت نرخ ارسال
// 🚦 مشکل: ارسال درخواست‌های زیاد
func handleRateLimit(bot *ParsRubika.BotClient) {
    // ⏳ افزایش تأخیر بین درخواست‌ها
    log.Println("🚦 خطای محدودیت نرخ ارسال دریافت شد")
    log.Println("💡 راه‌حل: افزایش تأخیر بین درخواست‌ها")
    
    // 🔄 ساخت مجدد کلاینت با تنظیمات جدید
    bot = ParsRubika.NewClient(token,
        ParsRubika.WithRateLimitDelay(2 * time.Second),
        ParsRubika.WithMaxRetries(5),
    )
}
📊 مانیتورینگ و سلامت
سلامت‌سنجی (Health Check)
func startHealthCheck(bot *ParsRubika.BotClient) {
    ticker := time.NewTicker(5 * time.Minute)
    
    go func() {
        for range ticker.C {
            ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
            
            // 🔍 بررسی وضعیت ربات
            _, err := bot.GetMe(ctx)
            if err != nil {
                log.Printf("⚠️ بررسی سلامت ناموفق: %v", err)
                
                // 🔄 تلاش برای بازیابی
                if strings.Contains(err.Error(), "token") {
                    log.Println("🔄 تلاش برای بازنشانی توکن...")
                    // منطق بازنشانی توکن یا ارسال هشدار به ادمین
                }
            } else {
                log.Println("✅ ربات در وضعیت سالم")
            }
            
            cancel()
        }
    }()
}

// 🌐 افزودن endpoint سلامت برای وب‌هوک
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"status": "ok", "timestamp": "` + time.Now().Format(time.RFC3339) + `"}`))
}
میدلور لاگینگ پیشرفته
type LoggingMiddleware struct {
    bot *ParsRubika.BotClient
}

func (lm *LoggingMiddleware) HandleUpdate(ctx context.Context, update *ParsRubika.Update, next ParsRubika.HandlerFunc) error {
    start := time.Now()
    
    log.Printf("📥 آپدیت دریافت شد - نوع: %s, چت: %s, کاربر: %s", 
        update.Type, update.ChatID, getSenderID(update))
    
    err := next(ctx, update)
    
    duration := time.Since(start)
    if err != nil {
        log.Printf("❌ خطا در پردازش آپدیت پس از %v: %v", duration, err)
        
        // 📧 ارسال گزارش خطا (اختیاری)
        go lm.sendErrorReport(ctx, update, err)
    } else {
        log.Printf("✅ آپدیت با موفقیت پردازش شد در %v", duration)
    }
    
    return err
}

func getSenderID(update *ParsRubika.Update) string {
    if update.NewMessage != nil {
        return update.NewMessage.SenderID
    }
    if update.UpdatedMessage != nil {
        return update.UpdatedMessage.SenderID
    }
    return "Unknown"
}

func (lm *LoggingMiddleware) sendErrorReport(ctx context.Context, update *ParsRubika.Update, err error) {
    // 📨 ارسال گزارش خطا به ادمین
    errorMsg := fmt.Sprintf(`🚨 **گزارش خطا در ربات**

💬 چت: %s
👤 کاربر: %s
❌ خطا: %v
⏰ زمان: %s
📄 آپدیت: %+v`,
        update.ChatID,
        getSenderID(update),
        err,
        time.Now().Format("2006/01/02 15:04:05"),
        update,
    )
    
    // ارسال به ادمین‌ها
    adminIDs := []string{"ADMIN_ID_1", "ADMIN_ID_2"}
    for _, adminID := range adminIDs {
        lm.bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
            ChatID: adminID,
            Text:   errorMsg,
        })
    }
}
🛠 ابزارهای توسعه
اسکریپت توسعه
#!/bin/bash
# dev.sh - اسکریپت توسعه

set -e

echo "🔧 محیط توسعه ParsRubika"

case "$1" in
    "run")
        echo "🚀 اجرای ربات در حالت توسعه..."
        RUBIKA_BOT_TOKEN=${RUBIKA_BOT_TOKEN:-"dev_token"} go run main.go handlers.go utils.go
        ;;
    "test")
        echo "🧪 اجرای تست‌ها..."
        go test -v -race -coverprofile=coverage.out ./...
        go tool cover -html=coverage.out -o coverage.html
        echo "📊 گزارش پوشش در coverage.html ذخیره شد"
        ;;
    "build")
        echo "🏗 ساخت باینری..."
        go build -ldflags="-s -w" -o rubika-bot .
        ;;
    "lint")
        echo "📝 بررسی کد با golangci-lint..."
        golangci-lint run
        ;;
    "fmt")
        echo "🎨 فرمت‌بندی کد..."
        go fmt ./...
        goimports -w .
        ;;
    "clean")
        echo "🧹 پاک‌سازی..."
        go clean
        rm -f rubika-bot coverage.out coverage.html
        ;;
    "docker-build")
        echo "🐳 ساخت ایمیج داکر..."
        docker build -t rubika-bot:dev .
        ;;
    "docker-run")
        echo "🐳 اجرا با داکر..."
        docker run --rm -it -p 8080:8080 -e RUBIKA_BOT_TOKEN=$RUBIKA_BOT_TOKEN rubika-bot:dev
        ;;
    *)
        echo "💡 استفاده: ./dev.sh [run|test|build|lint|fmt|clean|docker-build|docker-run]"
        echo ""
        echo "📋 دستورات:"
        echo "  run           - اجرای ربات در حالت توسعه"
        echo "  test          - اجرای تست‌ها و گزارش پوشش"
        echo "  build         - ساخت باینری"
        echo "  lint          - بررسی کد با linter"
        echo "  fmt           - فرمت‌بندی کد"
        echo "  clean         - پاک‌سازی فایل‌های اضافی"
        echo "  docker-build  - ساخت ایمیج داکر"
        echo "  docker-run    - اجرا با داکر"
        ;;
esac
پیکربندی محیط
# config.yaml
bot:
  token: "${RUBIKA_BOT_TOKEN}"
  webhook:
    enabled: false
    port: 8080
    path: "/webhook"
    secret: "${WEBHOOK_SECRET}"
  polling:
    enabled: true
    interval: "2s"
    limit: 100
    timeout: "30s"

database:
  url: "${DATABASE_URL}"
  max_connections: 20
  max_idle_connections: 5
  connection_max_lifetime: "1h"

redis:
  url: "${REDIS_URL}"
  pool_size: 10

logging:
  level: "info"
  format: "json" # json or text
  file: "logs/bot.log"
  max_size: 100 # MB
  max_backups: 3
  max_age: 28 # days

features:
  state_management: true
  file_upload: true
  admin_panel: true
  anti_spam: true
  hot_reload: false

monitoring:
  prometheus:
    enabled: true
    port: 9090
  health_check:
    enabled: true
    path: "/health"

📞 پشتیبانی

🔗 ارتباط با توسعه‌دهنده
  • 👤 ایدی روبیکا: NinjaCode
  • 📢 چنل روبیکا: Ninja_code
  • 📧 ایمیل: ninjacode.ir@gmail.com
  • 🐙 گیت‌هاب: Abolfazl-Zarei
  • 🌐 وب‌سایت: ninjacode.ir (در صورت وجود)
📝 گزارش مشکل

برای گزارش باگ یا درخواست ویژگی جدید، لطفاً مراحل زیر را دنبال کنید:

  1. جستجو: ابتدا در ایسوها جستجو کنید تا مطمئن شوید مشکل تکراری نیست.
  2. ایجاد ایسو جدید:
    • از یک عنوان واضح و مشخص استفاده کنید.
    • توضیح دهید که مشکل چیست و چگونه می‌توان آن را بازتولید کرد.
    • قطعه کد مربوطه را ارسال کنید.
    • خروجی خطا را کامل کپی کنید.
    • محیط خود را مشخص کنید (نسخه Go, سیستم‌عامل, نسخه کتابخانه).
# 1. بررسی نسخه‌ها
go version
go list -m all | grep ParsRubika

# 2. بررسی لاگ‌ها
tail -f logs/bot.log

# 3. جمع‌آوری اطلاعات سیستم
go env
uname -a
🤝 مشارکت در توسعه

مشارکت شما باعث خوشحالی ماست! برای شروع:

  1. Fork کردن پروژه: روی دکمه Fork در بالای صفحه گیت‌هاب کلیک کنید.
  2. کلون کردن مخزن:
    git clone https://github.com/YOUR_USERNAME/ParsRubika-bot-go.git
    cd ParsRubika-bot-go
    
  3. ایجاد شاخه جدید:
    git checkout -b feature/amazing-feature
    
  4. انجام تغییرات:
    • کد خود را بنویسید.
    • تست‌های مربوطه را اضافه کنید.
    • مطمئن شوید که همه تست‌ها پاس می‌شوند: go test ./...
    • کد را با go fmt و goimports فرمت کنید.
  5. کامیت کردن تغییرات:
    git add .
    git commit -m "اضافه کردن قابلیت جدید: توضیحی کوتاه در مورد تغییرات"
    
  6. Push کردن به شاخه خود:
    git push origin feature/amazing-feature
    
  7. ایجاد Pull Request:
    • به صفحه مخزن خود در گیت‌هاب بروید.
    • روی دکمه "New pull request" کلیک کنید.
    • شاخه خود را با شاخه main اصلی مقایسه کنید.
    • یک توضیح واضح برای PR خود بنویسید.

🎉 نتیجه‌گیری

ParsRubika یک کتابخانه کامل، قدرتمند و کاربردی برای ساخت ربات‌های روبیکا با زبان Go است. با استفاده از این مستندات می‌توانید:

✅ آنچه یاد گرفتید:
  • 🏗 ساختار کلی کتابخانه و مفاهیم پایه
  • نصب و راه‌اندازی سریع و آسان
  • 🛠 آموزش قدم به قدم از مبتدی تا پیشرفته
  • 📡 API Reference کامل برای تمام متدها
  • 🎛 مدیریت وضعیت پیشرفته کاربران
  • کیبوردهای پویا و تعاملی
  • 📁 مدیریت فایل‌ها و مدیا
  • 🌐 Webhook و Polling برای دریافت آپدیت‌ها
  • 🚀 مثال‌های پیشرفته واقعی (فروشگاه، نظرسنجی، مدیریت کانال)
  • استقرار و دیپلوی حرفه‌ای (داکر، کوبرنتیز)
  • 🔧 عیب‌یابی و مانیتورینگ
  • 🛡️ قابلیت‌های پیشرفته مانند Hot-Reload و Anti-Spam
🚀 شروع نهایی
package main

import (
    "context"
    "log"
    "os"
    
    ParsRubika "github.com/Abolfazl-Zarei/ParsRubika-bot-go"
)

func main() {
    // 🤖 ایجاد ربات با تمام قابلیت‌ها
    bot := ParsRubika.NewClient(os.Getenv("RUBIKA_BOT_TOKEN"),
        ParsRubika.WithRateLimitDelay(1*time.Second),
        ParsRubika.WithMaxRetries(3),
        ParsRubika.WithIgnoreTimeout(true),
        ParsRubika.WithHotReload(true),
    )
    
    // 🎯 هندلر ساده و قدرتمند
    bot.OnMessageUpdates(func(ctx context.Context, update *ParsRubika.Update) error {
        if update.NewMessage != nil {
            // 🛡️ بررسی ضد اسپم
            if !bot.CheckAntiSpam(update.NewMessage.SenderID) {
                return nil
            }
            
            // 💾 ذخیره وضعیت کاربر
            bot.SetState(update.NewMessage.SenderID, "last_message", update.NewMessage.Text)
            
            // 📨 ارسال پاسخ
            _, err := bot.SendMessage(ctx, &ParsRubika.SendMessageRequest{
                ChatID: update.ChatID,
                Text:   "👋 سلام! من با ParsRubika ساخته شده‌ام! 🚀",
            })
            return err
        }
        return nil
    })
    
    // 🚀 اجرا
    ctx := context.Background()
    log.Println("🎉 ربات شروع به کار کرد...")
    if err := bot.Run(ctx); err != nil {
        log.Fatal("💥 خطا در اجرای ربات:", err)
    }
}
📚 منابع بیشتر

🎯 همین حالا شروع کنید!

با ParsRubika، ربات‌های قدرتمند روبیکا بسازید 🚀

Footer

ساخته شده با ❤️ توسط ابوالفضل زارعی (NinjaCode)

📧 ninjacode.ir@gmail.com | 🐙 گیت‌هاب | 📱 روبیکا

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrBotAlreadyRunning = fmt.Errorf("بات در حال حاضر در حال اجراست")

ErrBotAlreadyRunning خطایی برای تلاش در راه‌اندازی مجدد بات در حال اجرا

View Source
var ErrBotBlocked = fmt.Errorf("بات توسط روبیکا مسدود شده است")

ErrBotBlocked خطایی برای بات مسدود شده

View Source
var ErrBotNotRunning = fmt.Errorf("بات در حال حاضر متوقف است")

ErrBotNotRunning خطایی برای تلاش در متوقف کردن باتی که در حال اجرا نیست

View Source
var ErrChatNotFound = fmt.Errorf("چت مورد نظر یافت نشد")

ErrChatNotFound خطایی برای چت یافت نشده

View Source
var ErrDownloadFailed = fmt.Errorf("دانلود فایل با شکست مواجه شد")

ErrDownloadFailed خطایی برای شکست در دانلود فایل

View Source
var ErrFileNotFound = fmt.Errorf("فایل مورد نظر یافت نشد")

ErrFileNotFound خطایی برای فایل یافت نشده

View Source
var ErrFileTooLarge = fmt.Errorf("حجم فایل بیش از حد مجاز است")

ErrFileTooLarge خطایی برای فایل بسیار بزرگ

View Source
var ErrHandlerFailed = fmt.Errorf("اجرای هندلر با شکست مواجه شد")

ErrHandlerFailed خطایی برای شکست در اجرای یک هندلر

View Source
var ErrHotReloadFailed = fmt.Errorf("عملیات بارگذاری مجدد (Hot-Reload) با شکست مواجه شد")

ErrHotReloadFailed خطایی برای شکست در عملیات Hot-Reload

View Source
var ErrInternalServer = fmt.Errorf("خطای داخلی سرور روبیکا رخ داده است")

ErrInternalServer خطایی برای خطای داخلی سرور

View Source
var ErrInvalidChatType = fmt.Errorf("نوع چت نامعتبر است")

ErrInvalidChatType خطایی برای نوع چت نامعتبر

View Source
var ErrInvalidFile = fmt.Errorf("فایل ورودی نامعتبر است")

ErrInvalidFile خطایی برای فایل نامعتبر

View Source
var ErrInvalidMediaType = fmt.Errorf("نوع رسانه (Media Type) نامعتبر است")

ErrInvalidMediaType خطایی برای نوع رسانه نامعتبر

View Source
var ErrInvalidParameter = fmt.Errorf("پارامتر ورودی نامعتبر است")

ErrInvalidParameter خطایی برای پارامتر نامعتبر

View Source
var ErrInvalidToken = fmt.Errorf("توکن بات نامعتبر است")

ErrInvalidToken خطایی برای توکن نامعتبر

View Source
var ErrMessageNotFound = fmt.Errorf("پیام مورد نظر یافت نشد")

ErrMessageNotFound خطایی برای پیام یافت نشده

View Source
var ErrNetwork = fmt.Errorf("خطا در اتصال به شبکه")

ErrNetwork خطایی برای خطای شبکه

View Source
var ErrPermissionDenied = fmt.Errorf("شما دسترسی لازم برای انجام این عملیات را ندارید")

ErrPermissionDenied خطایی برای عدم دسترسی

View Source
var ErrPollingFailed = fmt.Errorf("فرآیند دریافت آپدیت‌ها (پولینگ) با شکست مواجه شد")

ErrPollingFailed خطایی برای شکست در فرآیند پولینگ

View Source
var ErrStateNotFound = fmt.Errorf("وضعیت مورد نظر برای کاربر یافت نشد")

ErrStateNotFound خطایی برای وضعیت (state) یافت نشده

View Source
var ErrTimeout = fmt.Errorf("زمان انتظار برای پاسخ سرور به پایان رسید")

ErrTimeout خطایی برای اتمام زمان انتظار (Timeout)

View Source
var ErrTooManyRequests = fmt.Errorf("تعداد درخواست‌ها بیش از حد مجاز است. لطفاً کمی صبر کنید")

ErrTooManyRequests خطایی برای درخواست‌های زیاد

View Source
var ErrUnsupportedMethod = fmt.Errorf("این متد توسط API رسمی روبیکا پشتیبانی نمی‌شود")

ErrUnsupportedMethod خطایی برای متدهای پشتیبانی نشده

View Source
var ErrUploadFailed = fmt.Errorf("آپلود فایل با شکست مواجه شد")

ErrUploadFailed خطایی برای شکست در آپلود فایل

View Source
var ErrUserBlocked = fmt.Errorf("کاربر مورد نظر مسدود شده است")

ErrUserBlocked خطایی برای کاربر مسدود شده

View Source
var ErrUserBlockedByAntiSpam = fmt.Errorf("کاربر به دلیل فعالیت مشکوک توسط سیستم ضد اسپم مسدود شد")

ErrUserBlockedByAntiSpam خطایی برای مسدود شدن کاربر توسط سیستم ضد اسپم

View Source
var ErrWebhookSetupFailed = fmt.Errorf("تنظیم وب‌هوک با شکست مواجه شد")

ErrWebhookSetupFailed خطایی برای شکست در تنظیم وب‌هوک

Functions

func BlockQuote

func BlockQuote(text string) string

BlockQuote ایجاد بلوک نقل قول

func Bold

func Bold(text string) string

Bold متن را ضخیم می‌کند (استفاده از ** برای خوانایی بهتر)

func Code

func Code(text string) string

Code متن را به صورت کد نمایش می‌دهد

func Hashtag

func Hashtag(tag string) string

Hashtag ایجاد هشتگ

func Italic

func Italic(text string) string

Italic متن را کج می‌کند

func Link(text, url string) string

Link ایجاد لینک

func Mention

func Mention(username string) string

Mention ایجاد اشاره به کاربر

func OrderedList

func OrderedList(items []string) string

OrderedList ایجاد لیست مرتب (با فرمت Markdown)

func Pre

func Pre(text string) string

Pre متن را به صورت بلوک کد نمایش می‌دهد

func Quote

func Quote(text string) string

Quote ایجاد نقل قول

func Spoiler

func Spoiler(text string) string

Spoiler متن را به صورت اسپویلر نمایش می‌دهد

func Strikethrough

func Strikethrough(text string) string

Strikethrough متن را خط‌خورده می‌کند

func Underline

func Underline(text string) string

Underline متن را زیرخط‌دار می‌کند (با استفاده از تگ HTML) نکته: زیرخط‌دار بخش استاندارد Markdown نیست و ممکن است در همه پلتفرم‌ها پشتیبانی نشود.

func UnorderedList

func UnorderedList(items []string) string

UnorderedList ایجاد لیست نامرتب (با فرمت Markdown)

Types

type APIError

type APIError struct {
	StatusCode int    `json:"-"` // وضعیت HTTP
	Message    string `json:"message"`
	Code       string `json:"code,omitempty"` // کد خطای اختصاصی API (در صورت وجود)
}

APIError ساختاری برای خطاهای بازگشتی از API روبیکا

func (*APIError) Error

func (e *APIError) Error() string

Error متد رابط خطا برای نمایش پیام خطا

func (*APIError) Is

func (e *APIError) Is(target error) bool

Is بررسی اینکه آیا خطای داده شده با خطای API فعلی مطابقت دارد یا خیر

type AntiSpam

type AntiSpam struct {
	// contains filtered or unexported fields
}

AntiSpam برای جلوگیری از اسپم و درخواست‌های مکرر کاربران

func NewAntiSpam

func NewAntiSpam() *AntiSpam

NewAntiSpam ایجاد یک نمونه جدید از AntiSpam

func (*AntiSpam) Check

func (as *AntiSpam) Check(userID string) bool

Check بررسی اینکه آیا کاربر اسپم می‌کند یا خیر اگر کاربر اسپم نکند، true برمی‌گرداند. در غیر این صورت false برمی‌گرداند.

func (*AntiSpam) Reset

func (as *AntiSpam) Reset(userID string)

Reset بازنشانی وضعیت ضد اسپم برای یک کاربر خاص

func (*AntiSpam) SetCooldown

func (as *AntiSpam) SetCooldown(duration time.Duration)

SetCooldown تنظیم زمان کول‌داون

type AuxData

type AuxData struct {
	StartID  *string `json:"start_id"`
	ButtonID *string `json:"button_id"`
}

AuxData داده‌های کمکی

type BanChatMemberRequest

type BanChatMemberRequest struct {
	ChatID string `json:"chat_id"`
	UserID string `json:"user_id"`
}

BanChatMemberRequest درخواست مسدود کردن عضو چت

type BaseRequest

type BaseRequest struct{}

BaseRequest مدل پایه برای درخواست‌ها

type BaseResponse

type BaseResponse struct {
	OK          bool                `json:"ok"`
	ErrorCode   int                 `json:"error_code,omitempty"`
	Description string              `json:"description,omitempty"`
	Parameters  *ResponseParameters `json:"parameters,omitempty"`
}

BaseResponse مدل پایه برای پاسخ‌ها

type Bot

type Bot struct {
	BotID        string `json:"bot_id"`
	BotTitle     string `json:"bot_title"`
	Avatar       *File  `json:"avatar"`
	Description  string `json:"description"`
	Username     string `json:"username"`
	StartMessage string `json:"start_message"`
	ShareURL     string `json:"share_url"`
}

Bot اطلاعات بات

type BotClient

type BotClient struct {
	// contains filtered or unexported fields
}

BotClient کلاینت اصلی بات

func NewClient

func NewClient(token string, opts ...ClientOption) *BotClient

NewClient ایجاد یک نمونه جدید از BotClient (نسخه اصلاح‌شده)

func (*BotClient) AddHandler

func (c *BotClient) AddHandler(handler HandlerFunc, filter FilterFunc, order ...int)

AddHandler اضافه کردن هندلر

func (*BotClient) BanChatMember

func (c *BotClient) BanChatMember(ctx context.Context, req *BanChatMemberRequest) error

BanChatMember مسدود کردن عضو چت

func (*BotClient) CheckAntiSpam

func (c *BotClient) CheckAntiSpam(userID string) bool

CheckAntiSpam بررسی ضد اسپم

func (*BotClient) Close

func (c *BotClient) Close() error

Close بستن کلاینت

func (*BotClient) Connect

func (c *BotClient) Connect(ctx context.Context) error

Connect اتصال به API (همان init)

func (*BotClient) CreatePoll

func (c *BotClient) CreatePoll(ctx context.Context, chatID string, question string, options []string) (string, error)

CreatePoll ایجاد نظرسنجی

func (*BotClient) DeleteAvatar

func (c *BotClient) DeleteAvatar(ctx context.Context) error

DeleteAvatar حذف آواتار

func (*BotClient) DeleteMessage

func (c *BotClient) DeleteMessage(ctx context.Context, req *DeleteMessageRequest) error

DeleteMessage حذف پیام

func (*BotClient) DeleteMetadata

func (c *BotClient) DeleteMetadata(key string)

DeleteMetadata حذف متادیتا

func (*BotClient) DeleteState

func (c *BotClient) DeleteState(userID, key string)

DeleteState حذف وضعیت برای کاربر

func (*BotClient) DeleteUserState

func (c *BotClient) DeleteUserState(userID string)

DeleteUserState حذف تمام وضعیت‌های کاربر

func (*BotClient) DisableHotReload

func (c *BotClient) DisableHotReload()

DisableHotReload غیرفعال‌سازی قابلیت Hot-Reload

func (*BotClient) Disconnect

func (c *BotClient) Disconnect() error

Disconnect قطع اتصال

func (*BotClient) Download

func (c *BotClient) Download(ctx context.Context, fileID string, savePath string) error

Download دانلود فایل

func (*BotClient) DownloadFile

func (c *BotClient) DownloadFile(ctx context.Context, fileID string, savePath string) error

DownloadFile دانلود فایل

func (*BotClient) DownloadProfilePicture

func (c *BotClient) DownloadProfilePicture(ctx context.Context, userID string, savePath string) error

DownloadProfilePicture دانلود عکس پروفایل

func (*BotClient) EditChatKeypad

func (c *BotClient) EditChatKeypad(ctx context.Context, req *EditChatKeypadRequest) error

EditChatKeypad ویرایش کیبورد چت

func (*BotClient) EditInlineKeypad

func (c *BotClient) EditInlineKeypad(ctx context.Context, req *EditMessageKeypadRequest) error

EditInlineKeypad ویرایش کیبورد پیام

func (*BotClient) EditMessage

func (c *BotClient) EditMessage(ctx context.Context, chatID string, messageID string, newText string) error

EditMessage ویرایش پیام

func (*BotClient) EditMessageText

func (c *BotClient) EditMessageText(ctx context.Context, req *EditMessageTextRequest) error

EditMessageText ویرایش متن پیام

func (*BotClient) EnableHotReload

func (c *BotClient) EnableHotReload()

EnableHotReload فعال‌سازی قابلیت Hot-Reload

func (*BotClient) Enter

func (c *BotClient) Enter(ctx context.Context) (*BotClient, error)

Enter برای context manager

func (*BotClient) Exit

func (c *BotClient) Exit() error

Exit برای context manager

func (*BotClient) ForwardMessage

func (c *BotClient) ForwardMessage(ctx context.Context, req *ForwardMessageRequest) (string, error)

ForwardMessage فوروارد پیام

func (*BotClient) ForwardMessages

func (c *BotClient) ForwardMessages(ctx context.Context, fromChatID string, messageIDs []string, toChatID string) ([]string, error)

ForwardMessages فوروارد چندین پیام

func (*BotClient) GetBotInfo

func (c *BotClient) GetBotInfo(ctx context.Context) (*Bot, error)

GetBotInfo دریافت اطلاعات کامل بات

func (*BotClient) GetChat

func (c *BotClient) GetChat(ctx context.Context, chatID string) (*Chat, error)

GetChat دریافت اطلاعات چت

func (*BotClient) GetChatAdministrators

GetChatAdministrators دریافت مدیران چت

func (*BotClient) GetChatMember

func (c *BotClient) GetChatMember(ctx context.Context, req *GetChatMemberRequest) (*GetChatMemberResponse, error)

GetChatMember دریافت اطلاعات عضو چت

func (*BotClient) GetChatMemberCount

GetChatMemberCount دریافت تعداد اعضای چت

func (*BotClient) GetFile

func (c *BotClient) GetFile(ctx context.Context, fileID string) (*GetFileResponse, error)

GetFile دریافت اطلاعات فایل

func (*BotClient) GetMe

func (c *BotClient) GetMe(ctx context.Context) (*Bot, error)

GetMe دریافت اطلاعات بات

func (*BotClient) GetMembers

func (c *BotClient) GetMembers(ctx context.Context, chatID string) ([]ChatMember, error)

GetMembers دریافت اعضا

func (*BotClient) GetMetadata

func (c *BotClient) GetMetadata(key string) (interface{}, bool)

GetMetadata دریافت متادیتا

func (*BotClient) GetPollStatus

func (c *BotClient) GetPollStatus(ctx context.Context, chatID string, messageID string) (*PollStatus, error)

GetPollStatus دریافت وضعیت نظرسنجی

func (*BotClient) GetReloadManager

func (c *BotClient) GetReloadManager() *ReloadManager

GetReloadManager دسترسی به مدیر Hot-Reload را فراهم می‌کند

func (*BotClient) GetSelectionItem

GetSelectionItem دریافت آیتم‌های انتخابی

func (*BotClient) GetState

func (c *BotClient) GetState(userID, key string) (interface{}, bool)

GetState دریافت وضعیت برای کاربر

func (*BotClient) GetUpdates

func (c *BotClient) GetUpdates(ctx context.Context, offsetID *string, limit int) (*GetUpdatesResponse, error)

GetUpdates دریافت آپدیت‌ها

func (*BotClient) GetUserInfo

func (c *BotClient) GetUserInfo(ctx context.Context, userID string) (*User, error)

GetUserInfo دریافت اطلاعات کاربر

func (*BotClient) IsHotReloadEnabled

func (c *BotClient) IsHotReloadEnabled() bool

IsHotReloadEnabled بررسی وضعیت Hot-Reload

func (*BotClient) Middleware

func (c *BotClient) Middleware(middleware MiddlewareFunc)

Middleware اضافه کردن میدلور

func (*BotClient) OnAudio

func (c *BotClient) OnAudio(handler HandlerFunc)

OnAudio هندلر برای پیام‌های صوتی

func (*BotClient) OnCallbackQuery

func (c *BotClient) OnCallbackQuery(handler HandlerFunc)

OnCallbackQuery هندلر برای کوئری‌های دکمه

func (*BotClient) OnChatUpdates

func (c *BotClient) OnChatUpdates(handler HandlerFunc)

OnChatUpdates هندلر برای آپدیت‌های چت

func (*BotClient) OnCommand

func (c *BotClient) OnCommand(command string, handler HandlerFunc)

OnCommand هندلر برای دستورات

func (*BotClient) OnContact

func (c *BotClient) OnContact(handler HandlerFunc)

OnContact هندلر برای پیام‌های مخاطب

func (*BotClient) OnDocument

func (c *BotClient) OnDocument(handler HandlerFunc)

OnDocument هندلر برای پیام‌های سند

func (*BotClient) OnInlineQuery

func (c *BotClient) OnInlineQuery(handler HandlerFunc)

OnInlineQuery هندلر برای کوئری‌های اینلاین

func (*BotClient) OnLocation

func (c *BotClient) OnLocation(handler HandlerFunc)

OnLocation هندلر برای پیام‌های موقعیت مکانی

func (*BotClient) OnMessageUpdates

func (c *BotClient) OnMessageUpdates(handler HandlerFunc)

OnMessageUpdates هندلر برای آپدیت‌های پیام

func (*BotClient) OnPhoto

func (c *BotClient) OnPhoto(handler HandlerFunc)

OnPhoto هندلر برای پیام‌های عکس

func (*BotClient) OnPoll

func (c *BotClient) OnPoll(handler HandlerFunc)

OnPoll هندلر برای پیام‌های نظرسنجی

func (*BotClient) OnShutdown

func (c *BotClient) OnShutdown(handler HandlerFunc)

OnShutdown هندلر برای خاموشی بات

func (*BotClient) OnStart

func (c *BotClient) OnStart(handler HandlerFunc)

OnStart هندلر برای شروع بات

func (*BotClient) OnSticker

func (c *BotClient) OnSticker(handler HandlerFunc)

OnSticker هندلر برای پیام‌های استیکر

func (*BotClient) OnUpdate

func (c *BotClient) OnUpdate(handler HandlerFunc)

OnUpdate هندلر برای همه آپدیت‌ها

func (*BotClient) OnVideo

func (c *BotClient) OnVideo(handler HandlerFunc)

OnVideo هندلر برای پیام‌های ویدیویی

func (*BotClient) PinChatMessage

func (c *BotClient) PinChatMessage(ctx context.Context, req *PinChatMessageRequest) error

PinChatMessage پین کردن پیام

func (*BotClient) ProcessUpdate

func (c *BotClient) ProcessUpdate(ctx context.Context, update *Update) error

ProcessUpdate پردازش یک آپدیت (متد عمومی)

func (*BotClient) PromoteChatMember

func (c *BotClient) PromoteChatMember(ctx context.Context, req *PromoteChatMemberRequest) error

PromoteChatMember ارتقای عضو چت

func (*BotClient) RemoveHandler

func (c *BotClient) RemoveHandler(handler HandlerFunc)

RemoveHandler حذف هندلر

func (*BotClient) RequestSendFile

func (c *BotClient) RequestSendFile(ctx context.Context, fileType FileTypeEnum) (*RequestSendFileResponse, error)

RequestSendFile درخواست آدرس آپلود

func (*BotClient) ResetAntiSpam

func (c *BotClient) ResetAntiSpam(userID string)

ResetAntiSpam بازنشانی ضد اسپم برای کاربر

func (*BotClient) Run

func (c *BotClient) Run(ctx context.Context, pollingOpts ...PollingOptions) error

Run اجرای بات با پولینگ

func (*BotClient) SearchSelectionItems

SearchSelectionItems جستجوی آیتم‌های انتخابی

func (*BotClient) SendChatActivity

func (c *BotClient) SendChatActivity(ctx context.Context, chatID string, activity string) error

SendChatActivity ارسال فعالیت چت

func (*BotClient) SendContact

func (c *BotClient) SendContact(ctx context.Context, req *SendContactRequest) (string, error)

SendContact ارسال مخاطب

func (*BotClient) SendDocument

func (c *BotClient) SendDocument(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendDocument ارسال سند

func (*BotClient) SendFile

func (c *BotClient) SendFile(ctx context.Context, req *SendFileRequest) (string, error)

SendFile ارسال فایل

func (*BotClient) SendGif

func (c *BotClient) SendGif(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendGif ارسال گیف

func (*BotClient) SendLocation

func (c *BotClient) SendLocation(ctx context.Context, req *SendLocationRequest) (string, error)

SendLocation ارسال موقعیت مکانی

func (*BotClient) SendMessage

func (c *BotClient) SendMessage(ctx context.Context, req *SendMessageRequest) (string, error)

SendMessage ارسال پیام متنی

func (*BotClient) SendMusic

func (c *BotClient) SendMusic(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendMusic ارسال موزیک

func (*BotClient) SendPhoto

func (c *BotClient) SendPhoto(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendPhoto ارسال عکس

func (*BotClient) SendPoll

func (c *BotClient) SendPoll(ctx context.Context, req *SendPollRequest) (string, error)

SendPoll ارسال نظرسنجی

func (*BotClient) SendSticker

func (c *BotClient) SendSticker(ctx context.Context, chatID string, filePath string) (string, error)

SendSticker ارسال استیکر

func (*BotClient) SendVideo

func (c *BotClient) SendVideo(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendVideo ارسال ویدیو

func (*BotClient) SendVoice

func (c *BotClient) SendVoice(ctx context.Context, chatID string, filePath string, caption ...string) (string, error)

SendVoice ارسال پیام صوتی

func (*BotClient) SetChatPermissions

func (c *BotClient) SetChatPermissions(ctx context.Context, chatID string, permissions map[string]bool) error

SetChatPermissions تنظیم مجوزهای چت

func (*BotClient) SetCommands

func (c *BotClient) SetCommands(ctx context.Context, req *SetCommandsRequest) error

SetCommands تنظیم دستورات بات

func (*BotClient) SetMetadata

func (c *BotClient) SetMetadata(key string, value interface{})

SetMetadata تنظیم متادیتا

func (*BotClient) SetPin

func (c *BotClient) SetPin(ctx context.Context, chatID string, messageID string) error

SetPin پین کردن پیام

func (*BotClient) SetState

func (c *BotClient) SetState(userID, key string, value interface{})

SetState ذخیره وضعیت برای کاربر

func (*BotClient) SetUnpin

func (c *BotClient) SetUnpin(ctx context.Context, chatID string, messageID string) error

SetUnpin آنپین کردن پیام

func (*BotClient) Start

func (c *BotClient) Start(ctx context.Context, opts ...interface{}) error

Start شروع بات

func (*BotClient) StartPolling

func (c *BotClient) StartPolling(ctx context.Context, opts PollingOptions) error

StartPolling شروع دریافت آپدیت‌ها با پولینگ (هوشمند شده)

func (*BotClient) StartWebhook

func (c *BotClient) StartWebhook(ctx context.Context, opts WebhookOptions) error

StartWebhook راه‌اندازی سرور وب‌هوک (بهینه شده)

func (*BotClient) Stop

func (c *BotClient) Stop(ctx context.Context) error

Stop توقف بات

func (*BotClient) TerminateOtherSessions

func (c *BotClient) TerminateOtherSessions(ctx context.Context) error

TerminateOtherSessions خاتمه جلسات دیگر

func (*BotClient) UnbanChatMember

func (c *BotClient) UnbanChatMember(ctx context.Context, req *UnbanChatMemberRequest) error

UnbanChatMember رفع مسدودیت عضو چت

func (*BotClient) UnpinAllChatMessages

func (c *BotClient) UnpinAllChatMessages(ctx context.Context, chatID string) error

UnpinAllChatMessages آنپین کردن همه پیام‌ها

func (*BotClient) UnpinChatMessage

func (c *BotClient) UnpinChatMessage(ctx context.Context, req *UnpinChatMessageRequest) error

UnpinChatMessage آنپین کردن پیام

func (*BotClient) UpdateBotEndpoints

func (c *BotClient) UpdateBotEndpoints(ctx context.Context, url string, endpointType UpdateEndpointTypeEnum) error

UpdateBotEndpoints به‌روزرسانی endpointهای بات

func (*BotClient) UpdateProfile

func (c *BotClient) UpdateProfile(ctx context.Context, firstName, lastName, bio string) error

UpdateProfile به‌روزرسانی پروفایل

func (*BotClient) UpdateUsername

func (c *BotClient) UpdateUsername(ctx context.Context, username string) error

UpdateUsername به‌روزرسانی نام کاربری

func (*BotClient) Upload

func (c *BotClient) Upload(ctx context.Context, filePath string, fileType FileTypeEnum) (*File, error)

Upload آپلود فایل (مخفف)

func (*BotClient) UploadAvatar

func (c *BotClient) UploadAvatar(ctx context.Context, filePath string) (*File, error)

UploadAvatar آپلود آواتار

func (*BotClient) UploadFile

func (c *BotClient) UploadFile(uploadURL, filePath string) (*FileUploadResponse, error)

UploadFile آپلود فایل

func (*BotClient) UploadFileDirectly

func (c *BotClient) UploadFileDirectly(ctx context.Context, filePath string, fileType FileTypeEnum) (*File, error)

UploadFileDirectly آپلود فایل و دریافت اطلاعات کامل

func (*BotClient) VotePoll

func (c *BotClient) VotePoll(ctx context.Context, chatID string, messageID string, optionIndex int) error

VotePoll رأی دادن به نظرسنجی

type BotCommand

type BotCommand struct {
	Command     string `json:"command"`
	Description string `json:"description"`
}

BotCommand دستورات بات

type ButtonCalendarTypeEnum

type ButtonCalendarTypeEnum string
const (
	ButtonCalendarDatePersian   ButtonCalendarTypeEnum = "DatePersian"
	ButtonCalendarDateGregorian ButtonCalendarTypeEnum = "DateGregorian"
)

type ButtonLocationTypeEnum

type ButtonLocationTypeEnum string
const (
	ButtonLocationPicker ButtonLocationTypeEnum = "Picker"
	ButtonLocationView   ButtonLocationTypeEnum = "View"
)

type ButtonSelectionGetEnum

type ButtonSelectionGetEnum string
const (
	ButtonSelectionGetLocal ButtonSelectionGetEnum = "Local"
	ButtonSelectionGetApi   ButtonSelectionGetEnum = "Api"
)

type ButtonSelectionItem

type ButtonSelectionItem struct {
	Text     string                  `json:"text"`
	ImageUrl string                  `json:"image_url"`
	Type     ButtonSelectionTypeEnum `json:"type"`
}

ButtonSelectionItem آیتم در دکمه انتخاب

type ButtonSelectionSearchEnum

type ButtonSelectionSearchEnum string
const (
	ButtonSelectionSearchNone  ButtonSelectionSearchEnum = "None"
	ButtonSelectionSearchLocal ButtonSelectionSearchEnum = "Local"
	ButtonSelectionSearchApi   ButtonSelectionSearchEnum = "Api"
)

type ButtonSelectionTypeEnum

type ButtonSelectionTypeEnum string
const (
	ButtonSelectionTextOnly   ButtonSelectionTypeEnum = "TextOnly"
	ButtonSelectionTextImgThu ButtonSelectionTypeEnum = "TextImgThu"
	ButtonSelectionTextImgBig ButtonSelectionTypeEnum = "TextImgBig"
)

type ButtonTextboxTypeKeypadEnum

type ButtonTextboxTypeKeypadEnum string
const (
	ButtonTextboxKeypadString ButtonTextboxTypeKeypadEnum = "String"
	ButtonTextboxKeypadNumber ButtonTextboxTypeKeypadEnum = "Number"
)

type ButtonTextboxTypeLineEnum

type ButtonTextboxTypeLineEnum string
const (
	ButtonTextboxLineSingle ButtonTextboxTypeLineEnum = "SingleLine"
	ButtonTextboxLineMulti  ButtonTextboxTypeLineEnum = "MultiLine"
)

type ButtonTypeEnum

type ButtonTypeEnum string
const (
	ButtonTypeSimple           ButtonTypeEnum = "Simple"
	ButtonTypeSelection        ButtonTypeEnum = "Selection"
	ButtonTypeCalendar         ButtonTypeEnum = "Calendar"
	ButtonTypeNumberPicker     ButtonTypeEnum = "NumberPicker"
	ButtonTypeStringPicker     ButtonTypeEnum = "StringPicker"
	ButtonTypeLocation         ButtonTypeEnum = "Location"
	ButtonTypePayment          ButtonTypeEnum = "Payment"
	ButtonTypeCameraImage      ButtonTypeEnum = "CameraImage"
	ButtonTypeCameraVideo      ButtonTypeEnum = "CameraVideo"
	ButtonTypeGalleryImage     ButtonTypeEnum = "GalleryImage"
	ButtonTypeGalleryVideo     ButtonTypeEnum = "GalleryVideo"
	ButtonTypeFile             ButtonTypeEnum = "File"
	ButtonTypeAudio            ButtonTypeEnum = "Audio"
	ButtonTypeRecordAudio      ButtonTypeEnum = "RecordAudio"
	ButtonTypeMyPhoneNumber    ButtonTypeEnum = "MyPhoneNumber"
	ButtonTypeMyLocation       ButtonTypeEnum = "MyLocation"
	ButtonTypeTextbox          ButtonTypeEnum = "Textbox"
	ButtonTypeLink             ButtonTypeEnum = "Link"
	ButtonTypeAskMyPhoneNumber ButtonTypeEnum = "AskMyPhoneNumber"
	ButtonTypeAskMyLocation    ButtonTypeEnum = "AskMyLocation"
	ButtonTypeBarcode          ButtonTypeEnum = "Barcode"
	ButtonTypeWebApp           ButtonTypeEnum = "WebApp" // نوع جدید برای دکمه‌های وب اپ
	ButtonTypeLogin            ButtonTypeEnum = "Login"  // نوع جدید برای دکمه‌های لاگین
	ButtonTypeGame             ButtonTypeEnum = "Game"   // نوع جدید برای دکمه‌های بازی
)

type Chat

type Chat struct {
	ChatID    string       `json:"chat_id"`
	ChatType  ChatTypeEnum `json:"chat_type"`
	UserID    string       `json:"user_id"`
	FirstName string       `json:"first_name"`
	LastName  string       `json:"last_name"`
	Title     string       `json:"title"`
	Username  string       `json:"username"`
}

Chat اطلاعات چت

type ChatActivityEnum

type ChatActivityEnum string
const (
	ChatActivityTyping          ChatActivityEnum = "typing"
	ChatActivityUploadPhoto     ChatActivityEnum = "upload_photo"
	ChatActivityRecordVideo     ChatActivityEnum = "record_video"
	ChatActivityUploadVideo     ChatActivityEnum = "upload_video"
	ChatActivityRecordAudio     ChatActivityEnum = "record_audio"
	ChatActivityUploadAudio     ChatActivityEnum = "upload_audio"
	ChatActivityUploadDocument  ChatActivityEnum = "upload_document"
	ChatActivityFindLocation    ChatActivityEnum = "find_location"
	ChatActivityRecordVideoNote ChatActivityEnum = "record_video_note"
	ChatActivityUploadVideoNote ChatActivityEnum = "upload_video_note"
	ChatActivityChooseSticker   ChatActivityEnum = "choose_sticker"
)

type ChatKeypadTypeEnum

type ChatKeypadTypeEnum string
const (
	NoneKeypad   ChatKeypadTypeEnum = "None"
	NewKeypad    ChatKeypadTypeEnum = "New"
	RemoveKeypad ChatKeypadTypeEnum = "Remove"
)

type ChatMember

type ChatMember struct {
	User     Chat   `json:"user"`
	Status   string `json:"status"`
	JoinDate string `json:"join_date"`
}

ChatMember عضو چت

type ChatMemberStatusEnum

type ChatMemberStatusEnum string
const (
	MemberCreator       ChatMemberStatusEnum = "Creator"
	MemberAdministrator ChatMemberStatusEnum = "Administrator"
	MemberMember        ChatMemberStatusEnum = "Member"
	MemberRestricted    ChatMemberStatusEnum = "Restricted"
	MemberLeft          ChatMemberStatusEnum = "Left"
	MemberKicked        ChatMemberStatusEnum = "Kicked"
)

type ChatTypeEnum

type ChatTypeEnum string
const (
	UserChat    ChatTypeEnum = "User"
	BotChat     ChatTypeEnum = "Bot"
	GroupChat   ChatTypeEnum = "Group"
	ChannelChat ChatTypeEnum = "Channel"
)

type ClientOption

type ClientOption func(*BotClient)

ClientOption برای تنظیمات اولیه کلاینت

func WithBaseURL

func WithBaseURL(url string) ClientOption

WithBaseURL برای تغییر آدرس پایه API

func WithHTTPClient

func WithHTTPClient(client *http.Client) ClientOption

WithHTTPClient برای تنظیم کلاینت HTTP سفارشی

func WithHotReload

func WithHotReload(enabled bool) ClientOption

WithHotReload فعال‌سازی قابلیت Hot-Reload

func WithIgnoreTimeout

func WithIgnoreTimeout(ignore bool) ClientOption

WithIgnoreTimeout تنظیم نادیده گرفتن خطاهای timeout

func WithMaxRetries

func WithMaxRetries(retries int) ClientOption

WithMaxRetries تنظیم حداکثر تلاش مجدد

func WithRateLimitDelay

func WithRateLimitDelay(delay time.Duration) ClientOption

WithRateLimitDelay تنظیم تأخیر نرخ محدودیت

type ContactMessage

type ContactMessage struct {
	PhoneNumber string `json:"phone_number"`
	FirstName   string `json:"first_name"`
	LastName    string `json:"last_name"`
}

ContactMessage پیام مخاطب

type DeleteMessageRequest

type DeleteMessageRequest struct {
	ChatID    string `json:"chat_id"`
	MessageID string `json:"message_id"`
}

DeleteMessageRequest درخواست حذف پیام

type EditChatKeypadRequest

type EditChatKeypadRequest struct {
	ChatID         string               `json:"chat_id"`
	ReplyKeyboard  *ReplyKeyboardMarkup `json:"reply_keyboard,omitempty"`
	RemoveKeyboard *ReplyKeyboardRemove `json:"remove_keyboard,omitempty"`
	ChatKeypadType ChatKeypadTypeEnum   `json:"chat_keypad_type"`
}

EditChatKeypadRequest درخواست ویرایش کیبورد چت (پاسخ)

type EditMessageKeypadRequest

type EditMessageKeypadRequest struct {
	ChatID         string                `json:"chat_id"`
	MessageID      string                `json:"message_id"`
	InlineKeyboard *InlineKeyboardMarkup `json:"inline_keyboard"`
}

EditMessageKeypadRequest درخواست ویرایش کیبورد پیام (اینلاین)

type EditMessageTextRequest

type EditMessageTextRequest struct {
	ChatID               string                `json:"chat_id"`
	MessageID            string                `json:"message_id"`
	Text                 string                `json:"text"`
	InlineKeyboardMarkup *InlineKeyboardMarkup `json:"inline_keyboard,omitempty"`
}

EditMessageTextRequest درخواست ویرایش متن پیام

type File

type File struct {
	FileID   string       `json:"file_id"`
	FileName string       `json:"file_name"`
	Size     int64        `json:"size"`
	Type     FileTypeEnum `json:"type,omitempty"`
}

File اطلاعات فایل

type FileTypeEnum

type FileTypeEnum string
const (
	FileType    FileTypeEnum = "File"
	ImageType   FileTypeEnum = "Image"
	VoiceType   FileTypeEnum = "Voice"
	VideoType   FileTypeEnum = "Video"
	MusicType   FileTypeEnum = "Music"
	GifType     FileTypeEnum = "Gif"
	PhotoType   FileTypeEnum = "Photo"
	StickerType FileTypeEnum = "Sticker"
	AudioType   FileTypeEnum = "Audio" // نوع جدید برای فایل‌های صوتی
)

type FileUploadResponse

type FileUploadResponse struct {
	FileID string `json:"file_id"`
}

FileUploadResponse پاسخ آپلود فایل

type FilterFunc

type FilterFunc func(ctx context.Context, update *Update) bool

FilterFunc برای فیلتر کردن آپدیت‌ها

type FilterTypeEnum

type FilterTypeEnum string
const (
	FilterTypeText     FilterTypeEnum = "Text"
	FilterTypePhoto    FilterTypeEnum = "Photo"
	FilterTypeAudio    FilterTypeEnum = "Audio"
	FilterTypeVideo    FilterTypeEnum = "Video"
	FilterTypeDocument FilterTypeEnum = "Document"
	FilterTypeSticker  FilterTypeEnum = "Sticker"
	FilterTypeLocation FilterTypeEnum = "Location"
	FilterTypeContact  FilterTypeEnum = "Contact"
	FilterTypePoll     FilterTypeEnum = "Poll"
	FilterTypeCommand  FilterTypeEnum = "Command"
	FilterTypeCallback FilterTypeEnum = "Callback"
	FilterTypeInline   FilterTypeEnum = "Inline"
	FilterTypeEdited   FilterTypeEnum = "Edited"
	FilterTypeForward  FilterTypeEnum = "Forward"
	FilterTypeReply    FilterTypeEnum = "Reply"
	FilterTypeGroup    FilterTypeEnum = "Group"
	FilterTypeChannel  FilterTypeEnum = "Channel"
	FilterTypePrivate  FilterTypeEnum = "Private"
	FilterTypeBot      FilterTypeEnum = "Bot"
	FilterTypeUser     FilterTypeEnum = "User"
)

type FormattedMessage

type FormattedMessage struct {
	Text   string        `json:"text"`
	Format MessageFormat `json:"format"`
}

FormattedMessage پیام با فرمت خاص

func NewFormattedMessage

func NewFormattedMessage(text string, format MessageFormat) *FormattedMessage

NewFormattedMessage ایجاد یک پیام با فرمت خاص

type ForwardMessageRequest

type ForwardMessageRequest struct {
	FromChatID          string `json:"from_chat_id"`
	MessageID           string `json:"message_id"`
	ToChatID            string `json:"to_chat_id"`
	DisableNotification bool   `json:"disable_notification,omitempty"`
}

ForwardMessageRequest درخواست فوروارد پیام

type ForwardMessageResponse

type ForwardMessageResponse struct {
	NewMessageID string `json:"new_message_id"`
}

ForwardMessageResponse پاسخ فوروارد پیام

type ForwardedFrom

type ForwardedFrom struct {
	TypeFrom     ForwardedFromEnum `json:"type_from"`
	MessageID    string            `json:"message_id"`
	FromChatID   string            `json:"from_chat_id"`
	FromSenderID string            `json:"from_sender_id"`
}

ForwardedFrom اطلاعات فوروارد پیام

type ForwardedFromEnum

type ForwardedFromEnum string
const (
	ForwardedFromUser    ForwardedFromEnum = "User"
	ForwardedFromChannel ForwardedFromEnum = "Channel"
	ForwardedFromBot     ForwardedFromEnum = "Bot"
)

type GetChatAdministratorsRequest

type GetChatAdministratorsRequest struct {
	ChatID string `json:"chat_id"`
}

GetChatAdministratorsRequest درخواست دریافت مدیران چت

type GetChatAdministratorsResponse

type GetChatAdministratorsResponse struct {
	Administrators []ChatMember `json:"administrators"`
}

GetChatAdministratorsResponse پاسخ دریافت مدیران چت

type GetChatMemberCountRequest

type GetChatMemberCountRequest struct {
	ChatID string `json:"chat_id"`
}

GetChatMemberCountRequest درخواست دریافت تعداد اعضای چت

type GetChatMemberCountResponse

type GetChatMemberCountResponse struct {
	Count int `json:"count"`
}

GetChatMemberCountResponse پاسخ دریافت تعداد اعضای چت

type GetChatMemberRequest

type GetChatMemberRequest struct {
	ChatID string `json:"chat_id"`
	UserID string `json:"user_id"`
}

GetChatMemberRequest درخواست دریافت اطلاعات عضو چت

type GetChatMemberResponse

type GetChatMemberResponse struct {
	Member ChatMember `json:"member"`
}

GetChatMemberResponse پاسخ دریافت اطلاعات عضو چت

type GetChatRequest

type GetChatRequest struct {
	ChatID string `json:"chat_id"`
}

GetChatRequest درخواست دریافت اطلاعات چت

type GetFileRequest

type GetFileRequest struct {
	FileID string `json:"file_id"`
}

GetFileRequest درخواست دریافت اطلاعات فایل

type GetFileResponse

type GetFileResponse struct {
	DownloadURL string `json:"download_url"`
	FileName    string `json:"file_name"`
	Size        int64  `json:"size"` // <-- این خط را به int64 تغییر دهید
}

GetFileResponse پاسخ دریافت اطلاعات فایل

type GetSelectionItemRequest

type GetSelectionItemRequest struct {
	SelectionID string `json:"selection_id"`
	Query       string `json:"query,omitempty"`
}

GetSelectionItemRequest درخواست دریافت آیتم‌های انتخابی

type GetSelectionItemResponse

type GetSelectionItemResponse struct {
	Items []ButtonSelectionItem `json:"items"`
}

GetSelectionItemResponse پاسخ دریافت آیتم‌های انتخابی

type GetUpdatesRequest

type GetUpdatesRequest struct {
	OffsetID string `json:"offset_id,omitempty"`
	Limit    int    `json:"limit"`
}

GetUpdatesRequest درخواست دریافت آپدیت‌ها

type GetUpdatesResponse

type GetUpdatesResponse struct {
	Updates      []Update `json:"updates"`
	NextOffsetID string   `json:"next_offset_id"`
}

GetUpdatesResponse پاسخ دریافت آپدیت‌ها

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler اطلاعات هندلر

type HandlerFunc

type HandlerFunc func(ctx context.Context, update *Update) error

HandlerFunc برای پردازش آپدیت‌ها

type InlineKeyboardButton

type InlineKeyboardButton struct {
	Text                         string    `json:"text"`
	URL                          string    `json:"url,omitempty"`
	LoginURL                     *LoginUrl `json:"login_url,omitempty"`
	CallbackData                 string    `json:"callback_data,omitempty"`
	SwitchInlineQuery            string    `json:"switch_inline_query,omitempty"`
	SwitchInlineQueryCurrentChat string    `json:"switch_inline_query_current_chat,omitempty"`
}

InlineKeyboardButton دکمه کیبورد اینلاین

func NewInlineKeyboardButton

func NewInlineKeyboardButton(text string) *InlineKeyboardButton

NewInlineKeyboardButton ایجاد یک دکمه کیبورد اینلاین

func (*InlineKeyboardButton) WithCallbackData

func (b *InlineKeyboardButton) WithCallbackData(data string) *InlineKeyboardButton

WithCallbackData تنظیم داده callback برای دکمه

func (*InlineKeyboardButton) WithSwitchInlineQuery

func (b *InlineKeyboardButton) WithSwitchInlineQuery(query string) *InlineKeyboardButton

WithSwitchInlineQuery تنظیم سوئیچ اینلاین کوئری برای دکمه

func (*InlineKeyboardButton) WithURL

WithURL تنظیم URL برای دکمه

type InlineKeyboardMarkup

type InlineKeyboardMarkup struct {
	InlineKeyboard [][]*InlineKeyboardButton `json:"inline_keyboard"`
}

InlineKeyboardMarkup کیبورد اینلاین

func NewInlineKeyboard

func NewInlineKeyboard(rows ...[]*InlineKeyboardButton) *InlineKeyboardMarkup

NewInlineKeyboard ایجاد یک کیبورد اینلاین

type InlineMessage

type InlineMessage struct {
	SenderID string    `json:"sender_id"`
	Text     string    `json:"text"`
	File     *File     `json:"file"`
	Location *Location `json:"location"`
	AuxData  *AuxData  `json:"aux_data"`
	// نکته: در پاسخ‌های مربوط به receiveInlineMessage، این فیلد به صورت رشته (string) برگردانده می‌شود.
	MessageID string `json:"message_id"`
	ChatID    string `json:"chat_id"`
}

InlineMessage پیام اینلاین

type KeyboardButton

type KeyboardButton struct {
	Text            string                  `json:"text"`
	RequestContact  bool                    `json:"request_contact,omitempty"`
	RequestLocation bool                    `json:"request_location,omitempty"`
	RequestPoll     *KeyboardButtonPollType `json:"request_poll,omitempty"`
	WebApp          *WebAppInfo             `json:"web_app,omitempty"`
}

KeyboardButton دکمه کیبورد پاسخ

func NewReplyKeyboardButton

func NewReplyKeyboardButton(text string) *KeyboardButton

NewReplyKeyboardButton ایجاد یک دکمه کیبورد پاسخ

func (*KeyboardButton) WithRequestContact

func (b *KeyboardButton) WithRequestContact() *KeyboardButton

WithRequestContact تنظیم درخواست شماره تلفن برای دکمه

func (*KeyboardButton) WithRequestLocation

func (b *KeyboardButton) WithRequestLocation() *KeyboardButton

WithRequestLocation تنظیم درخواست موقعیت مکانی برای دکمه

type KeyboardButtonPollType

type KeyboardButtonPollType struct {
	Type string `json:"type"` // 'quiz' or 'regular'
}

KeyboardButtonPollType نوع نظرسنجی برای دکمه کیبورد

type Location

type Location struct {
	Longitude string `json:"longitude"`
	Latitude  string `json:"latitude"`
}

Location موقعیت مکانی

type LoginUrl

type LoginUrl struct {
	URL                string  `json:"url"`
	ForwardText        *string `json:"forward_text,omitempty"`
	BotUsername        *string `json:"bot_username,omitempty"`
	RequestWriteAccess *bool   `json:"request_write_access,omitempty"`
}

LoginUrl اطلاعات برای دکمه لاگین

type Message

type Message struct {
	// نکته: در پاسخ‌های مربوط به getUpdates و receiveUpdate، این فیلد به صورت عدد (int64) برگردانده می‌شود.
	MessageID        string            `json:"message_id"`
	Text             string            `json:"text"`
	Time             string            `json:"time"`
	IsEdited         bool              `json:"is_edited"`
	SenderType       MessageSenderEnum `json:"sender_type"`
	SenderID         string            `json:"sender_id"`
	AuxData          *AuxData          `json:"aux_data"`
	File             *File             `json:"file"`
	ReplyToMessageID string            `json:"reply_to_message_id"`
	ForwardedFrom    *ForwardedFrom    `json:"forwarded_from"`
	ForwardedNoLink  string            `json:"forwarded_no_link"`
	Location         *Location         `json:"location"`
	Sticker          *Sticker          `json:"sticker"`
	ContactMessage   *ContactMessage   `json:"contact_message"`
	Poll             *Poll             `json:"poll"`
	Payment          *PaymentStatus    `json:"payment"`
	// --- ویژگی‌های جدید نسخه 2.0.0 ---
	Metadata   map[string]interface{} `json:"metadata,omitempty"`    // متادیتای دلخواه برای پیام
	IsMarkdown bool                   `json:"is_markdown,omitempty"` // آیا پیام با فرمت Markdown است
	Font       string                 `json:"font,omitempty"`        // فونت متن پیام
}

Message پیام

type MessageFormat

type MessageFormat string

MessageFormat فرمت‌های مختلف پیام

const (
	FormatPlain    MessageFormat = "plain"
	FormatMarkdown MessageFormat = "markdown"
	FormatHTML     MessageFormat = "html"
)

type MessageIDResponse

type MessageIDResponse struct {
	MessageID string `json:"message_id"`
}

MessageIDResponse پاسخ حاوی آیدی پیام

type MessageSenderEnum

type MessageSenderEnum string
const (
	UserSender MessageSenderEnum = "User"
	BotSender  MessageSenderEnum = "Bot"
)

type MiddlewareFunc

type MiddlewareFunc func(ctx context.Context, update *Update, next HandlerFunc) error

MiddlewareFunc برای middleware

type NetworkStabilityManager

type NetworkStabilityManager struct {
	// contains filtered or unexported fields
}

NetworkStabilityManager مدیریت پایداری شبکه

func NewNetworkStabilityManager

func NewNetworkStabilityManager(client *BotClient) *NetworkStabilityManager

NewNetworkStabilityManager ایجاد یک نمونه جدید

func (*NetworkStabilityManager) CalculateBackoffDelay

func (nsm *NetworkStabilityManager) CalculateBackoffDelay(retryCount int) time.Duration

CalculateBackoffDelay محاسبه تأخیر برای تلاش مجدد با الگوریتم نمایی و Jitter

func (*NetworkStabilityManager) IsRetryableError

func (nsm *NetworkStabilityManager) IsRetryableError(err error) bool

IsRetryableError بررسی اینکه آیا یک خطا قابل تلاش مجدد است یا خیر

type PaymentStatus

type PaymentStatus struct {
	PaymentID string            `json:"payment_id"`
	Status    PaymentStatusEnum `json:"status"`
}

PaymentStatus وضعیت پرداخت

type PaymentStatusEnum

type PaymentStatusEnum string
const (
	PaymentPaid    PaymentStatusEnum = "Paid"
	PaymentNotPaid PaymentStatusEnum = "NotPaid"
)

type PinChatMessageRequest

type PinChatMessageRequest struct {
	ChatID              string `json:"chat_id"`
	MessageID           string `json:"message_id"`
	DisableNotification bool   `json:"disable_notification,omitempty"`
}

PinChatMessageRequest درخواست پین کردن پیام

type Poll

type Poll struct {
	Question   string      `json:"question"`
	Options    []string    `json:"options"`
	PollStatus *PollStatus `json:"poll_status"`
}

Poll نظرسنجی

type PollStatus

type PollStatus struct {
	State              PollStatusEnum `json:"state"`
	SelectionIndex     int            `json:"selection_index"`
	PercentVoteOptions []int          `json:"percent_vote_options"`
	TotalVote          int            `json:"total_vote"`
	ShowTotalVotes     bool           `json:"show_total_votes"`
}

PollStatus وضعیت نظرسنجی

type PollStatusEnum

type PollStatusEnum string
const (
	OpenPoll   PollStatusEnum = "Open"
	ClosedPoll PollStatusEnum = "Closed"
)

type PollingOptions

type PollingOptions struct {
	Handler           HandlerFunc
	RetryTimeout      time.Duration // این فیلد دیگر به صورت مستقیم استفاده نمی‌شود و توسط NetworkStabilityManager مدیریت می‌شود
	Limit             int
	AllowEmptyUpdates bool
	PollInterval      time.Duration
	Timeout           time.Duration
}

PollingOptions تنظیمات فرآیند Polling

type PromoteChatMemberRequest

type PromoteChatMemberRequest struct {
	ChatID              string `json:"chat_id"`
	UserID              string `json:"user_id"`
	IsAdministrator     *bool  `json:"is_administrator,omitempty"`
	CanChangeInfo       *bool  `json:"can_change_info,omitempty"`
	CanPostMessages     *bool  `json:"can_post_messages,omitempty"`
	CanEditMessages     *bool  `json:"can_edit_messages,omitempty"`
	CanDeleteMessages   *bool  `json:"can_delete_messages,omitempty"`
	CanInviteUsers      *bool  `json:"can_invite_users,omitempty"`
	CanPinMessages      *bool  `json:"can_pin_messages,omitempty"`
	CanManageVideoChats *bool  `json:"can_manage_video_chats,omitempty"`
	CanManageChat       *bool  `json:"can_manage_chat,omitempty"`
	CanManageTopics     *bool  `json:"can_manage_topics,omitempty"`
}

PromoteChatMemberRequest درخواست ارتقای عضو چت

type ReceiveInlineMessageRequest

type ReceiveInlineMessageRequest struct {
	InlineMessage *InlineMessage `json:"inline_message"`
}

ReceiveInlineMessageRequest درخواست دریافت پیام اینلاین (برای وب‌هوک)

type ReceiveQueryRequest

type ReceiveQueryRequest struct {
	// نکته: این فیلد در وب‌هوک به صورت string برگردانده می‌شود.
	QueryID  string `json:"query_id"`
	ChatID   string `json:"chat_id"`
	SenderID string `json:"sender_id"`
	Data     string `json:"data"`
}

ReceiveQueryRequest درخواست دریافت کوئری (برای وب‌هوک)

type ReceiveUpdateRequest

type ReceiveUpdateRequest struct {
	Update *Update `json:"update"`
}

ReceiveUpdateRequest درخواست دریافت آپدیت‌ها (برای وب‌هوک)

type ReloadManager

type ReloadManager struct {
	// contains filtered or unexported fields
}

ReloadManager مدیریت قابلیت بارگذاری مجدد (Hot-Reload)

func NewReloadManager

func NewReloadManager(client *BotClient) *ReloadManager

NewReloadManager ایجاد یک نمونه جدید از ReloadManager

func (*ReloadManager) OnReload

func (rm *ReloadManager) OnReload(fn func())

OnReload ثبت یک تابع برای اجرا پس از هر بارگذاری مجدد

func (*ReloadManager) StartWatching

func (rm *ReloadManager) StartWatching()

StartWatching شروع نظارت بر تغییرات فایل‌ها

func (*ReloadManager) StopWatching

func (rm *ReloadManager) StopWatching()

StopWatching توقف نظارت بر تغییرات فایل‌ها

func (*ReloadManager) TriggerReload

func (rm *ReloadManager) TriggerReload()

TriggerReload اجرای فرآیند بارگذاری مجدد

type ReplyKeyboardMarkup

type ReplyKeyboardMarkup struct {
	Keyboard              [][]*KeyboardButton `json:"keyboard"`
	IsPersistent          bool                `json:"is_persistent,omitempty"`
	ResizeKeyboard        bool                `json:"resize_keyboard,omitempty"`
	OneTimeKeyboard       bool                `json:"one_time_keyboard,omitempty"`
	InputFieldPlaceholder string              `json:"input_field_placeholder,omitempty"`
	Selective             bool                `json:"selective,omitempty"`
}

ReplyKeyboardMarkup کیبورد پاسخ

func NewReplyKeyboard

func NewReplyKeyboard(rows ...[]*KeyboardButton) *ReplyKeyboardMarkup

NewReplyKeyboard ایجاد یک کیبورد پاسخ

func (*ReplyKeyboardMarkup) WithOneTimeKeyboard

func (kb *ReplyKeyboardMarkup) WithOneTimeKeyboard(oneTime bool) *ReplyKeyboardMarkup

WithOneTimeKeyboard تنظیم کیبورد یکبار مصرف

func (*ReplyKeyboardMarkup) WithResizeKeyboard

func (kb *ReplyKeyboardMarkup) WithResizeKeyboard(resize bool) *ReplyKeyboardMarkup

WithResizeKeyboard تنظیم تغییر اندازه کیبورد

type ReplyKeyboardRemove

type ReplyKeyboardRemove struct {
	RemoveKeyboard bool `json:"remove_keyboard"`
	Selective      bool `json:"selective,omitempty"`
}

ReplyKeyboardRemove حذف کیبورد پاسخ

func NewRemoveKeyboard

func NewRemoveKeyboard() *ReplyKeyboardRemove

NewRemoveKeyboard ایجاد یک دستور برای حذف کیبورد

type RequestSendFileRequest

type RequestSendFileRequest struct {
	Type FileTypeEnum `json:"type"`
}

RequestSendFileRequest درخواست آدرس آپلود

type RequestSendFileResponse

type RequestSendFileResponse struct {
	UploadURL string `json:"upload_url"`
}

RequestSendFileResponse پاسخ حاوی آدرس آپلود

type ResponseParameters

type ResponseParameters struct {
	MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
	RetryAfter      int   `json:"retry_after,omitempty"`
}

ResponseParameters پارامترهای پاسخ

type SearchSelectionItemsRequest

type SearchSelectionItemsRequest struct {
	SelectionID string `json:"selection_id"`
	Query       string `json:"query"`
}

SearchSelectionItemsRequest درخواست جستجوی آیتم‌های انتخابی

type SearchSelectionItemsResponse

type SearchSelectionItemsResponse struct {
	Items []ButtonSelectionItem `json:"items"`
}

SearchSelectionItemsResponse پاسخ جستجوی آیتم‌های انتخابی

type SendContactRequest

type SendContactRequest struct {
	ChatID               string                `json:"chat_id"`
	FirstName            string                `json:"first_name"`
	LastName             string                `json:"last_name"`
	PhoneNumber          string                `json:"phone_number"`
	DisableNotification  bool                  `json:"disable_notification,omitempty"`
	ReplyToMessageID     string                `json:"reply_to_message_id,omitempty"`
	InlineKeyboardMarkup *InlineKeyboardMarkup `json:"inline_keyboard,omitempty"`
	ReplyKeyboardMarkup  *ReplyKeyboardMarkup  `json:"reply_keyboard,omitempty"`
}

SendContactRequest درخواست ارسال مخاطب

type SendFileRequest

type SendFileRequest struct {
	ChatID               string                `json:"chat_id"`
	FileID               string                `json:"file_id"`
	Text                 string                `json:"text,omitempty"`
	ReplyToMessageID     string                `json:"reply_to_message_id,omitempty"`
	DisableNotification  bool                  `json:"disable_notification,omitempty"`
	InlineKeyboardMarkup *InlineKeyboardMarkup `json:"inline_keyboard,omitempty"`
	ReplyKeyboardMarkup  *ReplyKeyboardMarkup  `json:"reply_keyboard,omitempty"`
}

SendFileRequest درخواست ارسال فایل

type SendLocationRequest

type SendLocationRequest struct {
	ChatID               string                `json:"chat_id"`
	Latitude             string                `json:"latitude"`
	Longitude            string                `json:"longitude"`
	DisableNotification  bool                  `json:"disable_notification,omitempty"`
	ReplyToMessageID     string                `json:"reply_to_message_id,omitempty"`
	InlineKeyboardMarkup *InlineKeyboardMarkup `json:"inline_keyboard,omitempty"`
	ReplyKeyboardMarkup  *ReplyKeyboardMarkup  `json:"reply_keyboard,omitempty"`
}

SendLocationRequest درخواست ارسال موقعیت مکانی

type SendMessageRequest

type SendMessageRequest struct {
	ChatID               string                `json:"chat_id"`
	Text                 string                `json:"text"`
	DisableNotification  bool                  `json:"disable_notification,omitempty"`
	ReplyToMessageID     string                `json:"reply_to_message_id,omitempty"`
	InlineKeyboardMarkup *InlineKeyboardMarkup `json:"inline_keyboard,omitempty"`
	ReplyKeyboardMarkup  *ReplyKeyboardMarkup  `json:"reply_keyboard,omitempty"`
}

SendMessageRequest درخواست ارسال پیام

type SendPollRequest

type SendPollRequest struct {
	ChatID   string   `json:"chat_id"`
	Question string   `json:"question"`
	Options  []string `json:"options"`
}

SendPollRequest درخواست ارسال نظرسنجی

type SetCommandsRequest

type SetCommandsRequest struct {
	BotCommands []BotCommand `json:"bot_commands"`
}

SetCommandsRequest درخواست تنظیم دستورات بات

type StateManager

type StateManager struct {
	// contains filtered or unexported fields
}

StateManager برای مدیریت وضعیت‌های کاربران

func NewStateManager

func NewStateManager() *StateManager

NewStateManager یک نمونه جدید از StateManager ایجاد می‌کند

func (*StateManager) DeleteState

func (sm *StateManager) DeleteState(userID, key string)

DeleteState یک کلید را برای کاربر مشخص حذف می‌کند

func (*StateManager) DeleteUserState

func (sm *StateManager) DeleteUserState(userID string)

DeleteUserState تمام وضعیت‌های یک کاربر را حذف می‌کند

func (*StateManager) GetAllUserStates

func (sm *StateManager) GetAllUserStates(userID string) (map[string]interface{}, bool)

GetAllUserStates تمام وضعیت‌های یک کاربر را برمی‌گرداند

func (*StateManager) GetState

func (sm *StateManager) GetState(userID, key string) (interface{}, bool)

GetState یک مقدار را برای کاربر و کلید مشخص برمی‌گرداند

func (*StateManager) SetState

func (sm *StateManager) SetState(userID, key string, value interface{})

SetState یک مقدار را برای کاربر مشخص ذخیره می‌کند

type Sticker

type Sticker struct {
	StickerID      string `json:"sticker_id"`
	File           *File  `json:"file"`
	EmojiCharacter string `json:"emoji_character"`
}

Sticker استیکر

type UnbanChatMemberRequest

type UnbanChatMemberRequest struct {
	ChatID string `json:"chat_id"`
	UserID string `json:"user_id"`
}

UnbanChatMemberRequest درخواست رفع مسدودیت عضو چت

type UnpinChatMessageRequest

type UnpinChatMessageRequest struct {
	ChatID    string `json:"chat_id"`
	MessageID string `json:"message_id"`
}

UnpinChatMessageRequest درخواست آنپین کردن پیام

type Update

type Update struct {
	Type   UpdateTypeEnum `json:"type"`
	ChatID string         `json:"chat_id"`
	// نکته: در API این فیلد به صورت string برگردانده می‌شود.
	RemovedMessageID *string        `json:"removed_message_id"`
	NewMessage       *Message       `json:"new_message"`
	UpdatedMessage   *Message       `json:"updated_message"`
	UpdatedPayment   *PaymentStatus `json:"updated_payment"`
}

Update آپدیت

type UpdateBotEndpointsRequest

type UpdateBotEndpointsRequest struct {
	URL  string                 `json:"url"`
	Type UpdateEndpointTypeEnum `json:"type"`
}

UpdateBotEndpointsRequest درخواست به‌روزرسانی endpointهای بات

type UpdateEndpointTypeEnum

type UpdateEndpointTypeEnum string
const (
	ReceiveUpdate        UpdateEndpointTypeEnum = "ReceiveUpdate"
	ReceiveInlineMessage UpdateEndpointTypeEnum = "ReceiveInlineMessage"
	ReceiveQuery         UpdateEndpointTypeEnum = "ReceiveQuery"
	GetSelectionItem     UpdateEndpointTypeEnum = "GetSelectionItem"
	SearchSelectionItems UpdateEndpointTypeEnum = "SearchSelectionItems"
)

type UpdateTypeEnum

type UpdateTypeEnum string
const (
	UpdatedMessage UpdateTypeEnum = "UpdatedMessage"
	NewMessage     UpdateTypeEnum = "NewMessage"
	RemovedMessage UpdateTypeEnum = "RemovedMessage"
	StartedBot     UpdateTypeEnum = "StartedBot"
	StoppedBot     UpdateTypeEnum = "StoppedBot"
	UpdatedPayment UpdateTypeEnum = "UpdatedPayment"
	CallbackQuery  UpdateTypeEnum = "CallbackQuery" // نوع جدید برای کوئری‌های دکمه
	InlineQuery    UpdateTypeEnum = "InlineQuery"   // نوع جدید برای کوئری‌های اینلاین
)

type User

type User struct {
	UserID     string `json:"user_id"`
	FirstName  string `json:"first_name"`
	LastName   string `json:"last_name"`
	Username   string `json:"username"`
	Bio        string `json:"bio"`
	IsVerified bool   `json:"is_verified"`
	IsPrivate  bool   `json:"is_private"`
	Avatar     *File  `json:"avatar"`
	LastSeen   string `json:"last_seen"`
}

User اطلاعات کاربر

type WebAppInfo

type WebAppInfo struct {
	URL string `json:"url"`
}

WebAppInfo اطلاعات برای دکمه وب اپ

type WebhookOptions

type WebhookOptions struct {
	Port    int
	Path    string
	Handler HandlerFunc
	Secret  string // برای احراز هویت (امنیت)
}

WebhookOptions تنظیمات وب‌هوک

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL