| | package service |
| |
|
| | import ( |
| | "bytes" |
| | "crypto/hmac" |
| | "crypto/sha256" |
| | "encoding/hex" |
| | "encoding/json" |
| | "fmt" |
| | "net/http" |
| | "one-api/dto" |
| | "one-api/setting" |
| | "time" |
| | ) |
| |
|
| | |
| | type WebhookPayload struct { |
| | Type string `json:"type"` |
| | Title string `json:"title"` |
| | Content string `json:"content"` |
| | Values []interface{} `json:"values,omitempty"` |
| | Timestamp int64 `json:"timestamp"` |
| | } |
| |
|
| | |
| | func generateSignature(secret string, payload []byte) string { |
| | h := hmac.New(sha256.New, []byte(secret)) |
| | h.Write(payload) |
| | return hex.EncodeToString(h.Sum(nil)) |
| | } |
| |
|
| | |
| | func SendWebhookNotify(webhookURL string, secret string, data dto.Notify) error { |
| | |
| | content := data.Content |
| | for _, value := range data.Values { |
| | content = fmt.Sprintf(content, value) |
| | } |
| |
|
| | |
| | payload := WebhookPayload{ |
| | Type: data.Type, |
| | Title: data.Title, |
| | Content: content, |
| | Values: data.Values, |
| | Timestamp: time.Now().Unix(), |
| | } |
| |
|
| | |
| | payloadBytes, err := json.Marshal(payload) |
| | if err != nil { |
| | return fmt.Errorf("failed to marshal webhook payload: %v", err) |
| | } |
| |
|
| | |
| | var req *http.Request |
| | var resp *http.Response |
| |
|
| | if setting.EnableWorker() { |
| | |
| | workerReq := &WorkerRequest{ |
| | URL: webhookURL, |
| | Key: setting.WorkerValidKey, |
| | Method: http.MethodPost, |
| | Headers: map[string]string{ |
| | "Content-Type": "application/json", |
| | }, |
| | Body: payloadBytes, |
| | } |
| |
|
| | |
| | if secret != "" { |
| | signature := generateSignature(secret, payloadBytes) |
| | workerReq.Headers["X-Webhook-Signature"] = signature |
| | workerReq.Headers["Authorization"] = "Bearer " + secret |
| | } |
| |
|
| | resp, err = DoWorkerRequest(workerReq) |
| | if err != nil { |
| | return fmt.Errorf("failed to send webhook request through worker: %v", err) |
| | } |
| | defer resp.Body.Close() |
| |
|
| | |
| | if resp.StatusCode < 200 || resp.StatusCode >= 300 { |
| | return fmt.Errorf("webhook request failed with status code: %d", resp.StatusCode) |
| | } |
| | } else { |
| | req, err = http.NewRequest(http.MethodPost, webhookURL, bytes.NewBuffer(payloadBytes)) |
| | if err != nil { |
| | return fmt.Errorf("failed to create webhook request: %v", err) |
| | } |
| |
|
| | |
| | req.Header.Set("Content-Type", "application/json") |
| |
|
| | |
| | if secret != "" { |
| | signature := generateSignature(secret, payloadBytes) |
| | req.Header.Set("X-Webhook-Signature", signature) |
| | } |
| |
|
| | |
| | client := GetImpatientHttpClient() |
| | resp, err = client.Do(req) |
| | if err != nil { |
| | return fmt.Errorf("failed to send webhook request: %v", err) |
| | } |
| | defer resp.Body.Close() |
| |
|
| | |
| | if resp.StatusCode < 200 || resp.StatusCode >= 300 { |
| | return fmt.Errorf("webhook request failed with status code: %d", resp.StatusCode) |
| | } |
| | } |
| |
|
| | return nil |
| | } |
| |
|