mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:01:09 +02:00
mana-search-go → mana-search mana-notify-go → mana-notify mana-crawler-go → mana-crawler mana-api-gateway-go → mana-api-gateway Legacy NestJS versions are deleted, suffix no longer needed. Updated all references in docker-compose, CLAUDE.md, package.json, Forgejo workflows, and service package.json files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
91 lines
2.1 KiB
Go
91 lines
2.1 KiB
Go
package channel
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type WebhookService struct {
|
|
client *http.Client
|
|
}
|
|
|
|
func NewWebhookService() *WebhookService {
|
|
return &WebhookService{
|
|
client: &http.Client{Timeout: 10 * time.Second},
|
|
}
|
|
}
|
|
|
|
type WebhookMessage struct {
|
|
URL string
|
|
Method string // POST or PUT
|
|
Headers map[string]string
|
|
Body map[string]any
|
|
Timeout int // ms
|
|
}
|
|
|
|
type WebhookResult struct {
|
|
Success bool
|
|
StatusCode int
|
|
Error string
|
|
DurationMs int
|
|
}
|
|
|
|
func (s *WebhookService) Send(ctx context.Context, msg *WebhookMessage) WebhookResult {
|
|
start := time.Now()
|
|
|
|
method := msg.Method
|
|
if method == "" {
|
|
method = http.MethodPost
|
|
}
|
|
|
|
timeout := 10 * time.Second
|
|
if msg.Timeout > 0 {
|
|
timeout = time.Duration(msg.Timeout) * time.Millisecond
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
|
defer cancel()
|
|
|
|
body, err := json.Marshal(msg.Body)
|
|
if err != nil {
|
|
return WebhookResult{Success: false, Error: "marshal error", DurationMs: int(time.Since(start).Milliseconds())}
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, method, msg.URL, bytes.NewReader(body))
|
|
if err != nil {
|
|
return WebhookResult{Success: false, Error: err.Error(), DurationMs: int(time.Since(start).Milliseconds())}
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("User-Agent", "ManaNotify/1.0")
|
|
for k, v := range msg.Headers {
|
|
req.Header.Set(k, v)
|
|
}
|
|
|
|
resp, err := s.client.Do(req)
|
|
durationMs := int(time.Since(start).Milliseconds())
|
|
if err != nil {
|
|
slog.Error("webhook send failed", "url", msg.URL, "error", err)
|
|
return WebhookResult{Success: false, Error: err.Error(), DurationMs: durationMs}
|
|
}
|
|
defer resp.Body.Close()
|
|
io.Copy(io.Discard, resp.Body)
|
|
|
|
success := resp.StatusCode >= 200 && resp.StatusCode < 300
|
|
if !success {
|
|
return WebhookResult{
|
|
Success: false,
|
|
StatusCode: resp.StatusCode,
|
|
Error: fmt.Sprintf("webhook returned %d", resp.StatusCode),
|
|
DurationMs: durationMs,
|
|
}
|
|
}
|
|
|
|
return WebhookResult{Success: true, StatusCode: resp.StatusCode, DurationMs: durationMs}
|
|
}
|