@atproto/bsky 0.0.76 → 0.0.78

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.
Files changed (226) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/api/app/bsky/feed/getActorLikes.js +2 -2
  3. package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
  4. package/dist/api/app/bsky/feed/getLikes.js +6 -6
  5. package/dist/api/app/bsky/feed/getLikes.js.map +1 -1
  6. package/dist/api/app/bsky/feed/getListFeed.d.ts.map +1 -1
  7. package/dist/api/app/bsky/feed/getListFeed.js +19 -3
  8. package/dist/api/app/bsky/feed/getListFeed.js.map +1 -1
  9. package/dist/api/app/bsky/feed/getPosts.js +4 -4
  10. package/dist/api/app/bsky/feed/getPosts.js.map +1 -1
  11. package/dist/api/app/bsky/feed/getQuotes.d.ts +4 -0
  12. package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -0
  13. package/dist/api/app/bsky/feed/getQuotes.js +67 -0
  14. package/dist/api/app/bsky/feed/getQuotes.js.map +1 -0
  15. package/dist/api/app/bsky/feed/getRepostedBy.js +6 -6
  16. package/dist/api/app/bsky/feed/getRepostedBy.js.map +1 -1
  17. package/dist/api/app/bsky/feed/searchPosts.js +4 -4
  18. package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
  19. package/dist/api/app/bsky/graph/getFollowers.js +8 -8
  20. package/dist/api/app/bsky/graph/getFollowers.js.map +1 -1
  21. package/dist/api/app/bsky/graph/getList.js +7 -7
  22. package/dist/api/app/bsky/graph/getList.js.map +1 -1
  23. package/dist/api/app/bsky/notification/listNotifications.d.ts.map +1 -1
  24. package/dist/api/app/bsky/notification/listNotifications.js +29 -8
  25. package/dist/api/app/bsky/notification/listNotifications.js.map +1 -1
  26. package/dist/api/index.d.ts.map +1 -1
  27. package/dist/api/index.js +2 -0
  28. package/dist/api/index.js.map +1 -1
  29. package/dist/data-plane/server/db/database-schema.d.ts +4 -2
  30. package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
  31. package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.d.ts +4 -0
  32. package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.d.ts.map +1 -0
  33. package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.js +15 -0
  34. package/dist/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.js.map +1 -0
  35. package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.d.ts +4 -0
  36. package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.d.ts.map +1 -0
  37. package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.js +30 -0
  38. package/dist/data-plane/server/db/migrations/20240723T220703655Z-quotes.js.map +1 -0
  39. package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.d.ts +4 -0
  40. package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.d.ts.map +1 -0
  41. package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.js +20 -0
  42. package/dist/data-plane/server/db/migrations/20240801T193939827Z-post-gate.js.map +1 -0
  43. package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.d.ts +4 -0
  44. package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.d.ts.map +1 -0
  45. package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.js +28 -0
  46. package/dist/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.js.map +1 -0
  47. package/dist/data-plane/server/db/migrations/index.d.ts +4 -0
  48. package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
  49. package/dist/data-plane/server/db/migrations/index.js +5 -1
  50. package/dist/data-plane/server/db/migrations/index.js.map +1 -1
  51. package/dist/data-plane/server/db/tables/post-agg.d.ts +1 -0
  52. package/dist/data-plane/server/db/tables/post-agg.d.ts.map +1 -1
  53. package/dist/data-plane/server/db/tables/post-gate.d.ts +14 -0
  54. package/dist/data-plane/server/db/tables/post-gate.d.ts.map +1 -0
  55. package/dist/data-plane/server/db/tables/post-gate.js +4 -0
  56. package/dist/data-plane/server/db/tables/post-gate.js.map +1 -0
  57. package/dist/data-plane/server/db/tables/post.d.ts +3 -0
  58. package/dist/data-plane/server/db/tables/post.d.ts.map +1 -1
  59. package/dist/data-plane/server/db/tables/quote.d.ts +16 -0
  60. package/dist/data-plane/server/db/tables/quote.d.ts.map +1 -0
  61. package/dist/data-plane/server/db/tables/quote.js +4 -0
  62. package/dist/data-plane/server/db/tables/quote.js.map +1 -0
  63. package/dist/data-plane/server/indexing/index.d.ts +2 -0
  64. package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
  65. package/dist/data-plane/server/indexing/index.js +6 -0
  66. package/dist/data-plane/server/indexing/index.js.map +1 -1
  67. package/dist/data-plane/server/indexing/plugins/post-gate.d.ts +10 -0
  68. package/dist/data-plane/server/indexing/plugins/post-gate.d.ts.map +1 -0
  69. package/dist/data-plane/server/indexing/plugins/post-gate.js +101 -0
  70. package/dist/data-plane/server/indexing/plugins/post-gate.js.map +1 -0
  71. package/dist/data-plane/server/indexing/plugins/post.d.ts +2 -0
  72. package/dist/data-plane/server/indexing/plugins/post.d.ts.map +1 -1
  73. package/dist/data-plane/server/indexing/plugins/post.js +122 -15
  74. package/dist/data-plane/server/indexing/plugins/post.js.map +1 -1
  75. package/dist/data-plane/server/indexing/plugins/thread-gate.d.ts.map +1 -1
  76. package/dist/data-plane/server/indexing/plugins/thread-gate.js +12 -0
  77. package/dist/data-plane/server/indexing/plugins/thread-gate.js.map +1 -1
  78. package/dist/data-plane/server/routes/index.d.ts.map +1 -1
  79. package/dist/data-plane/server/routes/index.js +2 -0
  80. package/dist/data-plane/server/routes/index.js.map +1 -1
  81. package/dist/data-plane/server/routes/interactions.d.ts.map +1 -1
  82. package/dist/data-plane/server/routes/interactions.js +2 -1
  83. package/dist/data-plane/server/routes/interactions.js.map +1 -1
  84. package/dist/data-plane/server/routes/quotes.d.ts +6 -0
  85. package/dist/data-plane/server/routes/quotes.d.ts.map +1 -0
  86. package/dist/data-plane/server/routes/quotes.js +27 -0
  87. package/dist/data-plane/server/routes/quotes.js.map +1 -0
  88. package/dist/data-plane/server/routes/records.d.ts.map +1 -1
  89. package/dist/data-plane/server/routes/records.js +11 -1
  90. package/dist/data-plane/server/routes/records.js.map +1 -1
  91. package/dist/data-plane/server/util.d.ts +6 -7
  92. package/dist/data-plane/server/util.d.ts.map +1 -1
  93. package/dist/data-plane/server/util.js +1 -9
  94. package/dist/data-plane/server/util.js.map +1 -1
  95. package/dist/hydration/feed.d.ts +10 -0
  96. package/dist/hydration/feed.d.ts.map +1 -1
  97. package/dist/hydration/feed.js +31 -7
  98. package/dist/hydration/feed.js.map +1 -1
  99. package/dist/hydration/hydrator.d.ts +4 -2
  100. package/dist/hydration/hydrator.d.ts.map +1 -1
  101. package/dist/hydration/hydrator.js +89 -34
  102. package/dist/hydration/hydrator.js.map +1 -1
  103. package/dist/hydration/util.d.ts +0 -1
  104. package/dist/hydration/util.d.ts.map +1 -1
  105. package/dist/hydration/util.js +1 -5
  106. package/dist/hydration/util.js.map +1 -1
  107. package/dist/lexicon/index.d.ts +2 -0
  108. package/dist/lexicon/index.d.ts.map +1 -1
  109. package/dist/lexicon/index.js +4 -0
  110. package/dist/lexicon/index.js.map +1 -1
  111. package/dist/lexicon/lexicons.d.ts +144 -0
  112. package/dist/lexicon/lexicons.d.ts.map +1 -1
  113. package/dist/lexicon/lexicons.js +146 -1
  114. package/dist/lexicon/lexicons.js.map +1 -1
  115. package/dist/lexicon/types/app/bsky/embed/record.d.ts +9 -1
  116. package/dist/lexicon/types/app/bsky/embed/record.d.ts.map +1 -1
  117. package/dist/lexicon/types/app/bsky/embed/record.js +11 -1
  118. package/dist/lexicon/types/app/bsky/embed/record.js.map +1 -1
  119. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +2 -0
  120. package/dist/lexicon/types/app/bsky/feed/defs.d.ts.map +1 -1
  121. package/dist/lexicon/types/app/bsky/feed/defs.js.map +1 -1
  122. package/dist/lexicon/types/app/bsky/feed/getQuotes.d.ts +44 -0
  123. package/dist/lexicon/types/app/bsky/feed/getQuotes.d.ts.map +1 -0
  124. package/dist/lexicon/types/app/bsky/feed/getQuotes.js +3 -0
  125. package/dist/lexicon/types/app/bsky/feed/getQuotes.js.map +1 -0
  126. package/dist/lexicon/types/app/bsky/feed/postgate.d.ts +25 -0
  127. package/dist/lexicon/types/app/bsky/feed/postgate.d.ts.map +1 -0
  128. package/dist/lexicon/types/app/bsky/feed/postgate.js +27 -0
  129. package/dist/lexicon/types/app/bsky/feed/postgate.js.map +1 -0
  130. package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts +2 -0
  131. package/dist/lexicon/types/app/bsky/feed/threadgate.d.ts.map +1 -1
  132. package/dist/lexicon/types/app/bsky/feed/threadgate.js.map +1 -1
  133. package/dist/proto/bsky_connect.d.ts +30 -1
  134. package/dist/proto/bsky_connect.d.ts.map +1 -1
  135. package/dist/proto/bsky_connect.js +29 -0
  136. package/dist/proto/bsky_connect.js.map +1 -1
  137. package/dist/proto/bsky_pb.d.ts +135 -1
  138. package/dist/proto/bsky_pb.d.ts.map +1 -1
  139. package/dist/proto/bsky_pb.js +425 -5
  140. package/dist/proto/bsky_pb.js.map +1 -1
  141. package/dist/util/uris.d.ts +12 -0
  142. package/dist/util/uris.d.ts.map +1 -0
  143. package/dist/util/uris.js +34 -0
  144. package/dist/util/uris.js.map +1 -0
  145. package/dist/views/index.d.ts +8 -2
  146. package/dist/views/index.d.ts.map +1 -1
  147. package/dist/views/index.js +84 -39
  148. package/dist/views/index.js.map +1 -1
  149. package/dist/views/types.d.ts +1 -1
  150. package/dist/views/types.d.ts.map +1 -1
  151. package/dist/views/types.js.map +1 -1
  152. package/dist/views/util.d.ts +11 -1
  153. package/dist/views/util.d.ts.map +1 -1
  154. package/dist/views/util.js +19 -8
  155. package/dist/views/util.js.map +1 -1
  156. package/package.json +4 -4
  157. package/proto/bsky.proto +42 -2
  158. package/src/api/app/bsky/feed/getActorLikes.ts +1 -1
  159. package/src/api/app/bsky/feed/getLikes.ts +1 -1
  160. package/src/api/app/bsky/feed/getListFeed.ts +30 -3
  161. package/src/api/app/bsky/feed/getPosts.ts +1 -1
  162. package/src/api/app/bsky/feed/getQuotes.ts +108 -0
  163. package/src/api/app/bsky/feed/getRepostedBy.ts +1 -1
  164. package/src/api/app/bsky/feed/searchPosts.ts +1 -1
  165. package/src/api/app/bsky/graph/getFollowers.ts +1 -1
  166. package/src/api/app/bsky/graph/getList.ts +5 -5
  167. package/src/api/app/bsky/notification/listNotifications.ts +32 -6
  168. package/src/api/index.ts +2 -0
  169. package/src/data-plane/server/db/database-schema.ts +7 -3
  170. package/src/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.ts +12 -0
  171. package/src/data-plane/server/db/migrations/20240723T220703655Z-quotes.ts +28 -0
  172. package/src/data-plane/server/db/migrations/20240801T193939827Z-post-gate.ts +17 -0
  173. package/src/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.ts +25 -0
  174. package/src/data-plane/server/db/migrations/index.ts +4 -0
  175. package/src/data-plane/server/db/tables/post-agg.ts +1 -0
  176. package/src/data-plane/server/db/tables/post-gate.ts +12 -0
  177. package/src/data-plane/server/db/tables/post.ts +3 -0
  178. package/src/data-plane/server/db/tables/quote.ts +15 -0
  179. package/src/data-plane/server/indexing/index.ts +7 -0
  180. package/src/data-plane/server/indexing/plugins/post-gate.ts +104 -0
  181. package/src/data-plane/server/indexing/plugins/post.ts +151 -16
  182. package/src/data-plane/server/indexing/plugins/thread-gate.ts +12 -0
  183. package/src/data-plane/server/routes/index.ts +2 -0
  184. package/src/data-plane/server/routes/interactions.ts +2 -1
  185. package/src/data-plane/server/routes/quotes.ts +32 -0
  186. package/src/data-plane/server/routes/records.ts +11 -1
  187. package/src/data-plane/server/util.ts +0 -8
  188. package/src/hydration/feed.ts +58 -12
  189. package/src/hydration/hydrator.ts +94 -22
  190. package/src/hydration/util.ts +0 -4
  191. package/src/lexicon/index.ts +12 -0
  192. package/src/lexicon/lexicons.ts +149 -1
  193. package/src/lexicon/types/app/bsky/embed/record.ts +20 -0
  194. package/src/lexicon/types/app/bsky/feed/defs.ts +2 -0
  195. package/src/lexicon/types/app/bsky/feed/getQuotes.ts +54 -0
  196. package/src/lexicon/types/app/bsky/feed/postgate.ts +47 -0
  197. package/src/lexicon/types/app/bsky/feed/threadgate.ts +2 -0
  198. package/src/proto/bsky_connect.ts +35 -0
  199. package/src/proto/bsky_pb.ts +424 -1
  200. package/src/util/uris.ts +31 -0
  201. package/src/views/index.ts +91 -35
  202. package/src/views/types.ts +1 -0
  203. package/src/views/util.ts +37 -7
  204. package/tests/__snapshots__/feed-generation.test.ts.snap +42 -0
  205. package/tests/data-plane/__snapshots__/indexing.test.ts.snap +20 -0
  206. package/tests/data-plane/indexing.test.ts +1 -0
  207. package/tests/postgates.test.ts +186 -0
  208. package/tests/seed/feed-hidden-replies.ts +62 -0
  209. package/tests/seed/postgates.ts +56 -0
  210. package/tests/views/__snapshots__/author-feed.test.ts.snap +65 -0
  211. package/tests/views/__snapshots__/block-lists.test.ts.snap +7 -0
  212. package/tests/views/__snapshots__/blocks.test.ts.snap +11 -0
  213. package/tests/views/__snapshots__/list-feed.test.ts.snap +24 -0
  214. package/tests/views/__snapshots__/lists.test.ts.snap +185 -1
  215. package/tests/views/__snapshots__/mute-lists.test.ts.snap +8 -0
  216. package/tests/views/__snapshots__/mutes.test.ts.snap +6 -0
  217. package/tests/views/__snapshots__/posts.test.ts.snap +15 -0
  218. package/tests/views/__snapshots__/quotes.test.ts.snap +402 -0
  219. package/tests/views/__snapshots__/thread.test.ts.snap +50 -0
  220. package/tests/views/__snapshots__/timeline.test.ts.snap +191 -0
  221. package/tests/views/author-feed.test.ts +3 -9
  222. package/tests/views/feed-hidden-replies.test.ts +246 -0
  223. package/tests/views/feed-view-post.test.ts +501 -0
  224. package/tests/views/list-feed.test.ts +12 -0
  225. package/tests/views/lists.test.ts +83 -18
  226. package/tests/views/quotes.test.ts +105 -0
