package tgcore import ( "bytes" "encoding/json" "io" "net/http" "strings" ) var API string func Init(token string) { API = "https://api.telegram.org/bot" + token } func TG(method string, body interface{}) (map[string]interface{}, error) { jsonBody, err := json.Marshal(body) if err != nil { return nil, err } resp, err := http.Post(API+"/"+method, "application/json", bytes.NewReader(jsonBody)) if err != nil { return nil, err } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } var result map[string]interface{} if err := json.Unmarshal(data, &result); err != nil { return nil, err } return result, nil } func Allowed(chatID int64, allowedIDs []int64) bool { if len(allowedIDs) == 0 { return true } for _, id := range allowedIDs { if id == chatID { return true } } return false } func SendMessage(chatID int64, text string, opts map[string]interface{}) error { safeText := text body := map[string]interface{}{ "chat_id": chatID, "text": safeText, "parse_mode": "HTML", "disable_web_page_preview": true, } if opts != nil { for k, v := range opts { body[k] = v } } _, err := TG("sendMessage", body) if err != nil && (strings.Contains(err.Error(), "parse") || strings.Contains(err.Error(), "HTML")) { delete(body, "parse_mode") _, err = TG("sendMessage", body) } return err } // TgHandler is the callback handler interface type TgHandler interface { List(chatID int64, page string) Links(chatID int64, page string) Feeds(chatID int64, page string) // Session callbacks SessionCallback(chatID int64, action string) MenuCallback(chatID int64, action string) } func HandleCallback(chatID int64, queryID string, data string, h TgHandler) { if data == "" { return } // Session callbacks if strings.HasPrefix(data, "session_") { action := strings.TrimPrefix(data, "session_") if h != nil { h.SessionCallback(chatID, action) } TG("answerCallbackQuery", map[string]interface{}{"callback_query_id": queryID}) return } // Menu callbacks if strings.HasPrefix(data, "menu_") { action := strings.TrimPrefix(data, "menu_") if h != nil { h.MenuCallback(chatID, action) } TG("answerCallbackQuery", map[string]interface{}{"callback_query_id": queryID}) return } // Pagination callbacks: list_N, links_N, feeds_N parts := strings.SplitN(data, "_", 2) if len(parts) == 2 { cmd := parts[0] page := parts[1] if h != nil { switch cmd { case "list": h.List(chatID, page) case "links": h.Links(chatID, page) case "feeds": h.Feeds(chatID, page) } } } TG("answerCallbackQuery", map[string]interface{}{"callback_query_id": queryID}) } func GetInt64(m map[string]interface{}, key string) int64 { if v, ok := m[key]; ok { switch n := v.(type) { case float64: return int64(n) case int64: return n } } return 0 } func GetString(m map[string]interface{}, key string) string { if v, ok := m[key]; ok { if s, ok := v.(string); ok { return s } } return "" }