Kurulumgo get github.com/Pariette-Inc/signalbird.sdk/v2

signalbird - Go

Üç yüzey taşır: Telsiz (log), Gönderim (e-posta/SMS/push) ve Yönetim (proje, sohbet gelen kutusu, uygulama).

Kurulum

bash
go get github.com/Pariette-Inc/signalbird.sdk/v2
go
import "github.com/Pariette-Inc/signalbird.sdk/v2/src/go/signalbird"

Go 1.21+ gerekir. Bağımlılığı yoktur - yalnız standart kütüphane.

Anahtarlar

Yüzey Tip Anahtar
Telsiz signalbird.Client sb_secret_live_…
Gönderim signalbird.Messaging sb_…
Yönetim signalbird.Management sb_… + kapsam

Telsiz - log ve olay

go
radio, err := signalbird.NewClientFromEnv()   // SIGNALBIRD_DOMAIN_KEY / _URL / _SOURCE
if err != nil {
    log.Fatal(err)
}

radio.Critical(ctx, "critical", "ödeme servisi yanıt vermiyor", map[string]any{
    "service": "iyzico",
    "attempt": 3,
})

radio.Info(ctx, "info", "ahmet@x.com yeni hesap oluşturdu", nil)

Kendi yapılandırmanız:

go
radio, err := signalbird.NewClient(signalbird.Config{
    DomainKey:       os.Getenv("SIGNALBIRD_DOMAIN_KEY"),
    Source:       "api-01",
    Timeout:      5 * time.Second,   // varsayılan
    ThrowOnError: false,             // varsayılan: sessiz hata
})

Beş seviye: LevelDebug, LevelInfo, LevelWarn, LevelError, LevelCritical. Seviye vermezseniz kanalın kendi varsayılanı geçerlidir.

Toplu gönderim

go
result, err := radio.Batch(ctx, []signalbird.Event{
    {Channel: "deploy", Message: "v2.4.0 yayında", Level: signalbird.LevelInfo},
    {Channel: "critical", Message: "kuyruk doldu"},
})

En fazla 100 kayıt; kısmi başarı normaldir ve başarısız satırlar yeniden denenmez.

HTTP middleware deseni

go
func SignalbirdRecovery(radio *signalbird.Client) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                if recovered := recover(); recovered != nil {
                    // Log göndermek isteği bekletmesin: bağlam kopyalanır
                    radio.Critical(context.WithoutCancel(r.Context()), "critical",
                        fmt.Sprint(recovered), map[string]any{
                            "path":   r.URL.Path,
                            "method": r.Method,
                        })

                    http.Error(w, "internal error", http.StatusInternalServerError)
                }
            }()

            next.ServeHTTP(w, r)
        })
    }
}

Gönderim - e-posta, SMS, push

go
send, err := signalbird.NewMessaging(signalbird.KeyConfig{
    DomainKey: os.Getenv("SIGNALBIRD_DOMAIN_KEY"),
})

result, err := send.SendEmail(ctx, map[string]any{
    "to":      "ahmet@example.com",
    "class":   "transactional",     // ZORUNLU, varsayılanı yok
    "subject": "Siparişiniz yola çıktı",
    "body":    "<p>Kargo takip no: 1234</p>",
})

if err != nil || !result.OK {
    log.Printf("signalbird: %s - %s", result.Code, result.Message)
}
go
send.SendSms(ctx, map[string]any{"to": "+905551112233", "class": "transactional", "body": "Kodunuz: 123456"})
send.PreviewSms(ctx, "Merhaba, siparişiniz hazır.")   // parça hesabı, kota harcamaz
send.SendPush(ctx, map[string]any{"to": "contact:42", "class": "transactional", "subject": "Sipariş", "body": "Yola çıktı"})

Kişiler

go
send.ListContacts(ctx, signalbird.Query{"q": "ahmet", "page": 1})
send.CreateContact(ctx, map[string]any{"email": "ahmet@example.com"})
send.UpdateContact(ctx, contactID, map[string]any{"phone": "+905551112233"})
send.DeleteContact(ctx, contactID)

// 1000'lik parçalar, SIRAYLA
send.BulkContacts(ctx, map[string]any{
    "contacts": rows,          // []any ya da []map[string]any
    "list_id":  42,
})

Kampanyalar

go
send.CreateCampaign(ctx, map[string]any{
    "name":    "Ağustos bülteni",
    "channel": "email",
    "list_id": 42,
    "subject": "Bu ay neler oldu?",
    "body":    "<h1>Merhaba</h1>",
})

// Sayfaları gezer; fn false dönerse durur
send.IterateCampaignMessages(ctx, batchID, nil, func(row map[string]any) bool {
    reconcile(row["external_ref"], row["status"])
    return true
})

Webhook doğrulama

