package push import ( "context" "fmt" "io" "net/http" "net/url" "strings" "time" ) const defaultBarkServer = "https://api.day.app" // BarkConfig 是 iOS Bark 推送的配置。 type BarkConfig struct { DeviceKey string Server string // 可选,默认 https://api.day.app } // BarkProvider 实现了通过 Bark 发送 iOS 推送。 type BarkProvider struct { deviceKey string server string client *http.Client } // NewBarkProvider 创建 Bark 推送 Provider。 // DeviceKey 为空时返回 ErrProviderConfigInvalid。 func NewBarkProvider(cfg BarkConfig) (*BarkProvider, error) { if strings.TrimSpace(cfg.DeviceKey) == "" { return nil, ErrProviderConfigInvalid } server := strings.TrimSpace(cfg.Server) if server == "" { server = defaultBarkServer } server = strings.TrimRight(server, "/") return &BarkProvider{ deviceKey: strings.TrimSpace(cfg.DeviceKey), server: server, client: &http.Client{Timeout: 10 * time.Second}, }, nil } func (p *BarkProvider) Name() string { return "bark" } func (p *BarkProvider) Send(ctx context.Context, msg Message) error { title := url.PathEscape(msg.Title) body := url.PathEscape(msg.Content) reqURL := fmt.Sprintf("%s/%s/%s/%s", p.server, p.deviceKey, title, body) req, err := http.NewRequestWithContext(ctx, http.MethodPost, reqURL, nil) if err != nil { return fmt.Errorf("bark: create request: %w", err) } resp, err := p.client.Do(req) if err != nil { return fmt.Errorf("bark: send failed: %w", err) } defer resp.Body.Close() if resp.StatusCode >= 400 { bodyBytes, _ := io.ReadAll(resp.Body) return fmt.Errorf("bark: http %d: %s", resp.StatusCode, string(bodyBytes)) } return nil }