v2.0.3: Webhook user identification by URL token
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 42s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 42s
- Added webhook_token to telegram_integrations
- Webhooks now identify users by token in URL (/webhook/telegram/{token}, /webhook/todoist/{token})
- Webhook automatically configured for all users on backend startup
- Migration 011: Add webhook_token column
This commit is contained in:
@@ -281,6 +281,16 @@ func generateRefreshToken() (string, error) {
|
||||
return base64.URLEncoding.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
// generateWebhookToken generates a unique token for webhook URL identification
|
||||
func generateWebhookToken() (string, error) {
|
||||
b := make([]byte, 24) // 24 bytes = 32 chars in base64
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
func (a *App) generateAccessToken(userID int) (string, error) {
|
||||
claims := JWTClaims{
|
||||
UserID: userID,
|
||||
@@ -2500,6 +2510,10 @@ func (a *App) initAuthDB() error {
|
||||
// Create new unique constraint per user for progress
|
||||
a.DB.Exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_progress_word_user_unique ON progress(word_id, user_id)")
|
||||
|
||||
// Add webhook_token to telegram_integrations for URL-based user identification
|
||||
a.DB.Exec("ALTER TABLE telegram_integrations ADD COLUMN IF NOT EXISTS webhook_token VARCHAR(255)")
|
||||
a.DB.Exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_telegram_integrations_webhook_token ON telegram_integrations(webhook_token) WHERE webhook_token IS NOT NULL")
|
||||
|
||||
// Clean up expired refresh tokens
|
||||
a.DB.Exec("DELETE FROM refresh_tokens WHERE expires_at < NOW()")
|
||||
|
||||
@@ -3085,20 +3099,46 @@ func main() {
|
||||
jwtSecret: []byte(jwtSecret),
|
||||
}
|
||||
|
||||
// Пытаемся настроить webhook автоматически при старте, если есть base URL и bot token в БД
|
||||
// Пытаемся настроить webhook автоматически при старте для всех пользователей с bot_token
|
||||
webhookBaseURL := getEnv("WEBHOOK_BASE_URL", "")
|
||||
if webhookBaseURL != "" {
|
||||
integration, err := app.getTelegramIntegration()
|
||||
if err == nil && integration.BotToken != nil && *integration.BotToken != "" {
|
||||
webhookURL := strings.TrimRight(webhookBaseURL, "/") + "/webhook/telegram"
|
||||
log.Printf("Attempting to setup Telegram webhook at startup. WEBHOOK_BASE_URL='%s'", webhookBaseURL)
|
||||
if err := setupTelegramWebhook(*integration.BotToken, webhookURL); err != nil {
|
||||
log.Printf("Warning: Failed to setup Telegram webhook at startup: %v. Webhook will be configured when user saves bot token.", err)
|
||||
} else {
|
||||
log.Printf("SUCCESS: Telegram webhook configured successfully at startup: %s", webhookURL)
|
||||
}
|
||||
log.Printf("Setting up Telegram webhooks for all users at startup...")
|
||||
rows, err := app.DB.Query(`
|
||||
SELECT user_id, bot_token, webhook_token
|
||||
FROM telegram_integrations
|
||||
WHERE bot_token IS NOT NULL
|
||||
AND bot_token != ''
|
||||
AND webhook_token IS NOT NULL
|
||||
AND webhook_token != ''
|
||||
AND user_id IS NOT NULL
|
||||
`)
|
||||
if err != nil {
|
||||
log.Printf("Warning: Failed to query telegram integrations at startup: %v", err)
|
||||
} else {
|
||||
log.Printf("Telegram bot token not found in database. Webhook will be configured when user saves bot token.")
|
||||
defer rows.Close()
|
||||
configuredCount := 0
|
||||
for rows.Next() {
|
||||
var userID int
|
||||
var botToken, webhookToken string
|
||||
if err := rows.Scan(&userID, &botToken, &webhookToken); err != nil {
|
||||
log.Printf("Warning: Failed to scan telegram integration: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
webhookURL := strings.TrimRight(webhookBaseURL, "/") + "/webhook/telegram/" + webhookToken
|
||||
log.Printf("Setting up Telegram webhook for user_id=%d: URL=%s", userID, webhookURL)
|
||||
if err := setupTelegramWebhook(botToken, webhookURL); err != nil {
|
||||
log.Printf("Warning: Failed to setup Telegram webhook for user_id=%d: %v", userID, err)
|
||||
} else {
|
||||
log.Printf("SUCCESS: Telegram webhook configured for user_id=%d: %s", userID, webhookURL)
|
||||
configuredCount++
|
||||
}
|
||||
}
|
||||
if configuredCount > 0 {
|
||||
log.Printf("Telegram webhooks configured for %d user(s) at startup", configuredCount)
|
||||
} else {
|
||||
log.Printf("No Telegram integrations found with bot_token and webhook_token. Webhooks will be configured when users save bot tokens.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("WEBHOOK_BASE_URL not set. Webhook will be configured when user saves bot token.")
|
||||
@@ -3137,8 +3177,8 @@ func main() {
|
||||
|
||||
// Webhooks - no auth (external services)
|
||||
r.HandleFunc("/webhook/message/post", app.messagePostHandler).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/webhook/todoist", app.todoistWebhookHandler).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/webhook/telegram", app.telegramWebhookHandler).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/webhook/todoist/{token}", app.todoistWebhookHandler).Methods("POST", "OPTIONS")
|
||||
r.HandleFunc("/webhook/telegram/{token}", app.telegramWebhookHandler).Methods("POST", "OPTIONS")
|
||||
|
||||
// Admin pages (basic access, consider adding auth later)
|
||||
r.HandleFunc("/admin", app.adminHandler).Methods("GET")
|
||||
@@ -3285,35 +3325,42 @@ func roundToFourDecimals(val float64) float64 {
|
||||
|
||||
// TelegramIntegration представляет запись из таблицы telegram_integrations
|
||||
type TelegramIntegration struct {
|
||||
ID int `json:"id"`
|
||||
ChatID *string `json:"chat_id"`
|
||||
BotToken *string `json:"bot_token"`
|
||||
ID int `json:"id"`
|
||||
ChatID *string `json:"chat_id"`
|
||||
BotToken *string `json:"bot_token"`
|
||||
WebhookToken *string `json:"webhook_token"`
|
||||
}
|
||||
|
||||
// getTelegramIntegration получает telegram интеграцию из БД
|
||||
// getTelegramIntegrationForUser gets telegram integration for specific user
|
||||
func (a *App) getTelegramIntegrationForUser(userID int) (*TelegramIntegration, error) {
|
||||
var integration TelegramIntegration
|
||||
var chatID, botToken sql.NullString
|
||||
var chatID, botToken, webhookToken sql.NullString
|
||||
|
||||
err := a.DB.QueryRow(`
|
||||
SELECT id, chat_id, bot_token
|
||||
SELECT id, chat_id, bot_token, webhook_token
|
||||
FROM telegram_integrations
|
||||
WHERE user_id = $1
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
`, userID).Scan(&integration.ID, &chatID, &botToken)
|
||||
`, userID).Scan(&integration.ID, &chatID, &botToken, &webhookToken)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
// Если записи нет, создаем новую для этого пользователя
|
||||
// Если записи нет, создаем новую для этого пользователя с webhook токеном
|
||||
webhookToken, err := generateWebhookToken()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate webhook token: %w", err)
|
||||
}
|
||||
|
||||
err = a.DB.QueryRow(`
|
||||
INSERT INTO telegram_integrations (chat_id, bot_token, user_id)
|
||||
VALUES (NULL, NULL, $1)
|
||||
INSERT INTO telegram_integrations (chat_id, bot_token, user_id, webhook_token)
|
||||
VALUES (NULL, NULL, $1, $2)
|
||||
RETURNING id
|
||||
`, userID).Scan(&integration.ID)
|
||||
`, userID, webhookToken).Scan(&integration.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create telegram integration: %w", err)
|
||||
}
|
||||
integration.WebhookToken = &webhookToken
|
||||
return &integration, nil
|
||||
} else if err != nil {
|
||||
return nil, fmt.Errorf("failed to get telegram integration: %w", err)
|
||||
@@ -3325,6 +3372,24 @@ func (a *App) getTelegramIntegrationForUser(userID int) (*TelegramIntegration, e
|
||||
if botToken.Valid {
|
||||
integration.BotToken = &botToken.String
|
||||
}
|
||||
if webhookToken.Valid {
|
||||
integration.WebhookToken = &webhookToken.String
|
||||
} else {
|
||||
// Если токена нет, генерируем его
|
||||
newToken, err := generateWebhookToken()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate webhook token: %w", err)
|
||||
}
|
||||
_, err = a.DB.Exec(`
|
||||
UPDATE telegram_integrations
|
||||
SET webhook_token = $1
|
||||
WHERE id = $2
|
||||
`, newToken, integration.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to update webhook token: %w", err)
|
||||
}
|
||||
integration.WebhookToken = &newToken
|
||||
}
|
||||
|
||||
return &integration, nil
|
||||
}
|
||||
@@ -3404,11 +3469,15 @@ func (a *App) saveTelegramBotTokenForUser(botToken string, userID int) error {
|
||||
// Проверяем, есть ли уже запись для этого пользователя
|
||||
integration, err := a.getTelegramIntegrationForUser(userID)
|
||||
if err != nil {
|
||||
// Если записи нет, создаем новую
|
||||
// Если записи нет, создаем новую с webhook токеном
|
||||
webhookToken, err := generateWebhookToken()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate webhook token: %w", err)
|
||||
}
|
||||
_, err = a.DB.Exec(`
|
||||
INSERT INTO telegram_integrations (bot_token, chat_id, user_id)
|
||||
VALUES ($1, NULL, $2)
|
||||
`, botToken, userID)
|
||||
INSERT INTO telegram_integrations (bot_token, chat_id, user_id, webhook_token)
|
||||
VALUES ($1, NULL, $2, $3)
|
||||
`, botToken, userID, webhookToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create telegram bot token: %w", err)
|
||||
}
|
||||
@@ -3422,6 +3491,21 @@ func (a *App) saveTelegramBotTokenForUser(botToken string, userID int) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update telegram bot token: %w", err)
|
||||
}
|
||||
// Убеждаемся, что webhook_token есть
|
||||
if integration.WebhookToken == nil || *integration.WebhookToken == "" {
|
||||
webhookToken, err := generateWebhookToken()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate webhook token: %w", err)
|
||||
}
|
||||
_, err = a.DB.Exec(`
|
||||
UPDATE telegram_integrations
|
||||
SET webhook_token = $1
|
||||
WHERE id = $2
|
||||
`, webhookToken, integration.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update webhook token: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -3541,7 +3625,8 @@ func utf16LengthToUTF8(text string, utf16Offset, utf16Length int) int {
|
||||
// processTelegramMessage обрабатывает сообщение из Telegram с использованием entities
|
||||
// Логика отличается от processMessage: использует entities для определения жирного текста
|
||||
// и не отправляет сообщение обратно в Telegram
|
||||
func (a *App) processTelegramMessage(fullText string, entities []TelegramEntity) (*ProcessedEntry, error) {
|
||||
// userID может быть nil, если пользователь не определен
|
||||
func (a *App) processTelegramMessage(fullText string, entities []TelegramEntity, userID *int) (*ProcessedEntry, error) {
|
||||
fullText = strings.TrimSpace(fullText)
|
||||
|
||||
// Регулярное выражение: project+/-score (без **)
|
||||
@@ -3646,7 +3731,7 @@ func (a *App) processTelegramMessage(fullText string, entities []TelegramEntity)
|
||||
|
||||
// Вставляем данные в БД только если есть nodes
|
||||
if len(scoreNodes) > 0 {
|
||||
err := a.insertMessageData(processedText, createdDate, scoreNodes, nil) // nil userID for webhook
|
||||
err := a.insertMessageData(processedText, createdDate, scoreNodes, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error inserting message data: %v", err)
|
||||
return nil, fmt.Errorf("error inserting data: %w", err)
|
||||
@@ -4802,12 +4887,6 @@ func (a *App) todoistWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("Method: %s", r.Method)
|
||||
log.Printf("URL: %s", r.URL.String())
|
||||
log.Printf("RemoteAddr: %s", r.RemoteAddr)
|
||||
log.Printf("Headers:")
|
||||
for key, values := range r.Header {
|
||||
for _, value := range values {
|
||||
log.Printf(" %s: %s", key, value)
|
||||
}
|
||||
}
|
||||
|
||||
if r.Method == "OPTIONS" {
|
||||
log.Printf("OPTIONS request, returning OK")
|
||||
@@ -4817,6 +4896,35 @@ func (a *App) todoistWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
setCORSHeaders(w)
|
||||
|
||||
// Извлекаем токен из URL
|
||||
vars := mux.Vars(r)
|
||||
token := vars["token"]
|
||||
if token == "" {
|
||||
log.Printf("Todoist webhook: missing token in URL")
|
||||
sendErrorWithCORS(w, "Missing webhook token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Находим пользователя по токену из telegram_integrations (используем тот же механизм)
|
||||
var userID int
|
||||
err := a.DB.QueryRow(`
|
||||
SELECT user_id FROM telegram_integrations
|
||||
WHERE webhook_token = $1 AND user_id IS NOT NULL
|
||||
LIMIT 1
|
||||
`, token).Scan(&userID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
log.Printf("Todoist webhook: invalid token: %s", token)
|
||||
sendErrorWithCORS(w, "Invalid webhook token", http.StatusUnauthorized)
|
||||
return
|
||||
} else if err != nil {
|
||||
log.Printf("Error finding user by webhook token: %v", err)
|
||||
sendErrorWithCORS(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Todoist webhook: token=%s, user_id=%d", token, userID)
|
||||
|
||||
// Читаем тело запроса для логирования
|
||||
bodyBytes, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
@@ -4925,8 +5033,9 @@ func (a *App) todoistWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
title, len(title), description, len(description), combinedText, len(combinedText))
|
||||
|
||||
// Обрабатываем сообщение через существующую логику (без отправки в Telegram)
|
||||
log.Printf("Calling processMessageWithoutTelegram with combined text...")
|
||||
response, err := a.processMessageWithoutTelegram(combinedText, nil) // nil userID for webhook
|
||||
userIDPtr := &userID
|
||||
log.Printf("Calling processMessageWithoutTelegram with combined text, user_id=%d...", userID)
|
||||
response, err := a.processMessageWithoutTelegram(combinedText, userIDPtr)
|
||||
if err != nil {
|
||||
log.Printf("ERROR processing Todoist message: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
@@ -4977,6 +5086,35 @@ func (a *App) telegramWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
setCORSHeaders(w)
|
||||
|
||||
// Извлекаем токен из URL
|
||||
vars := mux.Vars(r)
|
||||
token := vars["token"]
|
||||
if token == "" {
|
||||
log.Printf("Telegram webhook: missing token in URL")
|
||||
sendErrorWithCORS(w, "Missing webhook token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Находим пользователя по токену
|
||||
var userID int
|
||||
err := a.DB.QueryRow(`
|
||||
SELECT user_id FROM telegram_integrations
|
||||
WHERE webhook_token = $1 AND user_id IS NOT NULL
|
||||
LIMIT 1
|
||||
`, token).Scan(&userID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
log.Printf("Telegram webhook: invalid token: %s", token)
|
||||
sendErrorWithCORS(w, "Invalid webhook token", http.StatusUnauthorized)
|
||||
return
|
||||
} else if err != nil {
|
||||
log.Printf("Error finding user by webhook token: %v", err)
|
||||
sendErrorWithCORS(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Telegram webhook: token=%s, user_id=%d", token, userID)
|
||||
|
||||
// Парсим webhook от Telegram
|
||||
var update TelegramUpdate
|
||||
if err := json.NewDecoder(r.Body).Decode(&update); err != nil {
|
||||
@@ -5002,31 +5140,34 @@ func (a *App) telegramWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Telegram webhook: message present, chat_id=%d", message.Chat.ID)
|
||||
log.Printf("Telegram webhook: message present, chat_id=%d, user_id=%d", message.Chat.ID, userID)
|
||||
|
||||
// Сохраняем chat_id при первом сообщении (даже если нет текста)
|
||||
// Сохраняем chat_id при первом сообщении (если еще не сохранен)
|
||||
if message.Chat.ID != 0 {
|
||||
chatIDStr := strconv.FormatInt(message.Chat.ID, 10)
|
||||
log.Printf("Processing chat_id: %s", chatIDStr)
|
||||
integration, err := a.getTelegramIntegration()
|
||||
if err != nil {
|
||||
log.Printf("Error getting telegram integration: %v", err)
|
||||
} else {
|
||||
var existingChatID sql.NullString
|
||||
err := a.DB.QueryRow(`
|
||||
SELECT chat_id FROM telegram_integrations
|
||||
WHERE user_id = $1
|
||||
LIMIT 1
|
||||
`, userID).Scan(&existingChatID)
|
||||
|
||||
if err == nil && (!existingChatID.Valid || existingChatID.String == "") {
|
||||
// Сохраняем chat_id, если его еще нет
|
||||
if integration.ChatID == nil || *integration.ChatID == "" {
|
||||
log.Printf("Attempting to save chat_id: %s", chatIDStr)
|
||||
if err := a.saveTelegramChatID(chatIDStr); err != nil {
|
||||
log.Printf("Warning: Failed to save chat_id: %v", err)
|
||||
} else {
|
||||
log.Printf("Successfully saved chat_id from first message: %s", chatIDStr)
|
||||
}
|
||||
_, err = a.DB.Exec(`
|
||||
UPDATE telegram_integrations
|
||||
SET chat_id = $1
|
||||
WHERE user_id = $2
|
||||
`, chatIDStr, userID)
|
||||
if err != nil {
|
||||
log.Printf("Warning: Failed to save chat_id: %v", err)
|
||||
} else {
|
||||
log.Printf("Chat_id already exists in database: %s", *integration.ChatID)
|
||||
log.Printf("Successfully saved chat_id from first message: %s", chatIDStr)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("Warning: message.Chat.ID is 0, cannot save chat_id")
|
||||
}
|
||||
|
||||
userIDPtr := &userID
|
||||
|
||||
// Проверяем, что есть текст в сообщении
|
||||
if message.Text == "" {
|
||||
@@ -5044,10 +5185,10 @@ func (a *App) telegramWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
entities = []TelegramEntity{}
|
||||
}
|
||||
|
||||
log.Printf("Processing Telegram message: text='%s', entities count=%d", fullText, len(entities))
|
||||
log.Printf("Processing Telegram message: text='%s', entities count=%d, user_id=%d", fullText, len(entities), userID)
|
||||
|
||||
// Обрабатываем сообщение через новую логику (с entities, без отправки обратно в Telegram)
|
||||
response, err := a.processTelegramMessage(fullText, entities)
|
||||
response, err := a.processTelegramMessage(fullText, entities, userIDPtr)
|
||||
if err != nil {
|
||||
log.Printf("Error processing Telegram message: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
@@ -5207,11 +5348,18 @@ func (a *App) updateTelegramIntegrationHandler(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем обновленную интеграцию с webhook токеном
|
||||
integration, err := a.getTelegramIntegrationForUser(userID)
|
||||
if err != nil {
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Failed to get updated integration: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Настраиваем webhook автоматически при сохранении токена
|
||||
webhookBaseURL := getEnv("WEBHOOK_BASE_URL", "")
|
||||
log.Printf("Attempting to setup Telegram webhook. WEBHOOK_BASE_URL='%s'", webhookBaseURL)
|
||||
if webhookBaseURL != "" {
|
||||
webhookURL := strings.TrimRight(webhookBaseURL, "/") + "/webhook/telegram"
|
||||
if webhookBaseURL != "" && integration.WebhookToken != nil && *integration.WebhookToken != "" {
|
||||
webhookURL := strings.TrimRight(webhookBaseURL, "/") + "/webhook/telegram/" + *integration.WebhookToken
|
||||
log.Printf("Setting up Telegram webhook: URL=%s", webhookURL)
|
||||
if err := setupTelegramWebhook(req.BotToken, webhookURL); err != nil {
|
||||
log.Printf("ERROR: Failed to setup Telegram webhook: %v", err)
|
||||
@@ -5220,13 +5368,7 @@ func (a *App) updateTelegramIntegrationHandler(w http.ResponseWriter, r *http.Re
|
||||
log.Printf("SUCCESS: Telegram webhook configured successfully: %s", webhookURL)
|
||||
}
|
||||
} else {
|
||||
log.Printf("WARNING: WEBHOOK_BASE_URL not set. Webhook will not be configured automatically.")
|
||||
}
|
||||
|
||||
integration, err := a.getTelegramIntegrationForUser(userID)
|
||||
if err != nil {
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Failed to get updated integration: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
log.Printf("WARNING: WEBHOOK_BASE_URL not set or webhook_token missing. Webhook will not be configured automatically.")
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -5242,6 +5384,24 @@ func (a *App) getTodoistWebhookURLHandler(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
setCORSHeaders(w)
|
||||
|
||||
userID, ok := getUserIDFromContext(r)
|
||||
if !ok {
|
||||
sendErrorWithCORS(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем webhook токен для пользователя
|
||||
integration, err := a.getTelegramIntegrationForUser(userID)
|
||||
if err != nil {
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Failed to get telegram integration: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if integration.WebhookToken == nil || *integration.WebhookToken == "" {
|
||||
sendErrorWithCORS(w, "Webhook token not available", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем base URL из env
|
||||
baseURL := getEnv("WEBHOOK_BASE_URL", "")
|
||||
if baseURL == "" {
|
||||
@@ -5249,7 +5409,7 @@ func (a *App) getTodoistWebhookURLHandler(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
webhookURL := strings.TrimRight(baseURL, "/") + "/webhook/todoist"
|
||||
webhookURL := strings.TrimRight(baseURL, "/") + "/webhook/todoist/" + *integration.WebhookToken
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
|
||||
Reference in New Issue
Block a user