go
func handleWebhook(w http.ResponseWriter, r *http.Request) {
    raw, _ := io.ReadAll(r.Body)

    // HAM gövde üzerinde: json.Unmarshal + Marshal imzayı bozar
    if !signalbird.VerifyWebhook(raw, r.Header.Get("X-Signalbird-Signature"), secret) {
        http.Error(w, "invalid signature", http.StatusUnauthorized)
        return
    }

    var event struct {
        ID   string `json:"id"`
        Type string `json:"type"`
    }
    json.Unmarshal(raw, &event)

    // Yeniden gönderimlere karşı `id` ile tekilleştirin
    if seen(event.ID) {
        w.WriteHeader(http.StatusOK)
        return
    }
}

Yönetim - kendi projenizi kurun

go
admin, err := signalbird.NewManagement(signalbird.KeyConfig{
    DomainKey: os.Getenv("SIGNALBIRD_DOMAIN_KEY"),
})

created, _ := admin.CreateModuleKey(ctx, "logger", map[string]any{"title": "Ödeme hataları"})

var payload struct {
    Project struct{ ID int } `json:"project"`
    Secret  string           `json:"secret"`   // YALNIZ burada döner
}
created.Into(&payload)

admin.CreateRadioChannel(ctx, payload.Project.ID, map[string]any{
    "key":         "odeme",
    "name":        "Ödeme",
    "level":       "critical",
    "notify_push": true,
})

// Sohbet gelen kutusu
inbox, _ := admin.ListConversations(ctx, signalbird.Query{"status": "open"})

admin.Reply(ctx, conversationID, map[string]any{"body": "Merhaba! Birazdan dönüyoruz."})
admin.SetConversationStatus(ctx, conversationID, "resolved")

Anahtarınızın radio:*, chat:*, apps:* kapsamlarını taşıması gerekir. Ayrıntı: Yönetim dokümanı.


Sonuç biçimi

go
type Result struct {
    OK      bool
    Status  int
    Data    json.RawMessage
    Code    string
    Message string
}

Gövdeyi çözmek için Into:

go
var project struct {
    Project struct {
        ID   int    `json:"id"`
        Name string `json:"name"`
    } `json:"project"`
}

result.Into(&project)

ThrowOnError: true iken metotlar ikinci dönüş değerinde *signalbird.Error verir (Code, Status, Message, Body).

Ziyaretçi kimliği doğrulaması - identityHash

Sohbet widget'ı ve uygulama SDK'sı oturum açmış kullanıcıyı external_id ile tanıtır. Açık anahtar sayfada durduğu için Signalbird bu kimliği ancak yanında sizin sunucunuzda üretilmiş geçerli bir hash varsa güvenilir sayar (2.7.0). Hash olmadan ziyaretçi kişi kaydına bağlanmaz, cihazı o kullanıcıya push hedefi olarak bağlanmaz ve kanal ajanının araçları kimliği yalnız visitor.unverified altında görür.

go
client, _ := signalbird.NewClientFromEnv()
hash := client.IdentityHash(user.ID)

Gizli anahtarı zaten tutan Telsiz istemcisinin üzerindedir; ayrı kurulum gerekmez. Algoritma (her dilde aynı çıktı):

text
identity_hash = hex( HMAC-SHA256( hex(SHA-256(sb_secret_live_…)), external_id ) )

Anahtar gizli anahtarın SHA-256 özetidir (sunucu anahtarı düz saklamaz). Kullanım: Widget - Kimlik doğrulaması, Uygulama SDK'sı.

Sürüm bildirimi

SDK her istekte sürümünü bildirir: X-Signalbird-Sdk: go/<sürüm>. Yeni bir sürüm yayınlandığında API yanıtında Signalbird-Sdk-Status: outdated (ya da artık desteklenmiyorsa unsupported) döner ve SDK süreç başına bir kez uyarı yazar (log.Printf). Uyarı hata değildir: isteğin sonucu değişmez.

Panelde Domainler → [domain] → Anahtarlar her anahtarın hangi SDK sürümüyle kullanıldığını gösterir; eski sürümdeki anahtarlar için panelin tepesinde bir uyarı şeridi ve bildirim çıkar. Güncellemek için:

bash
go get github.com/Pariette-Inc/signalbird.sdk/v2@latest

Hata kodları

Kod Anlamı
ErrNoKey / ErrWrongKeyType Kurulum anında (NewClient hatası)
INVALID_KEY Anahtar yok, yanlış ya da proje pasif
API_KEY_SCOPE Anahtarda gereken kapsam yok
MODULE_DISABLED Paketinizde bu modül yok
LIMIT_REACHED Aylık limitiniz doldu
VALIDATION_ERROR 422
NETWORK_ERROR / TIMEOUT Ağ (status 0)

Davranış kuralları

  • Sessiz hata varsayılandır: err == nil ama result.OK == false olabilir. İkisini de kontrol edin.
  • Retry yoktur. Yeniden deneme kararı çağıranındır.
  • context her metotta ilk parametredir; isteğin iptali size bağlıdır.
  • Sorgu dizesinde nil alanlar atlanır, dilimler key[]= biçiminde gider, boole true/false metnine çevrilir.