@@ -28,13 +28,15 @@ import {
28
28
  StarterPackView,
29
29
  StarterPackViewBasic,
30
30
  } from '../lexicon/types/app/bsky/graph/defs'
31
- import { creatorFromUri, parseThreadGate, cidFromBlobJson } from './util'
31
+ import { parseThreadGate, parsePostgate, cidFromBlobJson } from './util'
32
+ import { uriToDid as creatorFromUri } from '../util/uris'
32
33
  import { isListRule } from '../lexicon/types/app/bsky/feed/threadgate'
33
34
  import { isSelfLabels } from '../lexicon/types/com/atproto/label/defs'
34
35
  import {
35
36
  Embed,
36
37
  EmbedBlocked,
37
38
  EmbedNotFound,
39
+ EmbedDetached,
38
40
  EmbedView,
39
41
  ExternalEmbed,
40
42
  ExternalEmbedView,
@@ -61,6 +63,7 @@ import {
61
63
  LabelerViewDetailed,
62
64
  } from '../lexicon/types/app/bsky/labeler/defs'
63
65
  import { Notification } from '../proto/bsky_pb'
66
+ import { postUriToThreadgateUri, postUriToPostgateUri } from '../util/uris'
64
67
 
65
68
  export class Views {
66
69
  constructor(public imgUriBuilder: ImageUriBuilder) {}
@@ -104,6 +107,16 @@ export class Views {
104
107
  return actor.muted || !!actor.mutedByList
105
108
  }
106
109
 
110
+ replyIsHiddenByThreadgate(
111
+ replyUri: string,
112
+ rootPostUri: string,
113
+ state: HydrationState,
114
+ ) {
115
+ const threadgateUri = postUriToThreadgateUri(rootPostUri)
116
+ const threadgate = state.threadgates?.get(threadgateUri)
117
+ return !!threadgate?.record?.hiddenReplies?.includes(replyUri)
118
+ }
119
+
107
120
  profileDetailed(
108
121
  did: string,
109
122
  state: HydrationState,
@@ -291,7 +304,7 @@ export class Views {
291
304
  // ------------
292
305
 
293
306
  list(uri: string, state: HydrationState): ListView | undefined {
294
- const creatorDid = new AtUri(uri).hostname
307
+ const creatorDid = creatorFromUri(uri)
295
308
  const list = state.lists?.get(uri)
296
309
  if (!list) return
297
310
  const creator = this.profile(creatorDid, state)
@@ -316,7 +329,7 @@ export class Views {
316
329
  const listAgg = state.listAggs?.get(uri)
317
330
  const listViewer = state.listViewers?.get(uri)
318
331
  const labels = state.labels?.getBySubject(uri) ?? []
319
- const creator = new AtUri(uri).hostname
332
+ const creator = creatorFromUri(uri)
320
333
  return {
321
334
  uri,
322
335
  cid: list.cid,
@@ -399,7 +412,7 @@ export class Views {
399
412
  const { uri, cid, record } = details
400
413
  if (!uri || !cid || !record) return []
401
414
  if (!isSelfLabels(record.labels)) return []
402
- const src = new AtUri(uri).host // record creator
415
+ const src = creatorFromUri(uri) // record creator
403
416
  const cts =
404
417
  typeof record.createdAt === 'string'
405
418
  ? normalizeDatetimeAlways(record.createdAt)
@@ -529,7 +542,7 @@ export class Views {
529
542
  }
530
543
  }
531
544
 
532
- threadGate(uri: string, state: HydrationState): ThreadgateView | undefined {
545
+ threadgate(uri: string, state: HydrationState): ThreadgateView | undefined {
533
546
  const gate = state.threadgates?.get(uri)
534
547
  if (!gate) return
535
548
  return {
@@ -552,11 +565,7 @@ export class Views {
552
565
  if (!author) return
553
566
  const aggs = state.postAggs?.get(uri)
554
567
  const viewer = state.postViewers?.get(uri)
555
- const gateUri = AtUri.make(
556
- authorDid,
557
- ids.AppBskyFeedThreadgate,
558
- parsedUri.rkey,
559
- ).toString()
568
+ const threadgateUri = postUriToThreadgateUri(uri)
560
569
  const labels = [
561
570
  ...(state.labels?.getBySubject(uri) ?? []),
562
571
  ...this.selfLabels({
@@ -577,6 +586,7 @@ export class Views {
577
586
  replyCount: aggs?.replies ?? 0,
578
587
  repostCount: aggs?.reposts ?? 0,
579
588
  likeCount: aggs?.likes ?? 0,
589
+ quoteCount: aggs?.quotes ?? 0,
580
590
  indexedAt: post.sortedAt.toISOString(),
581
591
  viewer: viewer
582
592
  ? {
@@ -584,11 +594,12 @@ export class Views {
584
594
  like: viewer.like,
585
595
  threadMuted: viewer.threadMuted,
586
596
  replyDisabled: this.userReplyDisabled(uri, state),
597
+ embeddingDisabled: this.userPostEmbeddingDisabled(uri, state),
587
598
  }
588
599
  : undefined,
589
600
  labels,
590
601
  threadgate: !post.record.reply // only hydrate gate on root post
591
- ? this.threadGate(gateUri, state)
602
+ ? this.threadgate(threadgateUri, state)
592
603
  : undefined,
593
604
  }
594
605
  }
@@ -608,12 +619,13 @@ export class Views {
608
619
  }
609
620
  const post = this.post(item.post.uri, state)
610
621
  if (!post) return
622
+ const reply = !postInfo?.violatesThreadGate
623
+ ? this.replyRef(item.post.uri, state)
624
+ : undefined
611
625
  return {
612
626
  post,
613
627
  reason,
614
- reply: !postInfo?.violatesThreadGate
615
- ? this.replyRef(item.post.uri, state)
616
- : undefined,
628
+ reply,
617
629
  }
618
630
  }
619
631
 
@@ -622,15 +634,16 @@ export class Views {
622
634
  if (!postRecord?.reply) return
623
635
  let root = this.maybePost(postRecord.reply.root.uri, state)
624
636
  let parent = this.maybePost(postRecord.reply.parent.uri, state)
625
- if (
626
- !state.ctx?.include3pBlocks &&
627
- state.postBlocks?.get(uri)?.reply &&
628
- isPostView(parent)
629
- ) {
630
- parent = this.blockedPost(parent.uri, parent.author.did, state)
631
- // in a reply to the root of a thread, parent and root are the same post.
632
- if (root.uri === parent.uri) {
633
- root = parent
637
+ if (!state.ctx?.include3pBlocks) {
638
+ const childBlocks = state.postBlocks?.get(uri)
639
+ const parentBlocks = state.postBlocks?.get(parent.uri)
640
+ // if child blocks parent, block parent
641
+ if (isPostView(parent) && childBlocks?.parent) {
642
+ parent = this.blockedPost(parent.uri, parent.author.did, state)
643
+ }
644
+ // if child or parent blocks root, block root
645
+ if (isPostView(root) && (childBlocks?.root || parentBlocks?.root)) {
646
+ root = this.blockedPost(root.uri, root.author.did, state)
634
647
  }
635
648
  }
636
649
  let grandparentAuthor: ProfileViewBasic | undefined
@@ -755,7 +768,10 @@ export class Views {
755
768
  if (height < 1) return undefined
756
769
  const parentUri = state.posts?.get(childUri)?.record.reply?.parent.uri
757
770
  if (!parentUri) return undefined
758
- if (!state.ctx?.include3pBlocks && state.postBlocks?.get(childUri)?.reply) {
771
+ if (
772
+ !state.ctx?.include3pBlocks &&
773
+ state.postBlocks?.get(childUri)?.parent
774
+ ) {
759
775
  return this.blockedPost(parentUri, creatorFromUri(parentUri), state)
760
776
  }
761
777
  const post = this.post(parentUri, state)
@@ -786,7 +802,7 @@ export class Views {
786
802
  if (postInfo?.violatesThreadGate) {
787
803
  return undefined
788
804
  }
789
- if (!state.ctx?.include3pBlocks && state.postBlocks?.get(uri)?.reply) {
805
+ if (!state.ctx?.include3pBlocks && state.postBlocks?.get(uri)?.parent) {
790
806
  return undefined
791
807
  }
792
808
  const post = this.post(uri, state)
@@ -887,6 +903,17 @@ export class Views {
887
903
  }
888
904
  }
889
905
 
906
+ embedDetached(uri: string): { $type: string; record: EmbedDetached } {
907
+ return {
908
+ $type: 'app.bsky.embed.record#view',
909
+ record: {
910
+ $type: 'app.bsky.embed.record#viewDetached',
911
+ uri,
912
+ detached: true,
913
+ },
914
+ }
915
+ }
916
+
890
917
  embedBlocked(
891
918
  uri: string,
892
919
  state: HydrationState,
@@ -923,6 +950,7 @@ export class Views {
923
950
  likeCount: postView.likeCount,
924
951
  replyCount: postView.replyCount,
925
952
  repostCount: postView.repostCount,
953
+ quoteCount: postView.quoteCount,
926
954
  indexedAt: postView.indexedAt,
927
955
  embeds: depth > 1 ? undefined : postView.embed ? [postView.embed] : [],
928
956
  }
@@ -944,9 +972,19 @@ export class Views {
944
972
  return this.embedBlocked(uri, state)
945
973
  }
946
974
 
975
+ const post = state.posts?.get(postUri)
976
+ if (post?.violatesEmbeddingRules) {
977
+ return this.embedDetached(uri)
978
+ }
979
+
947
980
  if (parsedUri.collection === ids.AppBskyFeedPost) {
948
981
  const view = this.embedPostView(uri, state, depth)
949
982
  if (!view) return this.embedNotFound(uri)
983
+ const postgateRecordUri = postUriToPostgateUri(parsedUri.toString())
984
+ const postgate = state.postgates?.get(postgateRecordUri)
985
+ if (postgate?.record?.detachedEmbeddingUris?.includes(postUri)) {
986
+ return this.embedDetached(uri)
987
+ }
950
988
  return this.recordEmbedWrapper(view, withTypeTag)
951
989
  } else if (parsedUri.collection === ids.AppBskyFeedGenerator) {
952
990
  const view = this.feedGenerator(uri, state)
@@ -1010,13 +1048,15 @@ export class Views {
1010
1048
  return true
1011
1049
  }
1012
1050
  const rootUriStr: string = post?.record.reply?.root.uri ?? uri
1013
- const gate = state.threadgates?.get(postToGateUri(rootUriStr))?.record
1051
+ const gate = state.threadgates?.get(
1052
+ postUriToThreadgateUri(rootUriStr),
1053
+ )?.record
1014
1054
  const viewer = state.ctx?.viewer
1015
1055
  if (!gate || !viewer) {
1016
1056
  return undefined
1017
1057
  }
1018
1058
  const rootPost = state.posts?.get(rootUriStr)?.record
1019
- const ownerDid = new AtUri(rootUriStr).hostname
1059
+ const ownerDid = creatorFromUri(rootUriStr)
1020
1060
  const {
1021
1061
  canReply,
1022
1062
  allowFollowing,
@@ -1037,6 +1077,30 @@ export class Views {
1037
1077
  return true
1038
1078
  }
1039
1079
 
1080
+ userPostEmbeddingDisabled(
1081
+ uri: string,
1082
+ state: HydrationState,
1083
+ ): boolean | undefined {
1084
+ const post = state.posts?.get(uri)
1085
+ if (!post) {
1086
+ return true
1087
+ }
1088
+ const postgateRecordUri = postUriToPostgateUri(uri)
1089
+ const gate = state.postgates?.get(postgateRecordUri)?.record
1090
+ const viewerDid = state.ctx?.viewer ?? undefined
1091
+ const {
1092
+ embeddingRules: { canEmbed },
1093
+ } = parsePostgate({
1094
+ gate,
1095
+ viewerDid,
1096
+ authorDid: creatorFromUri(uri),
1097
+ })
1098
+ if (canEmbed) {
1099
+ return false
1100
+ }
1101
+ return true
1102
+ }
1103
+
1040
1104
  notification(
1041
1105
  notif: Notification,
1042
1106
  lastSeenAt: string | undefined,
@@ -1093,14 +1157,6 @@ export class Views {
1093
1157
  }
1094
1158
  }
1095
1159
 
1096
- const postToGateUri = (uri: string) => {
1097
- const aturi = new AtUri(uri)
1098
- if (aturi.collection === ids.AppBskyFeedPost) {
1099
- aturi.collection = ids.AppBskyFeedThreadgate
1100
- }
1101
- return aturi.toString()
1102
- }
1103
-
1104
1160
  const getRootUri = (uri: string, post: Post): string => {
1105
1161
  return post.record.reply?.root.uri ?? uri
1106
1162
  }
@@ -39,6 +39,7 @@ export type {
39
39
  View as RecordEmbedView,
40
40
  ViewBlocked as EmbedBlocked,
41
41
  ViewNotFound as EmbedNotFound,
42
+ ViewDetached as EmbedDetached,
42
43
  ViewRecord as PostEmbedView,
43
44
  } from '../lexicon/types/app/bsky/embed/record'
44
45
  export { isMain as isRecordEmbed } from '../lexicon/types/app/bsky/embed/record'
package/src/views/util.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { AtUri } from '@atproto/syntax'
2
1
  import { BlobRef } from '@atproto/lexicon'
3
2
  import { Record as PostRecord } from '../lexicon/types/app/bsky/feed/post'
4
3
  import {
@@ -7,12 +6,12 @@ import {
7
6
  isListRule,
8
7
  isMentionRule,
9
8
  } from '../lexicon/types/app/bsky/feed/threadgate'
9
+ import {
10
+ Record as PostgateRecord,
11
+ isDisableRule as isPostgateDisableRule,
12
+ } from '../lexicon/types/app/bsky/feed/postgate'
10
13
  import { isMention } from '../lexicon/types/app/bsky/richtext/facet'
11
14
 
12
- export const creatorFromUri = (uri: string): string => {
13
- return new AtUri(uri).hostname
14
- }
15
-
16
15
  export const parseThreadGate = (
17
16
  replierDid: string,
18
17
  ownerDid: string,
@@ -27,8 +26,8 @@ export const parseThreadGate = (
27
26
  return { canReply: true }
28
27
  }
29
28
 
30
- const allowMentions = !!gate.allow.find(isMentionRule)
31
- const allowFollowing = !!gate.allow.find(isFollowingRule)
29
+ const allowMentions = gate.allow.some(isMentionRule)
30
+ const allowFollowing = gate.allow.some(isFollowingRule)
32
31
  const allowListUris = gate.allow?.filter(isListRule).map((item) => item.list)
33
32
 
34
33
  // check mentions first since it's quick and synchronous
@@ -62,3 +61,34 @@ export const cidFromBlobJson = (json: BlobRef) => {
62
61
  }
63
62
  return (json['cid'] ?? '') as string
64
63
  }
64
+
65
+ export const parsePostgate = ({
66
+ gate,
67
+ viewerDid,
68
+ authorDid,
69
+ }: {
70
+ gate: PostgateRecord | undefined
71
+ viewerDid: string | undefined
72
+ authorDid: string
73
+ }): ParsedPostgate => {
74
+ if (viewerDid === authorDid) {
75
+ return { embeddingRules: { canEmbed: true } }
76
+ }
77
+ // default state is unset, allow everyone
78
+ if (!gate || !gate.embeddingRules) {
79
+ return { embeddingRules: { canEmbed: true } }
80
+ }
81
+
82
+ const disabled = gate.embeddingRules.some(isPostgateDisableRule)
83
+ if (disabled) {
84
+ return { embeddingRules: { canEmbed: false } }
85
+ }
86
+
87
+ return { embeddingRules: { canEmbed: true } }
88
+ }
89
+
90
+ type ParsedPostgate = {
91
+ embeddingRules: {
92
+ canEmbed: boolean
93
+ }
94
+ }
@@ -26,6 +26,7 @@ Object {
26
26
  "indexedAt": "1970-01-01T00:00:00.000Z",
27
27
  "labels": Array [],
28
28
  "likeCount": 0,
29
+ "quoteCount": 0,
29
30
  "record": Object {
30
31
  "$type": "app.bsky.feed.post",
31
32
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -42,6 +43,7 @@ Object {
42
43
  "repostCount": 0,
43
44
  "uri": "record(0)",
44
45
  "viewer": Object {
46
+ "embeddingDisabled": false,
45
47
  "threadMuted": false,
46
48
  },
47
49
  }
@@ -73,6 +75,7 @@ Object {
73
75
  "indexedAt": "1970-01-01T00:00:00.000Z",
74
76
  "labels": Array [],
75
77
  "likeCount": 0,
78
+ "quoteCount": 0,
76
79
  "record": Object {
77
80
  "$type": "app.bsky.feed.post",
78
81
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -89,6 +92,7 @@ Object {
89
92
  "repostCount": 0,
90
93
  "uri": "record(0)",
91
94
  "viewer": Object {
95
+ "embeddingDisabled": false,
92
96
  "threadMuted": false,
93
97
  },
94
98
  }
@@ -160,6 +164,7 @@ Object {
160
164
  "indexedAt": "1970-01-01T00:00:00.000Z",
161
165
  "labels": Array [],
162
166
  "likeCount": 0,
167
+ "quoteCount": 0,
163
168
  "record": Object {
164
169
  "$type": "app.bsky.feed.post",
165
170
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -176,6 +181,7 @@ Object {
176
181
  "repostCount": 0,
177
182
  "uri": "record(0)",
178
183
  "viewer": Object {
184
+ "embeddingDisabled": false,
179
185
  "threadMuted": false,
180
186
  },
181
187
  }
@@ -249,6 +255,7 @@ Object {
249
255
  "indexedAt": "1970-01-01T00:00:00.000Z",
250
256
  "labels": Array [],
251
257
  "likeCount": 0,
258
+ "quoteCount": 0,
252
259
  "record": Object {
253
260
  "$type": "app.bsky.feed.post",
254
261
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -265,6 +272,7 @@ Object {
265
272
  "repostCount": 0,
266
273
  "uri": "record(0)",
267
274
  "viewer": Object {
275
+ "embeddingDisabled": false,
268
276
  "threadMuted": false,
269
277
  },
270
278
  }
@@ -531,6 +539,7 @@ Array [
531
539
  },
532
540
  ],
533
541
  "likeCount": 0,
542
+ "quoteCount": 0,
534
543
  "record": Object {
535
544
  "$type": "app.bsky.feed.post",
536
545
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -548,6 +557,7 @@ Array [
548
557
  "repostCount": 0,
549
558
  "uri": "record(0)",
550
559
  "viewer": Object {
560
+ "embeddingDisabled": false,
551
561
  "threadMuted": false,
552
562
  },
553
563
  },
@@ -573,6 +583,7 @@ Array [
573
583
  "indexedAt": "1970-01-01T00:00:00.000Z",
574
584
  "labels": Array [],
575
585
  "likeCount": 0,
586
+ "quoteCount": 1,
576
587
  "record": Object {
577
588
  "$type": "app.bsky.feed.post",
578
589
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -586,6 +597,7 @@ Array [
586
597
  "repostCount": 0,
587
598
  "uri": "record(2)",
588
599
  "viewer": Object {
600
+ "embeddingDisabled": false,
589
601
  "threadMuted": false,
590
602
  },
591
603
  },
@@ -644,6 +656,7 @@ Array [
644
656
  "indexedAt": "1970-01-01T00:00:00.000Z",
645
657
  "labels": Array [],
646
658
  "likeCount": 0,
659
+ "quoteCount": 1,
647
660
  "replyCount": 0,
648
661
  "repostCount": 0,
649
662
  "uri": "record(2)",
@@ -662,6 +675,7 @@ Array [
662
675
  "indexedAt": "1970-01-01T00:00:00.000Z",
663
676
  "labels": Array [],
664
677
  "likeCount": 2,
678
+ "quoteCount": 1,
665
679
  "record": Object {
666
680
  "$type": "app.bsky.feed.post",
667
681
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -707,6 +721,7 @@ Array [
707
721
  "repostCount": 0,
708
722
  "uri": "record(5)",
709
723
  "viewer": Object {
724
+ "embeddingDisabled": false,
710
725
  "like": "record(8)",
711
726
  "threadMuted": false,
712
727
  },
@@ -730,6 +745,7 @@ Array [
730
745
  "indexedAt": "1970-01-01T00:00:00.000Z",
731
746
  "labels": Array [],
732
747
  "likeCount": 0,
748
+ "quoteCount": 0,
733
749
  "record": Object {
734
750
  "$type": "app.bsky.feed.post",
735
751
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -749,6 +765,7 @@ Array [
749
765
  "repostCount": 0,
750
766
  "uri": "record(9)",
751
767
  "viewer": Object {
768
+ "embeddingDisabled": false,
752
769
  "threadMuted": false,
753
770
  },
754
771
  },
@@ -786,6 +803,7 @@ Array [
786
803
  "indexedAt": "1970-01-01T00:00:00.000Z",
787
804
  "labels": Array [],
788
805
  "likeCount": 3,
806
+ "quoteCount": 0,
789
807
  "record": Object {
790
808
  "$type": "app.bsky.feed.post",
791
809
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -795,6 +813,7 @@ Array [
795
813
  "repostCount": 1,
796
814
  "uri": "record(10)",
797
815
  "viewer": Object {
816
+ "embeddingDisabled": false,
798
817
  "threadMuted": false,
799
818
  },
800
819
  },
@@ -831,6 +850,7 @@ Array [
831
850
  "indexedAt": "1970-01-01T00:00:00.000Z",
832
851
  "labels": Array [],
833
852
  "likeCount": 3,
853
+ "quoteCount": 0,
834
854
  "record": Object {
835
855
  "$type": "app.bsky.feed.post",
836
856
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -840,6 +860,7 @@ Array [
840
860
  "repostCount": 1,
841
861
  "uri": "record(10)",
842
862
  "viewer": Object {
863
+ "embeddingDisabled": false,
843
864
  "threadMuted": false,
844
865
  },
845
866
  },
@@ -919,6 +940,7 @@ Array [
919
940
  "indexedAt": "1970-01-01T00:00:00.000Z",
920
941
  "labels": Array [],
921
942
  "likeCount": 0,
943
+ "quoteCount": 1,
922
944
  "replyCount": 0,
923
945
  "repostCount": 0,
924
946
  "uri": "record(2)",
@@ -938,6 +960,7 @@ Array [
938
960
  "indexedAt": "1970-01-01T00:00:00.000Z",
939
961
  "labels": Array [],
940
962
  "likeCount": 2,
963
+ "quoteCount": 1,
941
964
  "replyCount": 0,
942
965
  "repostCount": 0,
943
966
  "uri": "record(5)",
@@ -987,6 +1010,7 @@ Array [
987
1010
  "indexedAt": "1970-01-01T00:00:00.000Z",
988
1011
  "labels": Array [],
989
1012
  "likeCount": 0,
1013
+ "quoteCount": 1,
990
1014
  "record": Object {
991
1015
  "$type": "app.bsky.feed.post",
992
1016
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1017,6 +1041,7 @@ Array [
1017
1041
  "repostCount": 1,
1018
1042
  "uri": "record(11)",
1019
1043
  "viewer": Object {
1044
+ "embeddingDisabled": false,
1020
1045
  "threadMuted": false,
1021
1046
  },
1022
1047
  },
@@ -1079,6 +1104,7 @@ Array [
1079
1104
  },
1080
1105
  ],
1081
1106
  "likeCount": 0,
1107
+ "quoteCount": 0,
1082
1108
  "record": Object {
1083
1109
  "$type": "app.bsky.feed.post",
1084
1110
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1139,6 +1165,7 @@ Array [
1139
1165
  "indexedAt": "1970-01-01T00:00:00.000Z",
1140
1166
  "labels": Array [],
1141
1167
  "likeCount": 0,
1168
+ "quoteCount": 1,
1142
1169
  "replyCount": 0,
1143
1170
  "repostCount": 0,
1144
1171
  "uri": "record(3)",
@@ -1157,6 +1184,7 @@ Array [
1157
1184
  "indexedAt": "1970-01-01T00:00:00.000Z",
1158
1185
  "labels": Array [],
1159
1186
  "likeCount": 2,
1187
+ "quoteCount": 1,
1160
1188
  "record": Object {
1161
1189
  "$type": "app.bsky.feed.post",
1162
1190
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1215,6 +1243,7 @@ Array [
1215
1243
  "indexedAt": "1970-01-01T00:00:00.000Z",
1216
1244
  "labels": Array [],
1217
1245
  "likeCount": 0,
1246
+ "quoteCount": 0,
1218
1247
  "record": Object {
1219
1248
  "$type": "app.bsky.feed.post",
1220
1249
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1264,6 +1293,7 @@ Array [
1264
1293
  "indexedAt": "1970-01-01T00:00:00.000Z",
1265
1294
  "labels": Array [],
1266
1295
  "likeCount": 3,
1296
+ "quoteCount": 0,
1267
1297
  "record": Object {
1268
1298
  "$type": "app.bsky.feed.post",
1269
1299
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -1302,6 +1332,7 @@ Array [
1302
1332
  "indexedAt": "1970-01-01T00:00:00.000Z",
1303
1333
  "labels": Array [],
1304
1334
  "likeCount": 3,
1335
+ "quoteCount": 0,
1305
1336
  "record": Object {
1306
1337
  "$type": "app.bsky.feed.post",
1307
1338
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -1360,6 +1391,7 @@ Array [
1360
1391
  },
1361
1392
  ],
1362
1393
  "likeCount": 0,
1394
+ "quoteCount": 0,
1363
1395
  "record": Object {
1364
1396
  "$type": "app.bsky.feed.post",
1365
1397
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1377,6 +1409,7 @@ Array [
1377
1409
  "repostCount": 0,
1378
1410
  "uri": "record(0)",
1379
1411
  "viewer": Object {
1412
+ "embeddingDisabled": false,
1380
1413
  "threadMuted": false,
1381
1414
  },
1382
1415
  },
@@ -1435,6 +1468,7 @@ Array [
1435
1468
  "indexedAt": "1970-01-01T00:00:00.000Z",
1436
1469
  "labels": Array [],
1437
1470
  "likeCount": 0,
1471
+ "quoteCount": 1,
1438
1472
  "replyCount": 0,
1439
1473
  "repostCount": 0,
1440
1474
  "uri": "record(5)",
@@ -1453,6 +1487,7 @@ Array [
1453
1487
  "indexedAt": "1970-01-01T00:00:00.000Z",
1454
1488
  "labels": Array [],
1455
1489
  "likeCount": 2,
1490
+ "quoteCount": 1,
1456
1491
  "record": Object {
1457
1492
  "$type": "app.bsky.feed.post",
1458
1493
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1498,6 +1533,7 @@ Array [
1498
1533
  "repostCount": 0,
1499
1534
  "uri": "record(2)",
1500
1535
  "viewer": Object {
1536
+ "embeddingDisabled": false,
1501
1537
  "like": "record(8)",
1502
1538
  "threadMuted": false,
1503
1539
  },
@@ -1521,6 +1557,7 @@ Array [
1521
1557
  "indexedAt": "1970-01-01T00:00:00.000Z",
1522
1558
  "labels": Array [],
1523
1559
  "likeCount": 0,
1560
+ "quoteCount": 0,
1524
1561
  "record": Object {
1525
1562
  "$type": "app.bsky.feed.post",
1526
1563
  "createdAt": "1970-01-01T00:00:00.000Z",
@@ -1540,6 +1577,7 @@ Array [
1540
1577
  "repostCount": 0,
1541
1578
  "uri": "record(9)",
1542
1579
  "viewer": Object {
1580
+ "embeddingDisabled": false,
1543
1581
  "threadMuted": false,
1544
1582
  },
1545
1583
  },
@@ -1577,6 +1615,7 @@ Array [
1577
1615
  "indexedAt": "1970-01-01T00:00:00.000Z",
1578
1616
  "labels": Array [],
1579
1617
  "likeCount": 3,
1618
+ "quoteCount": 0,
1580
1619
  "record": Object {
1581
1620
  "$type": "app.bsky.feed.post",
1582
1621
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -1586,6 +1625,7 @@ Array [
1586
1625
  "repostCount": 1,
1587
1626
  "uri": "record(10)",
1588
1627
  "viewer": Object {
1628
+ "embeddingDisabled": false,
1589
1629
  "threadMuted": false,
1590
1630
  },
1591
1631
  },
@@ -1622,6 +1662,7 @@ Array [
1622
1662
  "indexedAt": "1970-01-01T00:00:00.000Z",
1623
1663
  "labels": Array [],
1624
1664
  "likeCount": 3,
1665
+ "quoteCount": 0,
1625
1666
  "record": Object {
1626
1667
  "$type": "app.bsky.feed.post",
1627
1668
  "createdAt": "1970-01-01T00:00:00.000000Z",
@@ -1631,6 +1672,7 @@ Array [
1631
1672
  "repostCount": 1,
1632
1673
  "uri": "record(10)",
1633
1674
  "viewer": Object {
1675
+ "embeddingDisabled": false,
1634
1676
  "threadMuted": false,
1635
1677
  },
1636
1678
  },