@atproto/bsky 0.1.7 → 0.2.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/CHANGELOG.md +44 -0
- package/dist/api/app/bsky/actor/getProfile.js +1 -1
- package/dist/api/app/bsky/actor/getProfile.js.map +1 -1
- package/dist/api/app/bsky/actor/getProfiles.js +1 -1
- package/dist/api/app/bsky/actor/getProfiles.js.map +1 -1
- package/dist/api/app/bsky/actor/getSuggestions.js +2 -2
- package/dist/api/app/bsky/actor/getSuggestions.js.map +1 -1
- package/dist/api/app/bsky/embed/getEmbedExternalView.d.ts.map +1 -1
- package/dist/api/app/bsky/embed/getEmbedExternalView.js +132 -53
- package/dist/api/app/bsky/embed/getEmbedExternalView.js.map +1 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getAuthorFeed.js +4 -2
- package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
- package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js +2 -2
- package/dist/api/app/bsky/graph/getSuggestedFollowsByActor.js.map +1 -1
- package/dist/api/app/bsky/notification/constants.d.ts +4 -1
- package/dist/api/app/bsky/notification/constants.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/constants.js +3 -0
- package/dist/api/app/bsky/notification/constants.js.map +1 -1
- package/dist/api/app/bsky/notification/getGroupedNotifications.js +19 -7
- package/dist/api/app/bsky/notification/getGroupedNotifications.js.map +1 -1
- package/dist/api/app/bsky/notification/grouping/spotlight.d.ts +1 -1
- package/dist/api/app/bsky/notification/grouping/spotlight.d.ts.map +1 -1
- package/dist/api/app/bsky/notification/grouping/spotlight.js +114 -80
- package/dist/api/app/bsky/notification/grouping/spotlight.js.map +1 -1
- package/dist/api/app/bsky/notification/listActivitySubscriptions.js +3 -2
- package/dist/api/app/bsky/notification/listActivitySubscriptions.js.map +1 -1
- package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.d.ts.map +1 -1
- package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.js +16 -148
- package/dist/api/app/bsky/unspecced/getAtmosphereExploreTab.js.map +1 -1
- package/dist/api/internal/bsky/actor/getProfiles.js +4 -1
- package/dist/api/internal/bsky/actor/getProfiles.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/data-plane/server/indexing/index.d.ts +3 -1
- package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/index.js +2 -0
- package/dist/data-plane/server/indexing/index.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile-link.d.ts +8 -0
- package/dist/data-plane/server/indexing/plugins/profile-link.d.ts.map +1 -0
- package/dist/data-plane/server/indexing/plugins/profile-link.js +30 -0
- package/dist/data-plane/server/indexing/plugins/profile-link.js.map +1 -0
- package/dist/data-plane/server/routes/records.d.ts.map +1 -1
- package/dist/data-plane/server/routes/records.js +1 -0
- package/dist/data-plane/server/routes/records.js.map +1 -1
- package/dist/hydration/actor.d.ts +4 -1
- package/dist/hydration/actor.d.ts.map +1 -1
- package/dist/hydration/actor.js +11 -0
- package/dist/hydration/actor.js.map +1 -1
- package/dist/hydration/external.d.ts +67 -64
- package/dist/hydration/external.d.ts.map +1 -1
- package/dist/hydration/external.js +79 -133
- package/dist/hydration/external.js.map +1 -1
- package/dist/hydration/hydrator.d.ts +53 -14
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +414 -105
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +24 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.js +13 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/link.d.ts +3 -0
- package/dist/lexicons/app/bsky/actor/link.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/actor/link.defs.d.ts +105 -0
- package/dist/lexicons/app/bsky/actor/link.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/actor/link.defs.js +34 -0
- package/dist/lexicons/app/bsky/actor/link.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/actor/link.js +6 -0
- package/dist/lexicons/app/bsky/actor/link.js.map +1 -0
- package/dist/lexicons/app/bsky/actor/profile.defs.d.ts +14 -0
- package/dist/lexicons/app/bsky/actor/profile.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.js +3 -0
- package/dist/lexicons/app/bsky/actor/profile.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/actor.d.ts +1 -0
- package/dist/lexicons/app/bsky/actor.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor.js +1 -0
- package/dist/lexicons/app/bsky/actor.js.map +1 -1
- package/dist/lexicons/app/bsky/authFullApp.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/authFullApp.defs.js +1 -0
- package/dist/lexicons/app/bsky/authFullApp.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/authManageProfile.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/authManageProfile.defs.js +1 -0
- package/dist/lexicons/app/bsky/authManageProfile.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/getEmbedExternalView.defs.d.ts +13 -3
- package/dist/lexicons/app/bsky/embed/getEmbedExternalView.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/getEmbedExternalView.defs.js +11 -3
- package/dist/lexicons/app/bsky/embed/getEmbedExternalView.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/notification/getGroupedNotifications.defs.d.ts +62 -3
- package/dist/lexicons/app/bsky/notification/getGroupedNotifications.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/notification/getGroupedNotifications.defs.js +53 -2
- package/dist/lexicons/app/bsky/notification/getGroupedNotifications.defs.js.map +1 -1
- package/dist/proto/bsky_connect.d.ts +10 -1
- package/dist/proto/bsky_connect.d.ts.map +1 -1
- package/dist/proto/bsky_connect.js +10 -1
- package/dist/proto/bsky_connect.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +34 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +60 -0
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/telemetry/events.d.ts +30 -0
- package/dist/telemetry/events.d.ts.map +1 -1
- package/dist/telemetry/events.js +37 -0
- package/dist/telemetry/events.js.map +1 -1
- package/dist/util/external/index.d.ts +8 -0
- package/dist/util/external/index.d.ts.map +1 -0
- package/dist/util/external/index.js +50 -0
- package/dist/util/external/index.js.map +1 -0
- package/dist/util/{standard-site.d.ts → external/standard-site.d.ts} +30 -4
- package/dist/util/external/standard-site.d.ts.map +1 -0
- package/dist/util/{standard-site.js → external/standard-site.js} +73 -4
- package/dist/util/external/standard-site.js.map +1 -0
- package/dist/views/external.js +1 -1
- package/dist/views/external.js.map +1 -1
- package/dist/views/index.d.ts +10 -6
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +84 -42
- package/dist/views/index.js.map +1 -1
- package/dist/views/profile-link-rules.d.ts +10 -0
- package/dist/views/profile-link-rules.d.ts.map +1 -0
- package/dist/views/profile-link-rules.js +48 -0
- package/dist/views/profile-link-rules.js.map +1 -0
- package/dist/views/types.d.ts +2 -0
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js.map +1 -1
- package/package.json +4 -4
- package/dist/util/standard-site.d.ts.map +0 -1
- package/dist/util/standard-site.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spotlight.js","sourceRoot":"","sources":["../../../../../../src/api/app/bsky/notification/grouping/spotlight.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/lex'\nimport { AtUri } from '@atproto/syntax'\nimport { app } from '../../../../../lexicons/index.js'\nimport {\n APPVIEW_NOTIFICATION_REASON,\n NOTIFICATION_REASON,\n} from '../constants.js'\nimport type {\n GroupingResult,\n NotificationGroup,\n NotificationItem,\n} from './grouping.js'\nimport {\n MAX_GROUP_SIZE,\n compareNotificationGroupsNewestFirst,\n isNotificationRead,\n} from './shared.js'\n\nconst MULTI_POST_LIKE_RANGES = [\n { maxItems: 200, requiredPosts: 4 },\n { maxItems: 500, requiredPosts: 8 },\n]\n\ntype SpotlightCandidate = Pick<\n NotificationGroup,\n 'kind' | 'groupingKey' | 'items'\n> & {\n isEligibleAfterTrimming: (\n spotlightItems: NotificationItem[],\n retainedItems: NotificationItem[],\n ) => boolean\n}\n\nexport const buildSpotlight = (\n items: NotificationItem[],\n groups: NotificationGroup[],\n cursor: string | undefined,\n limit: number,\n seenAt: number | undefined,\n): GroupingResult => {\n const noSpotlightPage = { groups, cursor }\n const itemCount = groups.reduce(\n (count, group) => count + group.items.length,\n 0,\n )\n\n // Grouping consumes a continuous raw prefix, even when groups interleave.\n // items contains all fetched notifications, but grouping may stop before consuming them all;\n // itemCount counts notifications included in the ordinary groups, and pageItems contains the notifications on the page.\n const pageItems = items.slice(0, itemCount)\n const spotlight = selectMultiPostLikeSpotlight(pageItems)\n if (!spotlight) return noSpotlightPage\n\n const selectedItems = new Set(spotlight.items)\n const positions = new Map(pageItems.map((item, index) => [item, index]))\n const proposedGroups = mapDefined(\n [\n ...groups.map((group) => ({\n // Filtering may remove notifications from this group; build a new group with only the remaining items and their updated metadata.\n kind: group.kind,\n groupingKey: group.groupingKey,\n items: group.items.filter((item) => !selectedItems.has(item)),\n })),\n spotlight,\n ],\n (group): NotificationGroup | undefined => {\n const newest = group.items[0]\n const oldest = group.items.at(-1)\n if (!newest || !oldest) return\n\n // Filtering may remove notifications from this group; build a new group with only the remaining items and their updated metadata.\n return {\n kind: group.kind,\n groupingKey: group.groupingKey,\n id: newest.id,\n items: group.items,\n actorDids: group.items.map((item) => item.actorDid),\n itemCount: group.items.length,\n indexedAt: newest.raw.indexedAt,\n firstIndexedAt: oldest.raw.indexedAt,\n isRead: isNotificationRead(newest.raw.indexedAt, seenAt),\n }\n },\n ).sort(compareNotificationGroupsNewestFirst)\n\n let retainedItems = pageItems\n const extraGroup = proposedGroups[limit]\n if (extraGroup) {\n const cutoff = positions.get(extraGroup.items[0]!)!\n retainedItems = pageItems.slice(0, cutoff)\n cursor = pageItems[cutoff - 1]!.raw.indexedAt\n // Trimming every group at one raw position preserves the page prefix.\n for (const group of proposedGroups) {\n group.items = group.items.filter((item) => positions.get(item)! < cutoff)\n group.actorDids = group.items.map((item) => item.actorDid)\n group.itemCount = group.items.length\n const oldest = group.items.at(-1)\n if (oldest) group.firstIndexedAt = oldest.raw.indexedAt\n }\n }\n\n const spotlightItems = retainedItems.filter((item) => selectedItems.has(item))\n if (!spotlight.isEligibleAfterTrimming(spotlightItems, retainedItems)) {\n return noSpotlightPage\n }\n\n return {\n cursor,\n groups: proposedGroups.filter((group) => group.items.length > 0),\n }\n}\n\nconst selectMultiPostLikeSpotlight = (\n items: NotificationItem[],\n): SpotlightCandidate | undefined => {\n const range = MULTI_POST_LIKE_RANGES.find(\n ({ maxItems }) => items.length <= maxItems,\n )\n if (!range) return\n\n // Eligibility uses the ordinary page's volume, including after trimming.\n const { requiredPosts } = range\n const likesByTopLiker = getLikeNotificationsByTopLiker(items)\n if (likesByTopLiker.length < requiredPosts) return\n const actorDid = likesByTopLiker[0]!.actorDid\n return {\n kind: APPVIEW_NOTIFICATION_REASON.MULTI_POST_LIKE,\n groupingKey: actorDid,\n items: likesByTopLiker.slice(0, MAX_GROUP_SIZE),\n isEligibleAfterTrimming: (spotlightItems, retainedItems) =>\n // Check if after trimming it still satisfies the requirements.\n spotlightItems.length >= requiredPosts &&\n getLikeNotificationsByTopLiker(retainedItems)[0]?.actorDid === actorDid,\n }\n}\n\nconst getLikeNotificationsByTopLiker = (\n items: NotificationItem[],\n): NotificationItem[] => {\n const likesByActor = new Map<DidString, NotificationItem[]>()\n for (const item of items) {\n if (\n item.raw.reason !== NOTIFICATION_REASON.LIKE ||\n new AtUri(item.raw.reasonSubject).collection !== app.bsky.feed.post.$type\n ) {\n continue\n }\n const likes = likesByActor.get(item.actorDid)\n if (likes) likes.push(item)\n else likesByActor.set(item.actorDid, [item])\n }\n\n // Each actor likes a post once; insertion order breaks ties by newest like.\n let top: NotificationItem[] = []\n for (const likes of likesByActor.values()) {\n if (likes.length > top.length) top = likes\n }\n return top\n}\n"]}
|
|
1
|
+
{"version":3,"file":"spotlight.js","sourceRoot":"","sources":["../../../../../../src/api/app/bsky/notification/grouping/spotlight.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/lex'\nimport { AtUri } from '@atproto/syntax'\nimport { app } from '../../../../../lexicons/index.js'\nimport {\n APPVIEW_NOTIFICATION_REASON,\n NOTIFICATION_REASON,\n} from '../constants.js'\nimport type {\n GroupingResult,\n NotificationGroup,\n NotificationItem,\n} from './grouping.js'\nimport {\n MAX_GROUP_SIZE,\n compareNotificationGroupsNewestFirst,\n isNotificationRead,\n} from './shared.js'\n\nconst MAX_SPOTLIGHTS = 3\nconst MULTI_POST_RANGES = [\n { maxItems: 200, requiredPosts: 4 },\n { maxItems: 500, requiredPosts: 8 },\n]\nconst SPOTLIGHT_KINDS = {\n [NOTIFICATION_REASON.LIKE]: APPVIEW_NOTIFICATION_REASON.MULTI_POST_LIKE,\n [NOTIFICATION_REASON.REPOST]: APPVIEW_NOTIFICATION_REASON.MULTI_POST_REPOST,\n [NOTIFICATION_REASON.LIKE_VIA_REPOST]:\n APPVIEW_NOTIFICATION_REASON.MULTI_POST_LIKE_VIA_REPOST,\n [NOTIFICATION_REASON.REPOST_VIA_REPOST]:\n APPVIEW_NOTIFICATION_REASON.MULTI_POST_REPOST_VIA_REPOST,\n} as const\ntype SpotlightReason = keyof typeof SPOTLIGHT_KINDS\nconst SPOTLIGHT_REASONS = Object.keys(SPOTLIGHT_KINDS) as SpotlightReason[]\n\ntype SpotlightCandidate = Pick<\n NotificationGroup,\n 'kind' | 'groupingKey' | 'items'\n> & {\n isEligibleAfterTrimming: (\n spotlightItems: NotificationItem[],\n retainedItems: NotificationItem[],\n ) => boolean\n}\n\nexport function buildSpotlight(\n items: NotificationItem[],\n groups: NotificationGroup[],\n cursor: string | undefined,\n limit: number,\n seenAt: number | undefined,\n): GroupingResult {\n // @NOTE Try one spotlight at a time, keeping the last page where all spotlights pass validation.\n let lastGoodPage: GroupingResult = { groups, cursor }\n const itemCount = groups.reduce(\n (count, group) => count + group.items.length,\n 0,\n )\n // @NOTE Grouping consumes a continuous raw prefix, even when groups interleave.\n // items contains all fetched notifications, but grouping may stop before consuming them all;\n // itemCount counts notifications included in the ordinary groups, and pageItems contains the notifications on the page.\n const pageItems = items.slice(0, itemCount)\n const positions = new Map(pageItems.map((item, index) => [item, index]))\n // @NOTE Rank each reason's top actor by full count, then recency, before capping spotlight size.\n const candidates = mapDefined(SPOTLIGHT_REASONS, (reason) =>\n selectSpotlight(pageItems, reason),\n )\n .sort(\n (left, right) =>\n right.items.length - left.items.length ||\n positions.get(left.items[0]!)! - positions.get(right.items[0]!)!,\n )\n .map((candidate) => ({\n ...candidate,\n items: candidate.items.slice(0, MAX_GROUP_SIZE),\n }))\n\n let lastGoodItems = pageItems\n const acceptedSpotlights: SpotlightCandidate[] = []\n for (const candidate of candidates) {\n if (acceptedSpotlights.length === MAX_SPOTLIGHTS) break\n // @NOTE 1. Tentatively add this spotlight using only notifications retained on the last accepted page.\n const candidateItems = candidate.items.filter(\n (item) => positions.get(item)! < lastGoodItems.length,\n )\n const selectedItems = new Set(candidateItems)\n const proposedGroups = mapDefined(\n [\n ...lastGoodPage.groups.map((group) => ({\n // @NOTE Filtering may remove notifications from this group; build a new group with only the remaining items and their updated metadata.\n kind: group.kind,\n groupingKey: group.groupingKey,\n items: group.items.filter((item) => !selectedItems.has(item)),\n })),\n { ...candidate, items: candidateItems },\n ],\n (group): NotificationGroup | undefined => {\n const newest = group.items[0]\n const oldest = group.items.at(-1)\n if (!newest || !oldest) return\n\n // @NOTE Filtering may remove notifications from this group; build a new group with only the remaining items and their updated metadata.\n return {\n kind: group.kind,\n groupingKey: group.groupingKey,\n id: newest.id,\n items: group.items,\n actorDids: group.items.map((item) => item.actorDid),\n itemCount: group.items.length,\n indexedAt: newest.raw.indexedAt,\n firstIndexedAt: oldest.raw.indexedAt,\n isRead: isNotificationRead(newest.raw.indexedAt, seenAt),\n }\n },\n ).sort(compareNotificationGroupsNewestFirst)\n\n // @NOTE 2. Trim the tentative page to the group limit without changing the saved state.\n let retainedItems = lastGoodItems\n let nextCursor = lastGoodPage.cursor\n const extraGroup = proposedGroups[limit]\n if (extraGroup) {\n const cutoff = positions.get(extraGroup.items[0]!)!\n retainedItems = lastGoodItems.slice(0, cutoff)\n nextCursor = pageItems[cutoff - 1]!.raw.indexedAt\n // @NOTE Trimming every group at one raw position preserves the page prefix.\n for (const group of proposedGroups) {\n group.items = group.items.filter(\n (item) => positions.get(item)! < cutoff,\n )\n group.actorDids = group.items.map((item) => item.actorDid)\n group.itemCount = group.items.length\n const oldest = group.items.at(-1)\n if (oldest) group.firstIndexedAt = oldest.raw.indexedAt\n }\n }\n\n const retained = new Set(retainedItems)\n // @NOTE 3. Reject the attempt if any spotlight fails, preserving the previously accepted page and cursor.\n const allEligible = [...acceptedSpotlights, candidate].every((spotlight) =>\n spotlight.isEligibleAfterTrimming(\n spotlight.items.filter((item) => retained.has(item)),\n retainedItems,\n ),\n )\n if (!allEligible) continue\n\n // @NOTE 4. Save the valid page, cursor, and remaining notifications for the next attempt.\n lastGoodPage = {\n cursor: nextCursor,\n groups: proposedGroups.filter((group) => group.items.length > 0),\n }\n lastGoodItems = retainedItems\n acceptedSpotlights.push(candidate)\n }\n\n return lastGoodPage\n}\n\nfunction selectSpotlight(\n items: NotificationItem[],\n reason: SpotlightReason,\n): SpotlightCandidate | undefined {\n const range = MULTI_POST_RANGES.find(\n ({ maxItems }) => items.length <= maxItems,\n )\n if (!range) return\n\n // @NOTE Eligibility uses the ordinary page's volume, including after trimming.\n const { requiredPosts } = range\n const topItems = getNotificationsByTopActor(items, reason)\n if (topItems.length < requiredPosts) return\n const actorDid = topItems[0]!.actorDid\n return {\n kind: SPOTLIGHT_KINDS[reason],\n groupingKey: actorDid,\n items: topItems,\n isEligibleAfterTrimming: (spotlightItems, retainedItems) =>\n // @NOTE Check if after trimming it still satisfies the requirements.\n spotlightItems.length >= requiredPosts &&\n getNotificationsByTopActor(retainedItems, reason)[0]?.actorDid ===\n actorDid,\n }\n}\n\nfunction getNotificationsByTopActor(\n items: NotificationItem[],\n reason: SpotlightReason,\n): NotificationItem[] {\n const collection =\n reason === NOTIFICATION_REASON.LIKE_VIA_REPOST ||\n reason === NOTIFICATION_REASON.REPOST_VIA_REPOST\n ? app.bsky.feed.repost.$type\n : app.bsky.feed.post.$type\n const itemsByActor = new Map<DidString, NotificationItem[]>()\n for (const item of items) {\n if (\n item.raw.reason !== reason ||\n new AtUri(item.raw.reasonSubject).collection !== collection\n ) {\n continue\n }\n const actorItems = itemsByActor.get(item.actorDid)\n if (actorItems) actorItems.push(item)\n else itemsByActor.set(item.actorDid, [item])\n }\n\n // @NOTE Each actor likes or reposts a post once per reason; insertion order breaks ties by newest notification.\n let top: NotificationItem[] = []\n for (const actorItems of itemsByActor.values()) {\n if (actorItems.length > top.length) top = actorItems\n }\n return top\n}\n"]}
|
|
@@ -47,8 +47,9 @@ const skeleton = async (input) => {
|
|
|
47
47
|
const hydration = async (input) => {
|
|
48
48
|
const { ctx, params, skeleton } = input;
|
|
49
49
|
const { dids } = skeleton;
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
return ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx, {
|
|
51
|
+
activitySubscriptions: true,
|
|
52
|
+
});
|
|
52
53
|
};
|
|
53
54
|
const noBlocks = (input) => {
|
|
54
55
|
const { skeleton, hydration, ctx } = input;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listActivitySubscriptions.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAQ5C,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EAKL,cAAc,GACf,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzE,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,yBAAyB,GAAG,cAAc,CAC9C,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,CACb,CAAA;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,yBAAyB,EAAE;QAC1D,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,QAAQ;QAC/B,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAA;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,QAAQ;gBACR,MAAM;aACP,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;gBAC5B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAC3B,yBAAyB,CACvB,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EACxC,GAAG,CACJ;gBACH,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;aAC9B,CAAC,CAAA;YAEF,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC;aACvD,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EACpB,KAAuC,EACf,EAAE;IAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;IAC7B,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAA;IACzC,IAAI,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAC/B,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GACpB,MAAM,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,2BAA2B,CAAC;QACvD,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;QAClC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAA;IACJ,OAAO;QACL,QAAQ;QACR,IAAI,EAAE,IAAmB;QACzB,MAAM;KACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,KAAK,EACrB,KAAuD,EACvD,EAAE;IACF,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IACvC,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAA;IACzB,
|
|
1
|
+
{"version":3,"file":"listActivitySubscriptions.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/notification/listActivitySubscriptions.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtxWithViewer,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n type HydrationFnInput,\n type PresentationFnInput,\n type RulesFnInput,\n type SkeletonFnInput,\n createPipeline,\n} from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\nimport { clearlyBadCursor, fillPage, resHeaders } from '../../../util.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const listActivitySubscriptions = createPipeline(\n skeleton,\n hydration,\n noBlocks,\n presentation,\n )\n server.add(app.bsky.notification.listActivitySubscriptions, {\n auth: ctx.authVerifier.standard,\n handler: async ({ params, auth, req }) => {\n const viewer = auth.credentials.iss\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n labelers,\n viewer,\n })\n\n const result = await fillPage({\n cursor: params.cursor,\n limit: params.limit,\n fetch: ({ cursor, limit }) =>\n listActivitySubscriptions(\n { ...params, cursor, limit, hydrateCtx },\n ctx,\n ),\n items: (r) => r.subscriptions,\n })\n\n return {\n encoding: 'application/json',\n body: result,\n headers: resHeaders({ labelers: hydrateCtx.labelers }),\n }\n },\n })\n}\n\nconst skeleton = async (\n input: SkeletonFnInput<Context, Params>,\n): Promise<SkeletonState> => {\n const { params, ctx } = input\n const actorDid = params.hydrateCtx.viewer\n if (clearlyBadCursor(params.cursor)) {\n return { actorDid, dids: [] }\n }\n const { dids, cursor } =\n await ctx.hydrator.dataplane.getActivitySubscriptionDids({\n actorDid: params.hydrateCtx.viewer,\n limit: params.limit,\n cursor: params.cursor,\n })\n return {\n actorDid,\n dids: dids as DidString[],\n cursor,\n }\n}\n\nconst hydration = async (\n input: HydrationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, params, skeleton } = input\n const { dids } = skeleton\n return ctx.hydrator.hydrateProfiles(dids, params.hydrateCtx, {\n activitySubscriptions: true,\n })\n}\n\nconst noBlocks = (input: RulesFnInput<Context, Params, SkeletonState>) => {\n const { skeleton, hydration, ctx } = input\n skeleton.dids = skeleton.dids.filter(\n (did) => !ctx.views.viewerBlockExists(did, hydration),\n )\n return skeleton\n}\n\nconst presentation = (\n input: PresentationFnInput<Context, Params, SkeletonState>,\n) => {\n const { ctx, hydration, skeleton } = input\n const { dids, cursor } = skeleton\n const subscriptions = mapDefined(dids, (did) => {\n return ctx.views.profile(did, hydration)\n })\n return { subscriptions, cursor }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = app.bsky.notification.listActivitySubscriptions.$Params & {\n hydrateCtx: HydrateCtxWithViewer\n}\n\ntype SkeletonState = {\n actorDid: DidString\n dids: DidString[]\n cursor?: string\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAtmosphereExploreTab.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getAtmosphereExploreTab.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,MAAM,EAGZ,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"getAtmosphereExploreTab.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getAtmosphereExploreTab.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,MAAM,EAGZ,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AA0BxD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAyHvD"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mapDefined } from '@atproto/common';
|
|
2
2
|
import { l } from '@atproto/lex';
|
|
3
3
|
import { AtUri } from '@atproto/syntax';
|
|
4
4
|
import { MethodNotImplementedError, UpstreamFailureError, UpstreamTimeoutError, } from '@atproto/xrpc-server';
|
|
5
5
|
import { safeFetchWrap } from '@atproto-labs/fetch-node';
|
|
6
|
-
import {
|
|
7
|
-
import { HydrationMap } from '../../../../hydration/util.js';
|
|
8
|
-
import { app, site, social } from '../../../../lexicons/index.js';
|
|
9
|
-
import { uriToDid } from '../../../../util/uris.js';
|
|
6
|
+
import { app } from '../../../../lexicons/index.js';
|
|
10
7
|
const MAX_CONFIG_BYTES = 512 * 1024;
|
|
11
8
|
const MAX_ATMOSPHERE_RECORDS = 500;
|
|
12
|
-
const MAX_GALLERY_ITEMS = 10;
|
|
13
|
-
const MAX_PREVIEW_ACTORS = 3;
|
|
14
9
|
const groupSchema = l.object({
|
|
15
10
|
featured: l.boolean(),
|
|
16
11
|
uris: l.array(l.unknown(), { maxLength: 100 }),
|
|
@@ -82,61 +77,42 @@ export default function (server, ctx) {
|
|
|
82
77
|
}
|
|
83
78
|
const articles = completeGroups(config.articles);
|
|
84
79
|
const publications = completeGroups(config.publications);
|
|
85
|
-
const photos = completeGroups(config.photos
|
|
86
|
-
...group,
|
|
87
|
-
// @NOTE Gallery membership comes from backlinks, not loose CMS photo URIs.
|
|
88
|
-
uris: mapDefined(group.uris, (input) => {
|
|
89
|
-
const uri = recordUri(input);
|
|
90
|
-
return uri &&
|
|
91
|
-
new AtUri(uri).collection === social.grain.gallery.$type
|
|
92
|
-
? uri
|
|
93
|
-
: undefined;
|
|
94
|
-
}),
|
|
95
|
-
})));
|
|
80
|
+
const photos = completeGroups(config.photos);
|
|
96
81
|
const livestreams = completeGroups(config.livestreams);
|
|
97
82
|
const uris = [
|
|
98
|
-
...new Set([...articles, ...publications, ...photos, ...livestreams].
|
|
83
|
+
...new Set([...articles, ...publications, ...photos, ...livestreams].map(({ uri }) => uri)),
|
|
99
84
|
];
|
|
100
85
|
const hydrateCtx = await ctx.hydrator.createContext({
|
|
101
86
|
viewer: auth.credentials.iss,
|
|
102
87
|
labelers: ctx.reqLabelers(req),
|
|
103
88
|
});
|
|
104
|
-
const state = await
|
|
89
|
+
const state = await ctx.hydrator.hydrateEmbedExternalViewFromUris(uris, hydrateCtx);
|
|
105
90
|
const now = Date.now();
|
|
106
91
|
const result = {
|
|
107
92
|
announcementBanner: config.announcementBanner,
|
|
108
|
-
articles: mapDefined(articles, ({ featured,
|
|
109
|
-
const
|
|
110
|
-
const view = uri
|
|
111
|
-
? ctx.views.externalRecordView(uri, state, now)
|
|
112
|
-
: undefined;
|
|
93
|
+
articles: mapDefined(articles, ({ featured, uri }) => {
|
|
94
|
+
const view = ctx.views.externalRecordView(uri, state, now);
|
|
113
95
|
return view && app.bsky.embed.external.viewArticle.$isTypeOf(view)
|
|
114
96
|
? { featured, view }
|
|
115
97
|
: undefined;
|
|
116
98
|
}),
|
|
117
|
-
publications: mapDefined(publications, ({ featured,
|
|
118
|
-
const view =
|
|
119
|
-
? ctx.views.externalRecordView(uris[0], state, now)
|
|
120
|
-
: undefined;
|
|
99
|
+
publications: mapDefined(publications, ({ featured, uri }) => {
|
|
100
|
+
const view = ctx.views.externalRecordView(uri, state, now);
|
|
121
101
|
return view &&
|
|
122
102
|
app.bsky.embed.external.viewArticlePublication.$isTypeOf(view)
|
|
123
103
|
? { featured, view }
|
|
124
104
|
: undefined;
|
|
125
105
|
}),
|
|
126
|
-
photos: mapDefined(photos, ({ featured,
|
|
127
|
-
const view =
|
|
128
|
-
? ctx.views.externalRecordView(uris[0], state, now)
|
|
129
|
-
: undefined;
|
|
106
|
+
photos: mapDefined(photos, ({ featured, uri }) => {
|
|
107
|
+
const view = ctx.views.externalRecordView(uri, state, now);
|
|
130
108
|
return view &&
|
|
131
109
|
app.bsky.embed.external.viewGallery.$isTypeOf(view) &&
|
|
132
110
|
view.items.length
|
|
133
111
|
? { featured, view }
|
|
134
112
|
: undefined;
|
|
135
113
|
}),
|
|
136
|
-
livestreams: mapDefined(livestreams, ({ featured,
|
|
137
|
-
const view =
|
|
138
|
-
? ctx.views.externalRecordView(uris[0], state, now)
|
|
139
|
-
: undefined;
|
|
114
|
+
livestreams: mapDefined(livestreams, ({ featured, uri }) => {
|
|
115
|
+
const view = ctx.views.externalRecordView(uri, state, now);
|
|
140
116
|
return view && app.bsky.embed.external.viewLivestream.$isTypeOf(view)
|
|
141
117
|
? { featured, view }
|
|
142
118
|
: undefined;
|
|
@@ -149,120 +125,12 @@ export default function (server, ctx) {
|
|
|
149
125
|
}
|
|
150
126
|
function completeGroups(groups = []) {
|
|
151
127
|
return mapDefined(groups, ({ featured, uris }) => {
|
|
152
|
-
const
|
|
153
|
-
if (!
|
|
128
|
+
const uri = recordUri(uris[0]);
|
|
129
|
+
if (!uri)
|
|
154
130
|
return;
|
|
155
|
-
return { featured,
|
|
131
|
+
return { featured, uri };
|
|
156
132
|
});
|
|
157
133
|
}
|
|
158
|
-
async function hydrateAtmosphere(uris, ctx, hydrator) {
|
|
159
|
-
const records = await hydrateRecords(uris, hydrator);
|
|
160
|
-
const available = uris.filter((uri) => records.get(uri));
|
|
161
|
-
const counts = await hydrator.external.getAtmosphereBacklinkCounts(available);
|
|
162
|
-
const backlinks = new HydrationMap();
|
|
163
|
-
// @NOTE Bound fan-out as well as each backlink page; never scan a whole collection.
|
|
164
|
-
for (const batch of chunkArray(available, 8)) {
|
|
165
|
-
await Promise.all(batch.map(async (uri) => {
|
|
166
|
-
const collection = new AtUri(uri).collection;
|
|
167
|
-
const sources = [];
|
|
168
|
-
if (collection === site.standard.document.$type) {
|
|
169
|
-
sources.push({
|
|
170
|
-
collection: site.standard.graph.recommend.$type,
|
|
171
|
-
limit: MAX_PREVIEW_ACTORS,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
else if (collection === site.standard.publication.$type) {
|
|
175
|
-
sources.push({
|
|
176
|
-
collection: site.standard.graph.subscription.$type,
|
|
177
|
-
limit: MAX_PREVIEW_ACTORS,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
else if (collection === social.grain.gallery.$type) {
|
|
181
|
-
sources.push({
|
|
182
|
-
collection: social.grain.favorite.$type,
|
|
183
|
-
limit: MAX_PREVIEW_ACTORS,
|
|
184
|
-
}, {
|
|
185
|
-
collection: social.grain.gallery.item.$type,
|
|
186
|
-
limit: MAX_GALLERY_ITEMS,
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
const links = [];
|
|
190
|
-
for (const { collection, limit } of sources) {
|
|
191
|
-
const page = await hydrator.external.getAtmosphereBacklinks(uri, collection, { limit });
|
|
192
|
-
links.push(...mapDefined(page.backlinks.slice(0, limit), ({ uri: input }) => {
|
|
193
|
-
const uri = recordUri(input);
|
|
194
|
-
return uri && new AtUri(uri).collection === collection
|
|
195
|
-
? uri
|
|
196
|
-
: undefined;
|
|
197
|
-
}));
|
|
198
|
-
}
|
|
199
|
-
backlinks.set(uri, [...new Set(links)]);
|
|
200
|
-
}));
|
|
201
|
-
}
|
|
202
|
-
records.merge(await hydrateRecords([...backlinks.values()].flatMap((uris) => uris ?? []), hydrator));
|
|
203
|
-
const photoUris = [];
|
|
204
|
-
for (const [galleryUri, links] of backlinks) {
|
|
205
|
-
if (new AtUri(galleryUri).collection !== social.grain.gallery.$type)
|
|
206
|
-
continue;
|
|
207
|
-
for (const uri of links ?? []) {
|
|
208
|
-
const item = social.grain.gallery.item.$ifMatches(records.get(uri)?.record);
|
|
209
|
-
if (!item ||
|
|
210
|
-
item.gallery !== galleryUri ||
|
|
211
|
-
uriToDid(uri) !== uriToDid(galleryUri))
|
|
212
|
-
continue;
|
|
213
|
-
const photoUri = recordUri(item.item);
|
|
214
|
-
if (photoUri &&
|
|
215
|
-
new AtUri(photoUri).collection === social.grain.photo.$type)
|
|
216
|
-
photoUris.push(photoUri);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
records.merge(await hydrateRecords(photoUris, hydrator));
|
|
220
|
-
const allUris = [...records.keys()];
|
|
221
|
-
const dids = [...new Set(allUris.map(uriToDid))];
|
|
222
|
-
const states = [];
|
|
223
|
-
for (const batch of chunkArray(dids, 200)) {
|
|
224
|
-
states.push(await hydrator.hydrateProfilesBasic(batch, ctx));
|
|
225
|
-
}
|
|
226
|
-
for (const batch of chunkArray(allUris, MAX_ATMOSPHERE_RECORDS)) {
|
|
227
|
-
states.push({
|
|
228
|
-
labels: await hydrator.label.getLabelsForSubjects(batch, ctx.labelers),
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
...mergeManyStates(...states),
|
|
233
|
-
ctx,
|
|
234
|
-
externalRecords: records,
|
|
235
|
-
externalRecordBacklinks: backlinks,
|
|
236
|
-
externalRecordBacklinkCounts: counts,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
async function hydrateRecords(uris, hydrator) {
|
|
240
|
-
const records = new HydrationMap();
|
|
241
|
-
for (const batch of chunkArray([...new Set(uris)], MAX_ATMOSPHERE_RECORDS)) {
|
|
242
|
-
records.merge(await hydrator.external.getRecordsByURI(batch));
|
|
243
|
-
}
|
|
244
|
-
return records;
|
|
245
|
-
}
|
|
246
|
-
// @NOTE A publication hydrated for another CMS group must not complete this article.
|
|
247
|
-
function articleUri(uris, state) {
|
|
248
|
-
const documents = uris.filter((uri) => new AtUri(uri).collection === site.standard.document.$type);
|
|
249
|
-
const publications = uris.filter((uri) => new AtUri(uri).collection === site.standard.publication.$type);
|
|
250
|
-
if (documents.length !== 1 ||
|
|
251
|
-
publications.length > 1 ||
|
|
252
|
-
documents.length + publications.length !== uris.length)
|
|
253
|
-
return;
|
|
254
|
-
const uri = documents[0];
|
|
255
|
-
const document = site.standard.document.$ifMatches(state.externalRecords?.get(uri)?.record);
|
|
256
|
-
if (!document)
|
|
257
|
-
return;
|
|
258
|
-
if (document.site.startsWith('at://')) {
|
|
259
|
-
if (document.site !== publications[0])
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
else if (publications.length)
|
|
263
|
-
return;
|
|
264
|
-
return uri;
|
|
265
|
-
}
|
|
266
134
|
function recordUri(value) {
|
|
267
135
|
if (!l.isAtUriString(value))
|
|
268
136
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAtmosphereExploreTab.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getAtmosphereExploreTab.ts"],"names":[],"mappings":"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","sourcesContent":["import { chunkArray, mapDefined } from '@atproto/common'\nimport { type AtUriString, type NsidString, l } from '@atproto/lex'\nimport { AtUri } from '@atproto/syntax'\nimport {\n MethodNotImplementedError,\n type Server,\n UpstreamFailureError,\n UpstreamTimeoutError,\n} from '@atproto/xrpc-server'\nimport { safeFetchWrap } from '@atproto-labs/fetch-node'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n ExternalRecordBacklinks,\n ExternalRecords,\n} from '../../../../hydration/external.js'\nimport {\n type HydrateCtx,\n type HydrationState,\n type Hydrator,\n mergeManyStates,\n} from '../../../../hydration/hydrator.js'\nimport { HydrationMap } from '../../../../hydration/util.js'\nimport { app, site, social } from '../../../../lexicons/index.js'\nimport { uriToDid } from '../../../../util/uris.js'\n\nconst MAX_CONFIG_BYTES = 512 * 1024\nconst MAX_ATMOSPHERE_RECORDS = 500\nconst MAX_GALLERY_ITEMS = 10\nconst MAX_PREVIEW_ACTORS = 3\n\nconst groupSchema = l.object({\n featured: l.boolean(),\n uris: l.array(l.unknown(), { maxLength: 100 }),\n})\nconst configSchema = l.object({\n announcementBanner: l.optional(\n app.bsky.unspecced.getAtmosphereExploreTab.announcementBanner,\n ),\n articles: l.optional(l.array(groupSchema, { maxLength: 100 })),\n publications: l.optional(l.array(groupSchema, { maxLength: 100 })),\n photos: l.optional(l.array(groupSchema, { maxLength: 100 })),\n livestreams: l.optional(l.array(groupSchema, { maxLength: 100 })),\n apps: l.optional(\n l.array(app.bsky.unspecced.getAtmosphereExploreTab.appCard, {\n maxLength: 100,\n }),\n ),\n})\ntype RecordGroup = { featured: boolean; uris: AtUriString[] }\n\nexport default function (server: Server, ctx: AppContext) {\n // @NOTE The wrapper caps decoded response bytes, including compressed bodies.\n const fetchConfig = safeFetchWrap({\n timeout: 5000,\n responseMaxSize: MAX_CONFIG_BYTES,\n })\n server.add(app.bsky.unspecced.getAtmosphereExploreTab, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req, signal }) => {\n const service = ctx.cfg.atmosphereExploreTabService\n if (!service)\n throw new MethodNotImplementedError(\n 'Atmosphere Explore service not configured',\n )\n let body: unknown\n try {\n const url = new URL(service)\n if (params.countryCode !== undefined) {\n url.searchParams.set('countryCode', params.countryCode)\n }\n if (params.regionCode !== undefined) {\n url.searchParams.set('regionCode', params.regionCode)\n }\n const response = await fetchConfig(url, {\n headers: { accept: 'application/json' },\n redirect: 'error',\n signal,\n })\n if (!response.ok) {\n await response.body?.cancel()\n throw new UpstreamFailureError(\n `Atmosphere Explore service returned HTTP ${response.status}`,\n )\n }\n body = await response.json()\n } catch (err) {\n if (err instanceof UpstreamFailureError) throw err\n if (\n err instanceof Error &&\n (err.name === 'TimeoutError' || err.name === 'AbortError')\n ) {\n throw new UpstreamTimeoutError('Atmosphere Explore request timed out')\n }\n throw new UpstreamFailureError(\n 'Unable to fetch Atmosphere Explore configuration',\n )\n }\n const parsed = configSchema.safeParse(body)\n if (!parsed.success)\n throw new UpstreamFailureError(\n 'Invalid Atmosphere Explore configuration',\n )\n const config = parsed.value\n const groups = [\n ...(config.articles ?? []),\n ...(config.publications ?? []),\n ...(config.photos ?? []),\n ...(config.livestreams ?? []),\n ]\n if (\n groups.reduce((count, group) => count + group.uris.length, 0) >\n MAX_ATMOSPHERE_RECORDS\n ) {\n throw new UpstreamFailureError(\n 'Atmosphere Explore configuration exceeds its record limit',\n )\n }\n const articles = completeGroups(config.articles)\n const publications = completeGroups(config.publications)\n const photos = completeGroups(\n config.photos?.map((group) => ({\n ...group,\n // @NOTE Gallery membership comes from backlinks, not loose CMS photo URIs.\n uris: mapDefined(group.uris, (input) => {\n const uri = recordUri(input)\n return uri &&\n new AtUri(uri).collection === social.grain.gallery.$type\n ? uri\n : undefined\n }),\n })),\n )\n const livestreams = completeGroups(config.livestreams)\n const uris = [\n ...new Set(\n [...articles, ...publications, ...photos, ...livestreams].flatMap(\n ({ uris }) => uris,\n ),\n ),\n ]\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer: auth.credentials.iss,\n labelers: ctx.reqLabelers(req),\n })\n const state = await hydrateAtmosphere(uris, hydrateCtx, ctx.hydrator)\n const now = Date.now()\n const result: app.bsky.unspecced.getAtmosphereExploreTab.$OutputBody = {\n announcementBanner: config.announcementBanner,\n articles: mapDefined(articles, ({ featured, uris }) => {\n const uri = articleUri(uris, state)\n const view = uri\n ? ctx.views.externalRecordView(uri, state, now)\n : undefined\n return view && app.bsky.embed.external.viewArticle.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n publications: mapDefined(publications, ({ featured, uris }) => {\n const view =\n uris.length === 1\n ? ctx.views.externalRecordView(uris[0], state, now)\n : undefined\n return view &&\n app.bsky.embed.external.viewArticlePublication.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n photos: mapDefined(photos, ({ featured, uris }) => {\n const view =\n uris.length === 1\n ? ctx.views.externalRecordView(uris[0], state, now)\n : undefined\n return view &&\n app.bsky.embed.external.viewGallery.$isTypeOf(view) &&\n view.items.length\n ? { featured, view }\n : undefined\n }),\n livestreams: mapDefined(livestreams, ({ featured, uris }) => {\n const view =\n uris.length === 1\n ? ctx.views.externalRecordView(uris[0], state, now)\n : undefined\n return view && app.bsky.embed.external.viewLivestream.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n apps: config.apps ?? [],\n }\n return { encoding: 'application/json', body: result }\n },\n })\n}\n\nfunction completeGroups(\n groups: l.Infer<typeof groupSchema>[] = [],\n): RecordGroup[] {\n return mapDefined(groups, ({ featured, uris }) => {\n const valid = mapDefined(uris, recordUri)\n if (!valid.length || valid.length !== uris.length) return\n return { featured, uris: valid }\n })\n}\n\nasync function hydrateAtmosphere(\n uris: AtUriString[],\n ctx: HydrateCtx,\n hydrator: Hydrator,\n): Promise<HydrationState> {\n const records = await hydrateRecords(uris, hydrator)\n const available = uris.filter((uri) => records.get(uri))\n const counts = await hydrator.external.getAtmosphereBacklinkCounts(available)\n const backlinks: ExternalRecordBacklinks = new HydrationMap()\n\n // @NOTE Bound fan-out as well as each backlink page; never scan a whole collection.\n for (const batch of chunkArray(available, 8)) {\n await Promise.all(\n batch.map(async (uri) => {\n const collection = new AtUri(uri).collection\n const sources: { collection: NsidString; limit: number }[] = []\n if (collection === site.standard.document.$type) {\n sources.push({\n collection: site.standard.graph.recommend.$type,\n limit: MAX_PREVIEW_ACTORS,\n })\n } else if (collection === site.standard.publication.$type) {\n sources.push({\n collection: site.standard.graph.subscription.$type,\n limit: MAX_PREVIEW_ACTORS,\n })\n } else if (collection === social.grain.gallery.$type) {\n sources.push(\n {\n collection: social.grain.favorite.$type,\n limit: MAX_PREVIEW_ACTORS,\n },\n {\n collection: social.grain.gallery.item.$type,\n limit: MAX_GALLERY_ITEMS,\n },\n )\n }\n const links: AtUriString[] = []\n for (const { collection, limit } of sources) {\n const page = await hydrator.external.getAtmosphereBacklinks(\n uri,\n collection,\n { limit },\n )\n links.push(\n ...mapDefined(page.backlinks.slice(0, limit), ({ uri: input }) => {\n const uri = recordUri(input)\n return uri && new AtUri(uri).collection === collection\n ? uri\n : undefined\n }),\n )\n }\n backlinks.set(uri, [...new Set(links)])\n }),\n )\n }\n records.merge(\n await hydrateRecords(\n [...backlinks.values()].flatMap((uris) => uris ?? []),\n hydrator,\n ),\n )\n\n const photoUris: AtUriString[] = []\n for (const [galleryUri, links] of backlinks) {\n if (new AtUri(galleryUri).collection !== social.grain.gallery.$type)\n continue\n for (const uri of links ?? []) {\n const item = social.grain.gallery.item.$ifMatches(\n records.get(uri)?.record,\n )\n if (\n !item ||\n item.gallery !== galleryUri ||\n uriToDid(uri) !== uriToDid(galleryUri)\n )\n continue\n const photoUri = recordUri(item.item)\n if (\n photoUri &&\n new AtUri(photoUri).collection === social.grain.photo.$type\n )\n photoUris.push(photoUri)\n }\n }\n records.merge(await hydrateRecords(photoUris, hydrator))\n\n const allUris = [...records.keys()]\n const dids = [...new Set(allUris.map(uriToDid))]\n const states: HydrationState[] = []\n for (const batch of chunkArray(dids, 200)) {\n states.push(await hydrator.hydrateProfilesBasic(batch, ctx))\n }\n for (const batch of chunkArray(allUris, MAX_ATMOSPHERE_RECORDS)) {\n states.push({\n labels: await hydrator.label.getLabelsForSubjects(batch, ctx.labelers),\n })\n }\n return {\n ...mergeManyStates(...states),\n ctx,\n externalRecords: records,\n externalRecordBacklinks: backlinks,\n externalRecordBacklinkCounts: counts,\n }\n}\n\nasync function hydrateRecords(\n uris: AtUriString[],\n hydrator: Hydrator,\n): Promise<ExternalRecords> {\n const records: ExternalRecords = new HydrationMap()\n for (const batch of chunkArray([...new Set(uris)], MAX_ATMOSPHERE_RECORDS)) {\n records.merge(await hydrator.external.getRecordsByURI(batch))\n }\n return records\n}\n\n// @NOTE A publication hydrated for another CMS group must not complete this article.\nfunction articleUri(\n uris: AtUriString[],\n state: HydrationState,\n): AtUriString | undefined {\n const documents = uris.filter(\n (uri) => new AtUri(uri).collection === site.standard.document.$type,\n )\n const publications = uris.filter(\n (uri) => new AtUri(uri).collection === site.standard.publication.$type,\n )\n if (\n documents.length !== 1 ||\n publications.length > 1 ||\n documents.length + publications.length !== uris.length\n )\n return\n const uri = documents[0]\n const document = site.standard.document.$ifMatches(\n state.externalRecords?.get(uri)?.record,\n )\n if (!document) return\n if (document.site.startsWith('at://')) {\n if (document.site !== publications[0]) return\n } else if (publications.length) return\n return uri\n}\n\nfunction recordUri(value: unknown): AtUriString | undefined {\n if (!l.isAtUriString(value)) return\n const uri = new AtUri(value)\n return uri.collection && uri.rkey && l.isDidString(uri.hostname)\n ? value\n : undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"getAtmosphereExploreTab.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/unspecced/getAtmosphereExploreTab.ts"],"names":[],"mappings":"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","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport { type AtUriString, l } from '@atproto/lex'\nimport { AtUri } from '@atproto/syntax'\nimport {\n MethodNotImplementedError,\n type Server,\n UpstreamFailureError,\n UpstreamTimeoutError,\n} from '@atproto/xrpc-server'\nimport { safeFetchWrap } from '@atproto-labs/fetch-node'\nimport type { AppContext } from '../../../../context.js'\nimport { app } from '../../../../lexicons/index.js'\n\nconst MAX_CONFIG_BYTES = 512 * 1024\nconst MAX_ATMOSPHERE_RECORDS = 500\n\nconst groupSchema = l.object({\n featured: l.boolean(),\n uris: l.array(l.unknown(), { maxLength: 100 }),\n})\nconst configSchema = l.object({\n announcementBanner: l.optional(\n app.bsky.unspecced.getAtmosphereExploreTab.announcementBanner,\n ),\n articles: l.optional(l.array(groupSchema, { maxLength: 100 })),\n publications: l.optional(l.array(groupSchema, { maxLength: 100 })),\n photos: l.optional(l.array(groupSchema, { maxLength: 100 })),\n livestreams: l.optional(l.array(groupSchema, { maxLength: 100 })),\n apps: l.optional(\n l.array(app.bsky.unspecced.getAtmosphereExploreTab.appCard, {\n maxLength: 100,\n }),\n ),\n})\ntype RecordGroup = { featured: boolean; uri: AtUriString }\n\nexport default function (server: Server, ctx: AppContext) {\n // @NOTE The wrapper caps decoded response bytes, including compressed bodies.\n const fetchConfig = safeFetchWrap({\n timeout: 5000,\n responseMaxSize: MAX_CONFIG_BYTES,\n })\n server.add(app.bsky.unspecced.getAtmosphereExploreTab, {\n auth: ctx.authVerifier.standardOptional,\n handler: async ({ auth, params, req, signal }) => {\n const service = ctx.cfg.atmosphereExploreTabService\n if (!service)\n throw new MethodNotImplementedError(\n 'Atmosphere Explore service not configured',\n )\n let body: unknown\n try {\n const url = new URL(service)\n if (params.countryCode !== undefined) {\n url.searchParams.set('countryCode', params.countryCode)\n }\n if (params.regionCode !== undefined) {\n url.searchParams.set('regionCode', params.regionCode)\n }\n const response = await fetchConfig(url, {\n headers: { accept: 'application/json' },\n redirect: 'error',\n signal,\n })\n if (!response.ok) {\n await response.body?.cancel()\n throw new UpstreamFailureError(\n `Atmosphere Explore service returned HTTP ${response.status}`,\n )\n }\n body = await response.json()\n } catch (err) {\n if (err instanceof UpstreamFailureError) throw err\n if (\n err instanceof Error &&\n (err.name === 'TimeoutError' || err.name === 'AbortError')\n ) {\n throw new UpstreamTimeoutError('Atmosphere Explore request timed out')\n }\n throw new UpstreamFailureError(\n 'Unable to fetch Atmosphere Explore configuration',\n )\n }\n const parsed = configSchema.safeParse(body)\n if (!parsed.success)\n throw new UpstreamFailureError(\n 'Invalid Atmosphere Explore configuration',\n )\n const config = parsed.value\n const groups = [\n ...(config.articles ?? []),\n ...(config.publications ?? []),\n ...(config.photos ?? []),\n ...(config.livestreams ?? []),\n ]\n if (\n groups.reduce((count, group) => count + group.uris.length, 0) >\n MAX_ATMOSPHERE_RECORDS\n ) {\n throw new UpstreamFailureError(\n 'Atmosphere Explore configuration exceeds its record limit',\n )\n }\n const articles = completeGroups(config.articles)\n const publications = completeGroups(config.publications)\n const photos = completeGroups(config.photos)\n const livestreams = completeGroups(config.livestreams)\n const uris = [\n ...new Set(\n [...articles, ...publications, ...photos, ...livestreams].map(\n ({ uri }) => uri,\n ),\n ),\n ]\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer: auth.credentials.iss,\n labelers: ctx.reqLabelers(req),\n })\n const state = await ctx.hydrator.hydrateEmbedExternalViewFromUris(\n uris,\n hydrateCtx,\n )\n const now = Date.now()\n const result: app.bsky.unspecced.getAtmosphereExploreTab.$OutputBody = {\n announcementBanner: config.announcementBanner,\n articles: mapDefined(articles, ({ featured, uri }) => {\n const view = ctx.views.externalRecordView(uri, state, now)\n return view && app.bsky.embed.external.viewArticle.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n publications: mapDefined(publications, ({ featured, uri }) => {\n const view = ctx.views.externalRecordView(uri, state, now)\n return view &&\n app.bsky.embed.external.viewArticlePublication.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n photos: mapDefined(photos, ({ featured, uri }) => {\n const view = ctx.views.externalRecordView(uri, state, now)\n return view &&\n app.bsky.embed.external.viewGallery.$isTypeOf(view) &&\n view.items.length\n ? { featured, view }\n : undefined\n }),\n livestreams: mapDefined(livestreams, ({ featured, uri }) => {\n const view = ctx.views.externalRecordView(uri, state, now)\n return view && app.bsky.embed.external.viewLivestream.$isTypeOf(view)\n ? { featured, view }\n : undefined\n }),\n apps: config.apps ?? [],\n }\n return { encoding: 'application/json', body: result }\n },\n })\n}\n\nfunction completeGroups(\n groups: l.Infer<typeof groupSchema>[] = [],\n): RecordGroup[] {\n return mapDefined(groups, ({ featured, uris }) => {\n const uri = recordUri(uris[0])\n if (!uri) return\n return { featured, uri }\n })\n}\n\nfunction recordUri(value: unknown): AtUriString | undefined {\n if (!l.isAtUriString(value)) return\n const uri = new AtUri(value)\n return uri.collection && uri.rkey && l.isDidString(uri.hostname)\n ? value\n : undefined\n}\n"]}
|
|
@@ -30,7 +30,10 @@ const skeleton = async (input) => {
|
|
|
30
30
|
};
|
|
31
31
|
const hydration = async (input) => {
|
|
32
32
|
const { ctx, params, skeleton } = input;
|
|
33
|
-
return ctx.hydrator.hydrateProfilesDetailed(skeleton.dids, params.hydrateCtx, {
|
|
33
|
+
return ctx.hydrator.hydrateProfilesDetailed(skeleton.dids, params.hydrateCtx, {
|
|
34
|
+
knownFollowersDids: skeleton.socialProofDids,
|
|
35
|
+
activitySubscriptions: true,
|
|
36
|
+
});
|
|
34
37
|
};
|
|
35
38
|
const presentation = (input) => {
|
|
36
39
|
const { ctx, skeleton, hydration } = input;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getProfiles.js","sourceRoot":"","sources":["../../../../../src/api/internal/bsky/actor/getProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAS5C,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAGjE,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;IAC9E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;QAC1C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI;QAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;gBAC7B,QAAQ;gBACR,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;aAC1C,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,CAAC,CAAA;YAEhE,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM;aACb,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,KAGvB,EAA0B,EAAE;IAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IACxB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5B,gEAAgE;IAChE,MAAM,eAAe,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAChE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAChB,CAAA;IACD,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,KAAK,EAAE,KAIxB,EAAE,EAAE;IACH,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IACvC,OAAO,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CACzC,QAAQ,CAAC,IAAI,EACb,MAAM,CAAC,UAAU,EACjB,
|
|
1
|
+
{"version":3,"file":"getProfiles.js","sourceRoot":"","sources":["../../../../../src/api/internal/bsky/actor/getProfiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAS5C,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAGjE,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;IAC9E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;QAC1C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI;QAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAClD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;gBAC7B,QAAQ;gBACR,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;aAC1C,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,CAAC,CAAA;YAEhE,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM;aACb,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,KAGvB,EAA0B,EAAE;IAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IACxB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;IAC5B,gEAAgE;IAChE,MAAM,eAAe,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAChE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAChB,CAAA;IACD,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,KAAK,EAAE,KAIxB,EAAE,EAAE;IACH,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IACvC,OAAO,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CACzC,QAAQ,CAAC,IAAI,EACb,MAAM,CAAC,UAAU,EACjB;QACE,kBAAkB,EAAE,QAAQ,CAAC,eAAe;QAC5C,qBAAqB,EAAE,IAAI;KAC5B,CACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,KAKrB,EAAE,EAAE;IACH,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;IAC1C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CACjD,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAC1C,CAAA;IACD,OAAO,EAAE,QAAQ,EAAE,CAAA;AACrB,CAAC,CAAA","sourcesContent":["import { mapDefined } from '@atproto/common'\nimport type { DidString } from '@atproto/syntax'\nimport type { Server } from '@atproto/xrpc-server'\nimport type { AppContext } from '../../../../context.js'\nimport type {\n HydrateCtx,\n HydrationState,\n Hydrator,\n} from '../../../../hydration/hydrator.js'\nimport { internal } from '../../../../lexicons/index.js'\nimport { createPipeline, noRules } from '../../../../pipeline.js'\nimport type { Views } from '../../../../views/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const getProfiles = createPipeline(skeleton, hydration, noRules, presentation)\n server.add(internal.bsky.actor.getProfiles, {\n auth: ctx.authVerifier.role,\n handler: async ({ params, req }) => {\n const labelers = ctx.reqLabelers(req)\n const hydrateCtx = await ctx.hydrator.createContext({\n viewer: params.viewer ?? null,\n labelers,\n includeTakedowns: params.includeTakedowns,\n })\n\n const result = await getProfiles({ ...params, hydrateCtx }, ctx)\n\n return {\n encoding: 'application/json',\n body: result,\n }\n },\n })\n}\n\nconst skeleton = async (input: {\n ctx: Context\n params: Params\n}): Promise<SkeletonState> => {\n const { params } = input\n const dids = params.dids\n const didSet = new Set(dids)\n // social proof is only hydrated for dids present in both inputs\n const socialProofDids = (params.socialProof ?? []).filter((did) =>\n didSet.has(did),\n )\n return { dids, socialProofDids }\n}\n\nconst hydration = async (input: {\n ctx: Context\n params: Params\n skeleton: SkeletonState\n}) => {\n const { ctx, params, skeleton } = input\n return ctx.hydrator.hydrateProfilesDetailed(\n skeleton.dids,\n params.hydrateCtx,\n {\n knownFollowersDids: skeleton.socialProofDids,\n activitySubscriptions: true,\n },\n )\n}\n\nconst presentation = (input: {\n ctx: Context\n params: Params\n skeleton: SkeletonState\n hydration: HydrationState\n}) => {\n const { ctx, skeleton, hydration } = input\n const profiles = mapDefined(skeleton.dids, (did) =>\n ctx.views.profileDetailed(did, hydration),\n )\n return { profiles }\n}\n\ntype Context = {\n hydrator: Hydrator\n views: Views\n}\n\ntype Params = internal.bsky.actor.getProfiles.$Params & {\n hydrateCtx: HydrateCtx\n}\n\ntype SkeletonState = {\n dids: DidString[]\n socialProofDids: DidString[]\n}\n"]}
|
package/dist/config.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ export interface ServerConfigValues {
|
|
|
54
54
|
rolodexApiKey?: string;
|
|
55
55
|
rolodexHttpVersion?: '1.1' | '2';
|
|
56
56
|
rolodexIgnoreBadTls?: boolean;
|
|
57
|
+
externalRecordsSafeDomains?: string[];
|
|
57
58
|
searchUrl?: string;
|
|
58
59
|
searchTagsHide: Set<string>;
|
|
59
60
|
searchTagsHideAll: Set<string>;
|
|
@@ -202,6 +203,7 @@ export declare class ServerConfig {
|
|
|
202
203
|
get debugFieldAllowedDids(): Set<string>;
|
|
203
204
|
get draftsLimit(): number;
|
|
204
205
|
get searchV2OverrideHeader(): string | undefined;
|
|
206
|
+
get externalRecordsSafeDomains(): string[];
|
|
205
207
|
}
|
|
206
208
|
export {};
|
|
207
209
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -96,6 +96,9 @@ export class ServerConfig {
|
|
|
96
96
|
const rolodexHttpVersion = process.env.BSKY_ROLODEX_HTTP_VERSION || '2';
|
|
97
97
|
const rolodexIgnoreBadTls = process.env.BSKY_ROLODEX_IGNORE_BAD_TLS === 'true';
|
|
98
98
|
assert(rolodexHttpVersion === '1.1' || rolodexHttpVersion === '2');
|
|
99
|
+
const externalRecordsSafeDomains = envList(process.env.BSKY_EXTERNAL_RECORDS_SAFE_DOMAINS)
|
|
100
|
+
.map((value) => value.trim())
|
|
101
|
+
.filter(Boolean);
|
|
99
102
|
const blobRateLimitBypassKey = process.env.BSKY_BLOB_RATE_LIMIT_BYPASS_KEY || undefined;
|
|
100
103
|
// single domain would be e.g. "mypds.com", subdomains are supported with a leading dot e.g. ".mypds.com"
|
|
101
104
|
const blobRateLimitBypassHostname = process.env.BSKY_BLOB_RATE_LIMIT_BYPASS_HOSTNAME || undefined;
|
|
@@ -245,6 +248,7 @@ export class ServerConfig {
|
|
|
245
248
|
rolodexApiKey,
|
|
246
249
|
rolodexHttpVersion,
|
|
247
250
|
rolodexIgnoreBadTls,
|
|
251
|
+
externalRecordsSafeDomains,
|
|
248
252
|
blobRateLimitBypassKey,
|
|
249
253
|
blobRateLimitBypassHostname,
|
|
250
254
|
adminPasswords,
|
|
@@ -533,6 +537,9 @@ export class ServerConfig {
|
|
|
533
537
|
get searchV2OverrideHeader() {
|
|
534
538
|
return this.cfg.searchV2OverrideHeader;
|
|
535
539
|
}
|
|
540
|
+
get externalRecordsSafeDomains() {
|
|
541
|
+
return this.cfg.externalRecordsSafeDomains ?? [];
|
|
542
|
+
}
|
|
536
543
|
}
|
|
537
544
|
function envList(str) {
|
|
538
545
|
if (str === undefined || str.length === 0)
|