social-agent-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +226 -0
- package/bin/postinstall.js +19 -0
- package/bin/social-agent.js +109 -0
- package/config.example.json +20 -0
- package/hooks/post-push +69 -0
- package/knowledge/bluesky.md +1083 -0
- package/knowledge/facebook.md +603 -0
- package/knowledge/instagram.md +686 -0
- package/knowledge/linkedin.md +1013 -0
- package/knowledge/mastodon.md +1291 -0
- package/knowledge/telegram.md +824 -0
- package/knowledge/x.md +1532 -0
- package/package.json +30 -0
|
@@ -0,0 +1,1083 @@
|
|
|
1
|
+
# Bluesky Platform Bilgisi
|
|
2
|
+
|
|
3
|
+
Bluesky, AT Protocol (Authenticated Transfer Protocol) üzerine kurulu merkezi olmayan bir sosyal ağdır.
|
|
4
|
+
API tamamen ücretsiz ve açıktır, herhangi bir geliştirici onayı veya OAuth uygulaması gerekmez.
|
|
5
|
+
Tüm işlemler XRPC (Cross-RPC) endpoint'leri üzerinden yapılır.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Kimlik Doğrulama (Authentication)
|
|
10
|
+
|
|
11
|
+
### 1.1 createSession — Giriş Yapma
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
POST https://bsky.social/xrpc/com.atproto.server.createSession
|
|
15
|
+
Content-Type: application/json
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
"identifier": "kullanici.bsky.social", // handle veya DID
|
|
19
|
+
"password": "xxxx-xxxx-xxxx-xxxx" // App Password önerilir
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Yanıt:**
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"accessJwt": "eyJ...", // 2 saat geçerli
|
|
27
|
+
"refreshJwt": "eyJ...", // 90 gün geçerli
|
|
28
|
+
"handle": "kullanici.bsky.social",
|
|
29
|
+
"did": "did:plc:abc123...",
|
|
30
|
+
"email": "user@example.com",
|
|
31
|
+
"emailConfirmed": true
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Önemli notlar:**
|
|
36
|
+
- `identifier` alanına handle (kullanici.bsky.social) veya DID (did:plc:...) yazılabilir.
|
|
37
|
+
- Hesap şifresi yerine **App Password** kullanılması şiddetle önerilir. Hesap ayarları > App Passwords > Yeni oluştur.
|
|
38
|
+
- App Password ile 2FA (iki faktörlü doğrulama) aktifken bile giriş yapılabilir.
|
|
39
|
+
- App Password ile hesap silme, şifre değiştirme gibi kritik işlemler yapılamaz — güvenlik sağlar.
|
|
40
|
+
|
|
41
|
+
### 1.2 Token Yenileme (Refresh Flow)
|
|
42
|
+
|
|
43
|
+
Access token süresi dolduğunda (2 saat), refresh token ile yenilenir:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
POST https://bsky.social/xrpc/com.atproto.server.refreshSession
|
|
47
|
+
Authorization: Bearer <refreshJwt>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Yanıt:** Yeni `accessJwt` ve `refreshJwt` döner. Eski refresh token geçersiz olur (rotation).
|
|
51
|
+
|
|
52
|
+
**Token akışı:**
|
|
53
|
+
1. `createSession` ile giriş yap → accessJwt + refreshJwt al
|
|
54
|
+
2. Tüm isteklerde `Authorization: Bearer <accessJwt>` kullan
|
|
55
|
+
3. 401 hatası alınca `refreshSession` ile yeni token al
|
|
56
|
+
4. Refresh token da süresi dolduysa tekrar `createSession` çağır
|
|
57
|
+
|
|
58
|
+
### 1.3 Oturumu Sonlandırma
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
POST https://bsky.social/xrpc/com.atproto.server.deleteSession
|
|
62
|
+
Authorization: Bearer <refreshJwt>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 2. API Endpoint'leri (XRPC)
|
|
68
|
+
|
|
69
|
+
Tüm endpoint'ler `https://bsky.social/xrpc/` altındadır. Base URL PDS (Personal Data Server) adresine göre değişebilir, ancak `bsky.social` varsayılan ve en yaygın PDS'dir.
|
|
70
|
+
|
|
71
|
+
### 2.1 Post İşlemleri
|
|
72
|
+
|
|
73
|
+
#### Post Oluşturma
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
POST /xrpc/com.atproto.repo.createRecord
|
|
77
|
+
Authorization: Bearer <accessJwt>
|
|
78
|
+
Content-Type: application/json
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
"repo": "<did>",
|
|
82
|
+
"collection": "app.bsky.feed.post",
|
|
83
|
+
"record": {
|
|
84
|
+
"$type": "app.bsky.feed.post",
|
|
85
|
+
"text": "Merhaba Bluesky!",
|
|
86
|
+
"createdAt": "2026-03-14T12:00:00.000Z",
|
|
87
|
+
"langs": ["tr"],
|
|
88
|
+
"facets": [],
|
|
89
|
+
"embed": null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Yanıt:**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"uri": "at://did:plc:abc123/app.bsky.feed.post/3k...",
|
|
98
|
+
"cid": "bafyrei..."
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- `uri` formatı: `at://<did>/<collection>/<rkey>`
|
|
103
|
+
- `rkey` (record key): URI'nin son parçası, post ID'sidir (TID formatı).
|
|
104
|
+
- `cid` (Content ID): Verinin hash'i, veri bütünlüğünü doğrular.
|
|
105
|
+
- `text` maksimum 300 karakter (grapheme cinsinden).
|
|
106
|
+
- `createdAt` ISO 8601 formatında zorunludur.
|
|
107
|
+
- `langs` opsiyonel, BCP-47 dil kodları (örn: `["tr"]`, `["en", "tr"]`).
|
|
108
|
+
|
|
109
|
+
#### Post Silme
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
POST /xrpc/com.atproto.repo.deleteRecord
|
|
113
|
+
Authorization: Bearer <accessJwt>
|
|
114
|
+
Content-Type: application/json
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
"repo": "<did>",
|
|
118
|
+
"collection": "app.bsky.feed.post",
|
|
119
|
+
"rkey": "<rkey>"
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Yanıt (Reply) Post
|
|
124
|
+
|
|
125
|
+
Reply yapmak için `record.reply` alanı eklenir:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"record": {
|
|
130
|
+
"$type": "app.bsky.feed.post",
|
|
131
|
+
"text": "Bu bir yanıt!",
|
|
132
|
+
"createdAt": "2026-03-14T12:00:00.000Z",
|
|
133
|
+
"reply": {
|
|
134
|
+
"root": {
|
|
135
|
+
"uri": "at://did:plc:abc/app.bsky.feed.post/root123",
|
|
136
|
+
"cid": "bafyrei..."
|
|
137
|
+
},
|
|
138
|
+
"parent": {
|
|
139
|
+
"uri": "at://did:plc:abc/app.bsky.feed.post/parent456",
|
|
140
|
+
"cid": "bafyrei..."
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- `root`: Thread'in ilk postu (en üst).
|
|
148
|
+
- `parent`: Doğrudan yanıt verilen post.
|
|
149
|
+
- Tek bir posta yanıt verirken root ve parent aynı olabilir.
|
|
150
|
+
|
|
151
|
+
#### Thread Gate (Yanıt Kısıtlama)
|
|
152
|
+
|
|
153
|
+
Post oluşturulduktan sonra kimin yanıt verebileceği kısıtlanabilir:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"repo": "<did>",
|
|
158
|
+
"collection": "app.bsky.feed.threadgate",
|
|
159
|
+
"rkey": "<post_rkey>",
|
|
160
|
+
"record": {
|
|
161
|
+
"$type": "app.bsky.feed.threadgate",
|
|
162
|
+
"post": "at://did:plc:abc/app.bsky.feed.post/123",
|
|
163
|
+
"createdAt": "2026-03-14T12:00:00.000Z",
|
|
164
|
+
"allow": [
|
|
165
|
+
{ "$type": "app.bsky.feed.threadgate#mentionRule" },
|
|
166
|
+
{ "$type": "app.bsky.feed.threadgate#followingRule" },
|
|
167
|
+
{ "$type": "app.bsky.feed.threadgate#listRule", "list": "at://did:plc:abc/app.bsky.graph.list/xyz" }
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 2.2 Beğenme (Like)
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
POST /xrpc/com.atproto.repo.createRecord
|
|
177
|
+
Authorization: Bearer <accessJwt>
|
|
178
|
+
Content-Type: application/json
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
"repo": "<did>",
|
|
182
|
+
"collection": "app.bsky.feed.like",
|
|
183
|
+
"record": {
|
|
184
|
+
"$type": "app.bsky.feed.like",
|
|
185
|
+
"subject": {
|
|
186
|
+
"uri": "at://did:plc:target/app.bsky.feed.post/abc123",
|
|
187
|
+
"cid": "bafyrei..."
|
|
188
|
+
},
|
|
189
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Beğeniyi kaldırmak için `deleteRecord` ile like kaydı silinir.
|
|
195
|
+
|
|
196
|
+
### 2.3 Repost
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"repo": "<did>",
|
|
201
|
+
"collection": "app.bsky.feed.repost",
|
|
202
|
+
"record": {
|
|
203
|
+
"$type": "app.bsky.feed.repost",
|
|
204
|
+
"subject": {
|
|
205
|
+
"uri": "at://did:plc:target/app.bsky.feed.post/abc123",
|
|
206
|
+
"cid": "bafyrei..."
|
|
207
|
+
},
|
|
208
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 2.4 Takip Etme (Follow)
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"repo": "<did>",
|
|
218
|
+
"collection": "app.bsky.graph.follow",
|
|
219
|
+
"record": {
|
|
220
|
+
"$type": "app.bsky.graph.follow",
|
|
221
|
+
"subject": "did:plc:hedef_kullanici",
|
|
222
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Takibi bırakmak: `deleteRecord` ile follow kaydı silinir.
|
|
228
|
+
|
|
229
|
+
### 2.5 Engelleme (Block)
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"repo": "<did>",
|
|
234
|
+
"collection": "app.bsky.graph.block",
|
|
235
|
+
"record": {
|
|
236
|
+
"$type": "app.bsky.graph.block",
|
|
237
|
+
"subject": "did:plc:engellenecek_kullanici",
|
|
238
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 2.6 Sessize Alma (Mute)
|
|
244
|
+
|
|
245
|
+
Mute farklıdır — repo kaydı oluşturulmaz, doğrudan API çağrısı yapılır:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
POST /xrpc/app.bsky.graph.muteActor
|
|
249
|
+
Authorization: Bearer <accessJwt>
|
|
250
|
+
Content-Type: application/json
|
|
251
|
+
|
|
252
|
+
{ "actor": "did:plc:hedef" }
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Unmute:
|
|
256
|
+
```
|
|
257
|
+
POST /xrpc/app.bsky.graph.unmuteActor
|
|
258
|
+
{ "actor": "did:plc:hedef" }
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 2.7 Medya Yükleme (Upload Blob)
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
POST /xrpc/com.atproto.repo.uploadBlob
|
|
265
|
+
Authorization: Bearer <accessJwt>
|
|
266
|
+
Content-Type: image/png (veya image/jpeg, image/webp, image/gif)
|
|
267
|
+
|
|
268
|
+
<binary data>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Yanıt:**
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"blob": {
|
|
275
|
+
"$type": "blob",
|
|
276
|
+
"ref": { "$link": "bafkrei..." },
|
|
277
|
+
"mimeType": "image/png",
|
|
278
|
+
"size": 45678
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Önemli:**
|
|
284
|
+
- Maksimum dosya boyutu: **1 MB** (görsel), **50 MB** (video — ayrı endpoint).
|
|
285
|
+
- Yüklenen blob geçicidir; 1 saat içinde bir kayıtta (record) referans verilmezse silinir.
|
|
286
|
+
- Desteklenen görsel formatları: PNG, JPEG, WebP, GIF (animasyonlu GIF dahil, ancak durağan olarak gösterilir).
|
|
287
|
+
|
|
288
|
+
### 2.8 Video Yükleme
|
|
289
|
+
|
|
290
|
+
Video yükleme ayrı bir akış gerektirir:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
GET /xrpc/app.bsky.video.getJobStatus?jobId=<id>
|
|
294
|
+
GET /xrpc/app.bsky.video.getUploadLimits
|
|
295
|
+
POST /xrpc/app.bsky.video.uploadVideo (Content-Type: video/mp4)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- Maksimum video boyutu: **50 MB**
|
|
299
|
+
- Maksimum süre: **60 saniye** (bazı hesaplarda 90 saniye)
|
|
300
|
+
- Format: MP4 (H.264 codec önerilir)
|
|
301
|
+
- Video yüklendikten sonra işlenir (transcoding), `getJobStatus` ile durum takip edilir.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 3. Rich Text Facets
|
|
306
|
+
|
|
307
|
+
Bluesky'da mention, link ve hashtag'ler `facets` dizisi ile tanımlanır.
|
|
308
|
+
**Kritik: Byte offset kullanılır, karakter offset değil!** UTF-8 encoding ile byte pozisyonları hesaplanmalıdır.
|
|
309
|
+
|
|
310
|
+
### 3.1 Facet Yapısı
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"facets": [
|
|
315
|
+
{
|
|
316
|
+
"index": {
|
|
317
|
+
"byteStart": 0,
|
|
318
|
+
"byteEnd": 14
|
|
319
|
+
},
|
|
320
|
+
"features": [
|
|
321
|
+
{
|
|
322
|
+
"$type": "app.bsky.richtext.facet#mention",
|
|
323
|
+
"did": "did:plc:abc123"
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### 3.2 Mention (Bahsetme)
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"$type": "app.bsky.richtext.facet#mention",
|
|
336
|
+
"did": "did:plc:hedef_kullanici_did"
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
- Metinde `@kullanici.bsky.social` yazılır.
|
|
341
|
+
- Facet'te handle değil **DID** belirtilir.
|
|
342
|
+
- Handle → DID çözümlemek için: `GET /xrpc/com.atproto.identity.resolveHandle?handle=kullanici.bsky.social`
|
|
343
|
+
|
|
344
|
+
### 3.3 Link
|
|
345
|
+
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"$type": "app.bsky.richtext.facet#link",
|
|
349
|
+
"uri": "https://example.com"
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
- Metindeki URL tam olarak facet aralığına denk gelmelidir.
|
|
354
|
+
- URI validasyonu yapılır, geçersiz URI'ler reddedilir.
|
|
355
|
+
|
|
356
|
+
### 3.4 Hashtag (Etiket)
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"$type": "app.bsky.richtext.facet#tag",
|
|
361
|
+
"tag": "bluesky"
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
- Metinde `#bluesky` yazılır, facet `tag` alanında `#` olmadan sadece etiket adı verilir.
|
|
366
|
+
- Hashtag arama: `https://bsky.app/search?q=%23bluesky`
|
|
367
|
+
|
|
368
|
+
### 3.5 Byte Offset Hesaplama (TypeScript)
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const encoder = new TextEncoder(); // UTF-8
|
|
372
|
+
|
|
373
|
+
function findByteOffsets(text: string, matchStart: number, matchText: string) {
|
|
374
|
+
const byteStart = encoder.encode(text.substring(0, matchStart)).byteLength;
|
|
375
|
+
const byteEnd = byteStart + encoder.encode(matchText).byteLength;
|
|
376
|
+
return { byteStart, byteEnd };
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Dikkat:** Türkçe karakterler (ş, ğ, ü, ö, ç, ı, İ) ve emoji gibi çok baytlı karakterlerde byte offset ile karakter index'i farklıdır. `TextEncoder` kullanmak zorunludur.
|
|
381
|
+
|
|
382
|
+
Örnek: `"Türkçe #test"` metninde `#test` karakter 8'de başlar ama byte 9'da başlar (ü = 2 byte).
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 4. Embed Tipleri
|
|
387
|
+
|
|
388
|
+
Post'lara görsel, link kartı, alıntı (quote) eklemek için `embed` alanı kullanılır.
|
|
389
|
+
|
|
390
|
+
### 4.1 Görsel Embed
|
|
391
|
+
|
|
392
|
+
```json
|
|
393
|
+
{
|
|
394
|
+
"embed": {
|
|
395
|
+
"$type": "app.bsky.embed.images",
|
|
396
|
+
"images": [
|
|
397
|
+
{
|
|
398
|
+
"alt": "Görsel açıklaması (erişilebilirlik için)",
|
|
399
|
+
"image": {
|
|
400
|
+
"$type": "blob",
|
|
401
|
+
"ref": { "$link": "bafkrei..." },
|
|
402
|
+
"mimeType": "image/jpeg",
|
|
403
|
+
"size": 45678
|
|
404
|
+
},
|
|
405
|
+
"aspectRatio": {
|
|
406
|
+
"width": 1200,
|
|
407
|
+
"height": 630
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
- Maksimum **4 görsel** eklenebilir.
|
|
416
|
+
- `alt` alanı zorunlu değil ama erişilebilirlik için önerilir.
|
|
417
|
+
- `aspectRatio` opsiyonel ama verilirse görsel düzgün kırpılır.
|
|
418
|
+
|
|
419
|
+
### 4.2 Harici Link Embed (Link Kartı / OG Card)
|
|
420
|
+
|
|
421
|
+
```json
|
|
422
|
+
{
|
|
423
|
+
"embed": {
|
|
424
|
+
"$type": "app.bsky.embed.external",
|
|
425
|
+
"external": {
|
|
426
|
+
"uri": "https://example.com/article",
|
|
427
|
+
"title": "Makale Başlığı",
|
|
428
|
+
"description": "Makale açıklaması...",
|
|
429
|
+
"thumb": {
|
|
430
|
+
"$type": "blob",
|
|
431
|
+
"ref": { "$link": "bafkrei..." },
|
|
432
|
+
"mimeType": "image/jpeg",
|
|
433
|
+
"size": 12345
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**Önemli:** Bluesky sunucusu link kartı otomatik oluşturmaz! Client tarafında:
|
|
441
|
+
1. Hedef URL'den OG meta tag'leri çekilir (title, description, image).
|
|
442
|
+
2. OG image varsa `uploadBlob` ile yüklenir.
|
|
443
|
+
3. Tüm bilgiler embed'e yazılır.
|
|
444
|
+
4. `thumb` opsiyoneldir, olmadan da link kartı oluşturulur (görselsiz).
|
|
445
|
+
|
|
446
|
+
### 4.3 Alıntı Post (Quote Post)
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"embed": {
|
|
451
|
+
"$type": "app.bsky.embed.record",
|
|
452
|
+
"record": {
|
|
453
|
+
"uri": "at://did:plc:abc/app.bsky.feed.post/xyz",
|
|
454
|
+
"cid": "bafyrei..."
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 4.4 Görsel + Alıntı (Kombine Embed)
|
|
461
|
+
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"embed": {
|
|
465
|
+
"$type": "app.bsky.embed.recordWithMedia",
|
|
466
|
+
"record": {
|
|
467
|
+
"record": {
|
|
468
|
+
"uri": "at://did:plc:abc/app.bsky.feed.post/xyz",
|
|
469
|
+
"cid": "bafyrei..."
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
"media": {
|
|
473
|
+
"$type": "app.bsky.embed.images",
|
|
474
|
+
"images": [...]
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### 4.5 Video Embed
|
|
481
|
+
|
|
482
|
+
```json
|
|
483
|
+
{
|
|
484
|
+
"embed": {
|
|
485
|
+
"$type": "app.bsky.embed.video",
|
|
486
|
+
"video": {
|
|
487
|
+
"$type": "blob",
|
|
488
|
+
"ref": { "$link": "bafkrei..." },
|
|
489
|
+
"mimeType": "video/mp4",
|
|
490
|
+
"size": 5000000
|
|
491
|
+
},
|
|
492
|
+
"alt": "Video açıklaması",
|
|
493
|
+
"aspectRatio": {
|
|
494
|
+
"width": 1920,
|
|
495
|
+
"height": 1080
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## 5. Okuma (Read) Endpoint'leri
|
|
504
|
+
|
|
505
|
+
Bu endpoint'ler `GET` istekleri ile çalışır. Çoğu kimlik doğrulama gerektirir.
|
|
506
|
+
|
|
507
|
+
### 5.1 Profil Bilgileri
|
|
508
|
+
|
|
509
|
+
```
|
|
510
|
+
GET /xrpc/app.bsky.actor.getProfile?actor=kullanici.bsky.social
|
|
511
|
+
Authorization: Bearer <accessJwt>
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
**Yanıt:** displayName, description, avatar, banner, followersCount, followsCount, postsCount, vb.
|
|
515
|
+
|
|
516
|
+
### 5.2 Kullanıcı Arama
|
|
517
|
+
|
|
518
|
+
```
|
|
519
|
+
GET /xrpc/app.bsky.actor.searchActors?q=arama_terimi&limit=25
|
|
520
|
+
Authorization: Bearer <accessJwt>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
- `q`: Arama terimi (handle veya display name)
|
|
524
|
+
- `limit`: Sonuç sayısı (maks 100, varsayılan 25)
|
|
525
|
+
- `cursor`: Sayfalama için
|
|
526
|
+
|
|
527
|
+
### 5.3 Post Arama
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
GET /xrpc/app.bsky.feed.searchPosts?q=arama_terimi&limit=25
|
|
531
|
+
Authorization: Bearer <accessJwt>
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
- `q`: Arama terimi
|
|
535
|
+
- `sort`: `top` veya `latest` (varsayılan: `latest`)
|
|
536
|
+
- `since` / `until`: Tarih filtresi (ISO 8601)
|
|
537
|
+
- `author`: Belirli bir kullanıcının postlarında ara
|
|
538
|
+
- `lang`: Dil filtresi (örn: `tr`)
|
|
539
|
+
- `tag`: Hashtag filtresi
|
|
540
|
+
|
|
541
|
+
### 5.4 Bildirimler
|
|
542
|
+
|
|
543
|
+
```
|
|
544
|
+
GET /xrpc/app.bsky.notification.listNotifications?limit=50
|
|
545
|
+
Authorization: Bearer <accessJwt>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Bildirim türleri (reason):** `like`, `repost`, `follow`, `mention`, `reply`, `quote`, `starterpack-joined`
|
|
549
|
+
|
|
550
|
+
Bildirimleri okundu olarak işaretleme:
|
|
551
|
+
```
|
|
552
|
+
POST /xrpc/app.bsky.notification.updateSeen
|
|
553
|
+
{ "seenAt": "2026-03-14T12:00:00.000Z" }
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### 5.5 Timeline (Akış)
|
|
557
|
+
|
|
558
|
+
```
|
|
559
|
+
GET /xrpc/app.bsky.feed.getTimeline?limit=50
|
|
560
|
+
Authorization: Bearer <accessJwt>
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### 5.6 Kullanıcının Postları
|
|
564
|
+
|
|
565
|
+
```
|
|
566
|
+
GET /xrpc/app.bsky.feed.getAuthorFeed?actor=kullanici.bsky.social&limit=50
|
|
567
|
+
Authorization: Bearer <accessJwt>
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
- `filter`: `posts_with_replies`, `posts_no_replies`, `posts_with_media`, `posts_and_author_threads`
|
|
571
|
+
|
|
572
|
+
### 5.7 Post Detayı
|
|
573
|
+
|
|
574
|
+
```
|
|
575
|
+
GET /xrpc/app.bsky.feed.getPosts?uris=at://did:plc:abc/app.bsky.feed.post/xyz
|
|
576
|
+
Authorization: Bearer <accessJwt>
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
- Birden fazla URI virgülle ayrılarak tek istekte sorgulanabilir (maks 25).
|
|
580
|
+
|
|
581
|
+
### 5.8 Thread Görüntüleme
|
|
582
|
+
|
|
583
|
+
```
|
|
584
|
+
GET /xrpc/app.bsky.feed.getPostThread?uri=at://did:plc:abc/app.bsky.feed.post/xyz&depth=6
|
|
585
|
+
Authorization: Bearer <accessJwt>
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### 5.9 Takipçiler ve Takip Edilenler
|
|
589
|
+
|
|
590
|
+
```
|
|
591
|
+
GET /xrpc/app.bsky.graph.getFollowers?actor=kullanici.bsky.social&limit=100
|
|
592
|
+
GET /xrpc/app.bsky.graph.getFollows?actor=kullanici.bsky.social&limit=100
|
|
593
|
+
Authorization: Bearer <accessJwt>
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### 5.10 Handle Çözümleme
|
|
597
|
+
|
|
598
|
+
```
|
|
599
|
+
GET /xrpc/com.atproto.identity.resolveHandle?handle=kullanici.bsky.social
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
Kimlik doğrulama gerektirmez. Yanıt: `{ "did": "did:plc:abc123" }`
|
|
603
|
+
|
|
604
|
+
### 5.11 Beğenenler ve Repost Edenler
|
|
605
|
+
|
|
606
|
+
```
|
|
607
|
+
GET /xrpc/app.bsky.feed.getLikes?uri=at://did:plc:abc/app.bsky.feed.post/xyz&limit=100
|
|
608
|
+
GET /xrpc/app.bsky.feed.getRepostedBy?uri=at://did:plc:abc/app.bsky.feed.post/xyz&limit=100
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## 6. Listeler ve Özel Akışlar (Custom Feeds)
|
|
614
|
+
|
|
615
|
+
### 6.1 Liste Oluşturma
|
|
616
|
+
|
|
617
|
+
```json
|
|
618
|
+
{
|
|
619
|
+
"repo": "<did>",
|
|
620
|
+
"collection": "app.bsky.graph.list",
|
|
621
|
+
"record": {
|
|
622
|
+
"$type": "app.bsky.graph.list",
|
|
623
|
+
"purpose": "app.bsky.graph.defs#curatelist",
|
|
624
|
+
"name": "Türk Geliştiriciler",
|
|
625
|
+
"description": "Türkiye'den yazılımcılar",
|
|
626
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Liste amaçları (`purpose`):
|
|
632
|
+
- `app.bsky.graph.defs#curatelist` — Kürasyon listesi (takip koleksiyonu)
|
|
633
|
+
- `app.bsky.graph.defs#modlist` — Moderasyon listesi (toplu mute/block)
|
|
634
|
+
|
|
635
|
+
### 6.2 Listeye Kullanıcı Ekleme
|
|
636
|
+
|
|
637
|
+
```json
|
|
638
|
+
{
|
|
639
|
+
"repo": "<did>",
|
|
640
|
+
"collection": "app.bsky.graph.listitem",
|
|
641
|
+
"record": {
|
|
642
|
+
"$type": "app.bsky.graph.listitem",
|
|
643
|
+
"subject": "did:plc:eklenecek_kullanici",
|
|
644
|
+
"list": "at://did:plc:abc/app.bsky.graph.list/xyz",
|
|
645
|
+
"createdAt": "2026-03-14T12:00:00.000Z"
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
### 6.3 Custom Feed (Özel Akış / Feed Generator)
|
|
651
|
+
|
|
652
|
+
Bluesky'da herkes kendi algoritmasını oluşturabilir. Feed generator bir web servisidir:
|
|
653
|
+
|
|
654
|
+
```
|
|
655
|
+
GET /xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:abc/app.bsky.feed.generator/my-feed&limit=30
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
Popüler feed'ler:
|
|
659
|
+
- `at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot` — Keşfet
|
|
660
|
+
- `at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/with-friends` — Arkadaşlarla
|
|
661
|
+
|
|
662
|
+
Feed'leri listeleme:
|
|
663
|
+
```
|
|
664
|
+
GET /xrpc/app.bsky.feed.getActorFeeds?actor=kullanici.bsky.social
|
|
665
|
+
GET /xrpc/app.bsky.feed.getSuggestedFeeds
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## 7. URL Yapısı
|
|
671
|
+
|
|
672
|
+
### Web URL'leri (bsky.app)
|
|
673
|
+
|
|
674
|
+
| Sayfa | URL |
|
|
675
|
+
|-------|-----|
|
|
676
|
+
| Profil | `https://bsky.app/profile/kullanici.bsky.social` |
|
|
677
|
+
| Profil (DID ile) | `https://bsky.app/profile/did:plc:abc123` |
|
|
678
|
+
| Post | `https://bsky.app/profile/kullanici.bsky.social/post/<rkey>` |
|
|
679
|
+
| Post (DID ile) | `https://bsky.app/profile/did:plc:abc123/post/<rkey>` |
|
|
680
|
+
| Arama | `https://bsky.app/search?q=arama_terimi` |
|
|
681
|
+
| Hashtag arama | `https://bsky.app/search?q=%23hashtag` |
|
|
682
|
+
| Ayarlar | `https://bsky.app/settings` |
|
|
683
|
+
| Akışlar | `https://bsky.app/feeds` |
|
|
684
|
+
| Bildirimler | `https://bsky.app/notifications` |
|
|
685
|
+
| Listeler | `https://bsky.app/profile/kullanici.bsky.social/lists` |
|
|
686
|
+
| Belirli liste | `https://bsky.app/profile/kullanici.bsky.social/lists/<rkey>` |
|
|
687
|
+
| Feed | `https://bsky.app/profile/kullanici.bsky.social/feed/<rkey>` |
|
|
688
|
+
| Starter Pack | `https://bsky.app/starter-pack/kullanici.bsky.social/<rkey>` |
|
|
689
|
+
|
|
690
|
+
### AT Protocol URI'leri
|
|
691
|
+
|
|
692
|
+
```
|
|
693
|
+
at://did:plc:abc123/app.bsky.feed.post/3k... → Post
|
|
694
|
+
at://did:plc:abc123/app.bsky.feed.like/3k... → Like kaydı
|
|
695
|
+
at://did:plc:abc123/app.bsky.feed.repost/3k... → Repost kaydı
|
|
696
|
+
at://did:plc:abc123/app.bsky.graph.follow/3k... → Follow kaydı
|
|
697
|
+
at://did:plc:abc123/app.bsky.graph.block/3k... → Block kaydı
|
|
698
|
+
at://did:plc:abc123/app.bsky.graph.list/3k... → Liste
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Web URL'den AT URI'ye Dönüşüm
|
|
702
|
+
|
|
703
|
+
Post URL'si `https://bsky.app/profile/HANDLE/post/RKEY` formatındadır.
|
|
704
|
+
1. Handle'ı DID'e çevir: `resolveHandle`
|
|
705
|
+
2. AT URI oluştur: `at://<did>/app.bsky.feed.post/<rkey>`
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## 8. Görsel Boyutları ve Öneriler
|
|
710
|
+
|
|
711
|
+
### Post Görselleri
|
|
712
|
+
|
|
713
|
+
| Özellik | Değer |
|
|
714
|
+
|---------|-------|
|
|
715
|
+
| Önerilen boyut | 1200 x 630 px (1.91:1 oran) |
|
|
716
|
+
| Maksimum dosya boyutu | 1 MB (1.000.000 byte) |
|
|
717
|
+
| Maksimum görsel sayısı | 4 adet per post |
|
|
718
|
+
| Desteklenen formatlar | PNG, JPEG, WebP, GIF |
|
|
719
|
+
| Minimum boyut | Belirtilmemiş, çok küçük olmamalı |
|
|
720
|
+
|
|
721
|
+
### Profil Görselleri
|
|
722
|
+
|
|
723
|
+
| Özellik | Değer |
|
|
724
|
+
|---------|-------|
|
|
725
|
+
| Avatar | 1000 x 1000 px önerilir, kare kırpılır |
|
|
726
|
+
| Banner | 3000 x 1000 px önerilir (3:1 oran) |
|
|
727
|
+
| Maks dosya boyutu | 1 MB |
|
|
728
|
+
|
|
729
|
+
### Aspect Ratio (En-Boy Oranı)
|
|
730
|
+
|
|
731
|
+
Post'a görsel eklerken `aspectRatio` belirtilmesi önerilir:
|
|
732
|
+
```json
|
|
733
|
+
{
|
|
734
|
+
"aspectRatio": {
|
|
735
|
+
"width": 1200,
|
|
736
|
+
"height": 630
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
Yaygın oranlar:
|
|
742
|
+
- **1.91:1** (1200x630) — Link kartı benzeri, yatay
|
|
743
|
+
- **16:9** (1920x1080) — Geniş ekran
|
|
744
|
+
- **4:3** (1200x900) — Klasik
|
|
745
|
+
- **1:1** (1080x1080) — Kare
|
|
746
|
+
- **4:5** (1080x1350) — Dikey (en uzun desteklenen oran)
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## 9. Rate Limiting (Hız Sınırlaması)
|
|
751
|
+
|
|
752
|
+
Bluesky rate limitleri çok cömerttir, diğer platformlara kıyasla oldukça rahat:
|
|
753
|
+
|
|
754
|
+
### Puan Sistemi
|
|
755
|
+
|
|
756
|
+
| Sınır | Değer |
|
|
757
|
+
|-------|-------|
|
|
758
|
+
| Toplam bütçe | **5000 puan / saat** (kayan pencere) |
|
|
759
|
+
| Puan sıfırlanması | Her saat başı değil, sürekli kayan pencere |
|
|
760
|
+
|
|
761
|
+
### İşlem Başına Puan Maliyeti
|
|
762
|
+
|
|
763
|
+
| İşlem | Puan |
|
|
764
|
+
|-------|------|
|
|
765
|
+
| `createRecord` (post, like, repost, follow) | 3 puan |
|
|
766
|
+
| `deleteRecord` | 1 puan |
|
|
767
|
+
| `uploadBlob` (görsel/video yükleme) | 25 puan |
|
|
768
|
+
| `createSession` | 3 puan |
|
|
769
|
+
| Okuma işlemleri (GET) | 1 puan |
|
|
770
|
+
|
|
771
|
+
### Hesaplama Örneği
|
|
772
|
+
|
|
773
|
+
Saatte yapılabilecek maksimum işlemler:
|
|
774
|
+
- ~1666 post (sadece metin)
|
|
775
|
+
- ~200 görsel yükleme
|
|
776
|
+
- ~5000 okuma isteği
|
|
777
|
+
- Karma kullanım: 100 görselli post (100×25 + 100×3 = 2800 puan) + 2200 okuma
|
|
778
|
+
|
|
779
|
+
### Rate Limit Yanıtı
|
|
780
|
+
|
|
781
|
+
Limit aşıldığında HTTP 429 döner:
|
|
782
|
+
```
|
|
783
|
+
HTTP/1.1 429 Too Many Requests
|
|
784
|
+
RateLimit-Limit: 5000
|
|
785
|
+
RateLimit-Remaining: 0
|
|
786
|
+
RateLimit-Reset: 1710421200
|
|
787
|
+
RateLimit-Policy: 5000;w=3600
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
Header'lardan kalan puan ve sıfırlanma zamanı okunabilir.
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
## 10. Etiketler ve Moderasyon (Labels)
|
|
795
|
+
|
|
796
|
+
### 10.1 Self-Label (Kendi İçeriğini Etiketleme)
|
|
797
|
+
|
|
798
|
+
Post'a veya profil'e içerik uyarısı eklemek için:
|
|
799
|
+
|
|
800
|
+
```json
|
|
801
|
+
{
|
|
802
|
+
"record": {
|
|
803
|
+
"$type": "app.bsky.feed.post",
|
|
804
|
+
"text": "İçerik burada",
|
|
805
|
+
"createdAt": "2026-03-14T12:00:00.000Z",
|
|
806
|
+
"labels": {
|
|
807
|
+
"$type": "com.atproto.label.defs#selfLabels",
|
|
808
|
+
"values": [
|
|
809
|
+
{ "val": "sexual" }
|
|
810
|
+
]
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### 10.2 Yaygın Etiket Değerleri
|
|
817
|
+
|
|
818
|
+
| Etiket | Açıklama |
|
|
819
|
+
|--------|----------|
|
|
820
|
+
| `sexual` | Cinsel içerik |
|
|
821
|
+
| `nudity` | Çıplaklık |
|
|
822
|
+
| `porn` | Pornografi |
|
|
823
|
+
| `graphic-media` | Şiddet/rahatsız edici görsel |
|
|
824
|
+
| `gore` | Kanlı/şiddet içeriği |
|
|
825
|
+
|
|
826
|
+
### 10.3 Moderasyon Servisleri
|
|
827
|
+
|
|
828
|
+
Bluesky'da moderasyon merkezi değildir. Farklı labeler servisleri içerikleri etiketler:
|
|
829
|
+
|
|
830
|
+
```
|
|
831
|
+
GET /xrpc/app.bsky.labeler.getServices?dids=did:plc:labeler_did
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
Kullanıcılar hangi moderasyon servislerine abone olacaklarını seçebilir.
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## 11. Sayfalama (Pagination)
|
|
839
|
+
|
|
840
|
+
Çoğu liste endpoint'i `cursor` tabanlı sayfalama kullanır:
|
|
841
|
+
|
|
842
|
+
```
|
|
843
|
+
GET /xrpc/app.bsky.feed.getTimeline?limit=50
|
|
844
|
+
|
|
845
|
+
→ { "cursor": "1710421200::bafyrei...", "feed": [...] }
|
|
846
|
+
|
|
847
|
+
GET /xrpc/app.bsky.feed.getTimeline?limit=50&cursor=1710421200::bafyrei...
|
|
848
|
+
|
|
849
|
+
→ { "cursor": "1710420000::bafyrei...", "feed": [...] }
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
- `cursor` opak bir string'dir, içeriği değişebilir.
|
|
853
|
+
- `cursor` null veya yoksa son sayfa demektir.
|
|
854
|
+
- `limit` genellikle 1-100 arasıdır.
|
|
855
|
+
|
|
856
|
+
---
|
|
857
|
+
|
|
858
|
+
## 12. Hata Kodları
|
|
859
|
+
|
|
860
|
+
| HTTP Kodu | XRPC Hatası | Açıklama |
|
|
861
|
+
|-----------|-------------|----------|
|
|
862
|
+
| 400 | `InvalidRequest` | Geçersiz parametre veya body |
|
|
863
|
+
| 401 | `AuthenticationRequired` | Token geçersiz veya eksik |
|
|
864
|
+
| 403 | `Forbidden` | Yetkisiz işlem (engelli kullanıcıya erişim vb.) |
|
|
865
|
+
| 404 | `RecordNotFound` | Kayıt bulunamadı |
|
|
866
|
+
| 413 | `PayloadTooLarge` | Dosya çok büyük (1 MB üzeri görsel) |
|
|
867
|
+
| 429 | `RateLimitExceeded` | Rate limit aşıldı |
|
|
868
|
+
| 502 | `UpstreamFailure` | PDS veya AppView hatası |
|
|
869
|
+
|
|
870
|
+
Hata yanıt formatı:
|
|
871
|
+
```json
|
|
872
|
+
{
|
|
873
|
+
"error": "InvalidRequest",
|
|
874
|
+
"message": "Record/text must be a string with length between 1 and 300"
|
|
875
|
+
}
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
## 13. DID ve Handle Sistemi
|
|
881
|
+
|
|
882
|
+
### DID (Decentralized Identifier)
|
|
883
|
+
|
|
884
|
+
Her Bluesky hesabı benzersiz ve kalıcı bir DID'e sahiptir:
|
|
885
|
+
- `did:plc:abc123...` — PLC (Public Ledger of Credentials) yöntemi, en yaygın
|
|
886
|
+
- `did:web:example.com` — Web tabanlı DID, kendi domain'ini handle olarak kullananlar
|
|
887
|
+
|
|
888
|
+
DID asla değişmez, handle değişse bile DID aynı kalır. Bu yüzden kayıtlarda (record) her zaman DID kullanılır.
|
|
889
|
+
|
|
890
|
+
### Handle
|
|
891
|
+
|
|
892
|
+
Handle, kullanıcının okunabilir adıdır:
|
|
893
|
+
- `kullanici.bsky.social` — Varsayılan subdomain
|
|
894
|
+
- `kullanici.com` — Özel domain (DNS TXT kaydı ile doğrulanır)
|
|
895
|
+
|
|
896
|
+
Handle çözümleme:
|
|
897
|
+
```
|
|
898
|
+
GET /xrpc/com.atproto.identity.resolveHandle?handle=kullanici.bsky.social
|
|
899
|
+
→ { "did": "did:plc:abc123" }
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
---
|
|
903
|
+
|
|
904
|
+
## 14. PDS (Personal Data Server) Bilgisi
|
|
905
|
+
|
|
906
|
+
Bluesky merkezi olmayan bir yapıdadır. Her kullanıcının verisi bir PDS'de tutulur:
|
|
907
|
+
- `bsky.social` — Bluesky'ın resmi PDS'i (çoğu kullanıcı burada)
|
|
908
|
+
- Üçüncü parti PDS'ler de vardır
|
|
909
|
+
|
|
910
|
+
Kullanıcının PDS'ini bulmak:
|
|
911
|
+
```
|
|
912
|
+
GET https://plc.directory/did:plc:abc123
|
|
913
|
+
→ { "service": [{ "serviceEndpoint": "https://pds.example.com" }] }
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
API istekleri genelde `bsky.social`'a yapılır, PDS yönlendirmeyi otomatik yapar.
|
|
917
|
+
|
|
918
|
+
---
|
|
919
|
+
|
|
920
|
+
## 15. Yararlı Kod Kalıpları
|
|
921
|
+
|
|
922
|
+
### 15.1 Post Atma (Tam Akış)
|
|
923
|
+
|
|
924
|
+
```typescript
|
|
925
|
+
// 1. Giriş yap
|
|
926
|
+
const session = await createSession(identifier, password);
|
|
927
|
+
|
|
928
|
+
// 2. Görsel varsa yükle
|
|
929
|
+
const blob = await uploadBlob(session.accessJwt, imageBuffer, "image/jpeg");
|
|
930
|
+
|
|
931
|
+
// 3. Facet'leri oluştur
|
|
932
|
+
const facets = parseFacets(text);
|
|
933
|
+
|
|
934
|
+
// 4. Record oluştur
|
|
935
|
+
const record = {
|
|
936
|
+
$type: "app.bsky.feed.post",
|
|
937
|
+
text: text,
|
|
938
|
+
createdAt: new Date().toISOString(),
|
|
939
|
+
langs: ["tr"],
|
|
940
|
+
facets: facets,
|
|
941
|
+
embed: blob ? {
|
|
942
|
+
$type: "app.bsky.embed.images",
|
|
943
|
+
images: [{ alt: "", image: blob, aspectRatio: { width: 1200, height: 630 } }]
|
|
944
|
+
} : undefined
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
// 5. Post gönder
|
|
948
|
+
const result = await createRecord(session, "app.bsky.feed.post", record);
|
|
949
|
+
const postUrl = `https://bsky.app/profile/${session.did}/post/${result.uri.split("/").pop()}`;
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
### 15.2 Thread (Zincirleme Post) Atma
|
|
953
|
+
|
|
954
|
+
```typescript
|
|
955
|
+
let previousUri: string | null = null;
|
|
956
|
+
let previousCid: string | null = null;
|
|
957
|
+
let rootUri: string | null = null;
|
|
958
|
+
let rootCid: string | null = null;
|
|
959
|
+
|
|
960
|
+
for (const text of threadTexts) {
|
|
961
|
+
const record: any = {
|
|
962
|
+
$type: "app.bsky.feed.post",
|
|
963
|
+
text: text,
|
|
964
|
+
createdAt: new Date().toISOString(),
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
if (previousUri) {
|
|
968
|
+
record.reply = {
|
|
969
|
+
root: { uri: rootUri, cid: rootCid },
|
|
970
|
+
parent: { uri: previousUri, cid: previousCid }
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
const result = await createRecord(session, "app.bsky.feed.post", record);
|
|
975
|
+
|
|
976
|
+
if (!rootUri) {
|
|
977
|
+
rootUri = result.uri;
|
|
978
|
+
rootCid = result.cid;
|
|
979
|
+
}
|
|
980
|
+
previousUri = result.uri;
|
|
981
|
+
previousCid = result.cid;
|
|
982
|
+
}
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
### 15.3 Post URL'sinden URI Elde Etme
|
|
986
|
+
|
|
987
|
+
```typescript
|
|
988
|
+
async function postUrlToAtUri(url: string): Promise<string> {
|
|
989
|
+
// https://bsky.app/profile/handle.bsky.social/post/3k...
|
|
990
|
+
const match = url.match(/\/profile\/([^/]+)\/post\/([^/]+)/);
|
|
991
|
+
if (!match) throw new Error("Geçersiz post URL'si");
|
|
992
|
+
|
|
993
|
+
const [, actor, rkey] = match;
|
|
994
|
+
|
|
995
|
+
// Handle ise DID'e çevir
|
|
996
|
+
let did = actor;
|
|
997
|
+
if (!actor.startsWith("did:")) {
|
|
998
|
+
const res = await fetch(`https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=${actor}`);
|
|
999
|
+
const data = await res.json();
|
|
1000
|
+
did = data.did;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
return `at://${did}/app.bsky.feed.post/${rkey}`;
|
|
1004
|
+
}
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
## 16. Limitler Özeti
|
|
1010
|
+
|
|
1011
|
+
| Limit | Değer |
|
|
1012
|
+
|-------|-------|
|
|
1013
|
+
| Post metin uzunluğu | 300 grapheme (karakter) |
|
|
1014
|
+
| Post başına görsel | 4 adet |
|
|
1015
|
+
| Görsel dosya boyutu | 1 MB |
|
|
1016
|
+
| Video dosya boyutu | 50 MB |
|
|
1017
|
+
| Video süresi | 60 saniye |
|
|
1018
|
+
| Bio (profil açıklaması) | 256 karakter |
|
|
1019
|
+
| Display name | 64 karakter |
|
|
1020
|
+
| Handle uzunluğu | 253 karakter |
|
|
1021
|
+
| Liste adı | 64 karakter |
|
|
1022
|
+
| Liste açıklaması | 300 karakter |
|
|
1023
|
+
| Rate limit | 5000 puan/saat |
|
|
1024
|
+
| Takip limiti | Teknik sınır yok, spam koruması var |
|
|
1025
|
+
| Günlük post limiti | Teknik sınır yok, rate limit dahilinde |
|
|
1026
|
+
| Alt text (görsel açıklama) | Teknik sınır yok |
|
|
1027
|
+
|
|
1028
|
+
---
|
|
1029
|
+
|
|
1030
|
+
## 17. Diğer Faydalı Endpoint'ler
|
|
1031
|
+
|
|
1032
|
+
### Profil Güncelleme
|
|
1033
|
+
```
|
|
1034
|
+
GET /xrpc/com.atproto.repo.getRecord?repo=<did>&collection=app.bsky.actor.profile&rkey=self
|
|
1035
|
+
PUT /xrpc/com.atproto.repo.putRecord (profil güncellemede putRecord kullanılır)
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
### Tercihler (Preferences)
|
|
1039
|
+
```
|
|
1040
|
+
GET /xrpc/app.bsky.actor.getPreferences
|
|
1041
|
+
POST /xrpc/app.bsky.actor.putPreferences
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
### Önerilen Kullanıcılar
|
|
1045
|
+
```
|
|
1046
|
+
GET /xrpc/app.bsky.actor.getSuggestions?limit=50
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
### Popüler Feed'ler
|
|
1050
|
+
```
|
|
1051
|
+
GET /xrpc/app.bsky.unspecced.getPopularFeedGenerators
|
|
1052
|
+
GET /xrpc/app.bsky.feed.getSuggestedFeeds
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
### Starter Pack
|
|
1056
|
+
```
|
|
1057
|
+
GET /xrpc/app.bsky.graph.getStarterPack?starterPack=at://did:plc:abc/app.bsky.graph.starterpack/xyz
|
|
1058
|
+
GET /xrpc/app.bsky.graph.getStarterPacks
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
---
|
|
1062
|
+
|
|
1063
|
+
## 18. Önemli Notlar ve İpuçları
|
|
1064
|
+
|
|
1065
|
+
1. **Tüm yazma işlemleri `createRecord`/`deleteRecord`/`putRecord` üzerinden yapılır.** Her şey (post, like, follow, block, list) birer AT Protocol kaydıdır.
|
|
1066
|
+
|
|
1067
|
+
2. **CID zorunluluğu:** Like ve repost gibi işlemlerde hedef postun hem `uri` hem `cid` değeri gerekir. CID almak için önce `getPosts` ile post detayını çekin.
|
|
1068
|
+
|
|
1069
|
+
3. **createdAt zorunludur.** Tüm kayıtlarda ISO 8601 formatında `createdAt` alanı bulunmalıdır.
|
|
1070
|
+
|
|
1071
|
+
4. **Facet byte offset hatası en sık yapılan hatadır.** Karakter index'i değil byte pozisyonu kullanılmalıdır. Türkçe karakterler ve emojiler byte offset'i kaydırır.
|
|
1072
|
+
|
|
1073
|
+
5. **Blob geçicidir.** Yüklenen görseller 1 saat içinde bir kayıtta referans verilmezse silinir. Önce görsel yükle, sonra hemen post oluştur.
|
|
1074
|
+
|
|
1075
|
+
6. **App Password kullanın.** Ana hesap şifresini API'de kullanmayın. Bluesky ayarlarından App Password oluşturun.
|
|
1076
|
+
|
|
1077
|
+
7. **Rate limit cömert ama dikkatli olun.** Özellikle toplu görsel yükleme hızla puan tüketir (her biri 25 puan). 200 görselde limit dolar.
|
|
1078
|
+
|
|
1079
|
+
8. **Bluesky API tamamen ücretsizdir.** Herhangi bir API anahtarı, geliştirici hesabı veya uygulama onayı gerekmez. createSession ile hemen başlayabilirsiniz.
|
|
1080
|
+
|
|
1081
|
+
9. **Thread oluştururken sıralama önemlidir.** Her yanıt bir öncekinin `uri` ve `cid` değerlerini bilmelidir. Sıralı (sequential) gönderim zorunludur.
|
|
1082
|
+
|
|
1083
|
+
10. **Silinen kayıtlar geri alınamaz.** `deleteRecord` kalıcıdır.
|