mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at thread-bug 203 lines 5.1 kB view raw
1import { 2 type $Typed, 3 AppBskyEmbedRecord, 4 AppBskyEmbedRecordWithMedia, 5 type AppBskyFeedDefs, 6 type AppBskyFeedPostgate, 7 AtUri, 8} from '@atproto/api' 9 10export const POSTGATE_COLLECTION = 'app.bsky.feed.postgate' 11 12export function createPostgateRecord( 13 postgate: Partial<AppBskyFeedPostgate.Record> & { 14 post: AppBskyFeedPostgate.Record['post'] 15 }, 16): AppBskyFeedPostgate.Record { 17 return { 18 $type: POSTGATE_COLLECTION, 19 createdAt: new Date().toISOString(), 20 post: postgate.post, 21 detachedEmbeddingUris: postgate.detachedEmbeddingUris || [], 22 embeddingRules: postgate.embeddingRules || [], 23 } 24} 25 26export function mergePostgateRecords( 27 prev: AppBskyFeedPostgate.Record, 28 next: Partial<AppBskyFeedPostgate.Record>, 29) { 30 const detachedEmbeddingUris = Array.from( 31 new Set([ 32 ...(prev.detachedEmbeddingUris || []), 33 ...(next.detachedEmbeddingUris || []), 34 ]), 35 ) 36 const embeddingRules = [ 37 ...(prev.embeddingRules || []), 38 ...(next.embeddingRules || []), 39 ].filter( 40 (rule, i, all) => all.findIndex(_rule => _rule.$type === rule.$type) === i, 41 ) 42 return createPostgateRecord({ 43 post: prev.post, 44 detachedEmbeddingUris, 45 embeddingRules, 46 }) 47} 48 49export function createEmbedViewDetachedRecord({ 50 uri, 51}: { 52 uri: string 53}): $Typed<AppBskyEmbedRecord.View> { 54 const record: $Typed<AppBskyEmbedRecord.ViewDetached> = { 55 $type: 'app.bsky.embed.record#viewDetached', 56 uri, 57 detached: true, 58 } 59 return { 60 $type: 'app.bsky.embed.record#view', 61 record, 62 } 63} 64 65export function createMaybeDetachedQuoteEmbed({ 66 post, 67 quote, 68 quoteUri, 69 detached, 70}: 71 | { 72 post: AppBskyFeedDefs.PostView 73 quote: AppBskyFeedDefs.PostView 74 quoteUri: undefined 75 detached: false 76 } 77 | { 78 post: AppBskyFeedDefs.PostView 79 quote: undefined 80 quoteUri: string 81 detached: true 82 }): AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined { 83 if (AppBskyEmbedRecord.isView(post.embed)) { 84 if (detached) { 85 return createEmbedViewDetachedRecord({uri: quoteUri}) 86 } else { 87 return createEmbedRecordView({post: quote}) 88 } 89 } else if (AppBskyEmbedRecordWithMedia.isView(post.embed)) { 90 if (detached) { 91 return { 92 ...post.embed, 93 record: createEmbedViewDetachedRecord({uri: quoteUri}), 94 } 95 } else { 96 return createEmbedRecordWithMediaView({post, quote}) 97 } 98 } 99} 100 101export function createEmbedViewRecordFromPost( 102 post: AppBskyFeedDefs.PostView, 103): $Typed<AppBskyEmbedRecord.ViewRecord> { 104 return { 105 $type: 'app.bsky.embed.record#viewRecord', 106 uri: post.uri, 107 cid: post.cid, 108 author: post.author, 109 value: post.record, 110 labels: post.labels, 111 replyCount: post.replyCount, 112 repostCount: post.repostCount, 113 likeCount: post.likeCount, 114 quoteCount: post.quoteCount, 115 indexedAt: post.indexedAt, 116 embeds: post.embed ? [post.embed] : [], 117 } 118} 119 120export function createEmbedRecordView({ 121 post, 122}: { 123 post: AppBskyFeedDefs.PostView 124}): AppBskyEmbedRecord.View { 125 return { 126 $type: 'app.bsky.embed.record#view', 127 record: createEmbedViewRecordFromPost(post), 128 } 129} 130 131export function createEmbedRecordWithMediaView({ 132 post, 133 quote, 134}: { 135 post: AppBskyFeedDefs.PostView 136 quote: AppBskyFeedDefs.PostView 137}): AppBskyEmbedRecordWithMedia.View | undefined { 138 if (!AppBskyEmbedRecordWithMedia.isView(post.embed)) return 139 return { 140 ...(post.embed || {}), 141 record: { 142 record: createEmbedViewRecordFromPost(quote), 143 }, 144 } 145} 146 147export function getMaybeDetachedQuoteEmbed({ 148 viewerDid, 149 post, 150}: { 151 viewerDid: string 152 post: AppBskyFeedDefs.PostView 153}) { 154 if (AppBskyEmbedRecord.isView(post.embed)) { 155 // detached 156 if (AppBskyEmbedRecord.isViewDetached(post.embed.record)) { 157 const urip = new AtUri(post.embed.record.uri) 158 return { 159 embed: post.embed, 160 uri: urip.toString(), 161 isOwnedByViewer: urip.host === viewerDid, 162 isDetached: true, 163 } 164 } 165 166 // post 167 if (AppBskyEmbedRecord.isViewRecord(post.embed.record)) { 168 const urip = new AtUri(post.embed.record.uri) 169 return { 170 embed: post.embed, 171 uri: urip.toString(), 172 isOwnedByViewer: urip.host === viewerDid, 173 isDetached: false, 174 } 175 } 176 } else if (AppBskyEmbedRecordWithMedia.isView(post.embed)) { 177 // detached 178 if (AppBskyEmbedRecord.isViewDetached(post.embed.record.record)) { 179 const urip = new AtUri(post.embed.record.record.uri) 180 return { 181 embed: post.embed, 182 uri: urip.toString(), 183 isOwnedByViewer: urip.host === viewerDid, 184 isDetached: true, 185 } 186 } 187 188 // post 189 if (AppBskyEmbedRecord.isViewRecord(post.embed.record.record)) { 190 const urip = new AtUri(post.embed.record.record.uri) 191 return { 192 embed: post.embed, 193 uri: urip.toString(), 194 isOwnedByViewer: urip.host === viewerDid, 195 isDetached: false, 196 } 197 } 198 } 199} 200 201export const embeddingRules = { 202 disableRule: {$type: 'app.bsky.feed.postgate#disableRule'}, 203}