[APP-1784] Proper fix for Live Now status not showing (#9779)

* Be sure to validate if actor is allowed to be live on certain domain

* Rename for clarity

* Memoize
This commit is contained in:
Eric Bailey
2026-01-27 16:44:27 -06:00
committed by GitHub
parent 26605ee730
commit 39e7132fd8
4 changed files with 38 additions and 21 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
const tick = useTickEveryMinute() const tick = useTickEveryMinute()
const liveNowConfig = useLiveNowConfig() const liveNowConfig = useLiveNowConfig()
const {formatted: allowedServices} = getLiveServiceNames( const {formatted: allowedServices} = getLiveServiceNames(
liveNowConfig.allowedDomains, liveNowConfig.currentAccountAllowedHosts,
) )
const time = useCallback( const time = useCallback(
+4 -2
View File
@@ -31,8 +31,10 @@ export function useLiveLinkMetaQuery(url: string | null) {
queryFn: async () => { queryFn: async () => {
if (!url) return undefined if (!url) return undefined
const urlp = new URL(url) const urlp = new URL(url)
if (!liveNowConfig.allowedDomains.has(urlp.hostname)) { if (!liveNowConfig.currentAccountAllowedHosts.has(urlp.hostname)) {
const {formatted} = getLiveServiceNames(liveNowConfig.allowedDomains) const {formatted} = getLiveServiceNames(
liveNowConfig.currentAccountAllowedHosts,
)
throw new Error( throw new Error(
_( _(
msg`This service is not supported while the Live feature is in beta. Allowed services: ${formatted}.`, msg`This service is not supported while the Live feature is in beta. Allowed services: ${formatted}.`,
+7 -1
View File
@@ -3,6 +3,7 @@ import {
type $Typed, type $Typed,
type AppBskyActorDefs, type AppBskyActorDefs,
AppBskyEmbedExternal, AppBskyEmbedExternal,
AtUri,
} from '@atproto/api' } from '@atproto/api'
import {isAfter, parseISO} from 'date-fns' import {isAfter, parseISO} from 'date-fns'
@@ -73,10 +74,15 @@ export function isStatusValidForViewers(
config: LiveNowConfig, config: LiveNowConfig,
) { ) {
if (status.status !== 'app.bsky.actor.status#live') return false if (status.status !== 'app.bsky.actor.status#live') return false
if (!status.uri) return false // should not happen, just backwards compat
try { try {
const {host: liveDid} = new AtUri(status.uri)
if (AppBskyEmbedExternal.isView(status.embed)) { if (AppBskyEmbedExternal.isView(status.embed)) {
const url = new URL(status.embed.external.uri) const url = new URL(status.embed.external.uri)
return config.allSupportedDomains.has(url.hostname) const exception = config.allowedHostsExceptionsByDid.get(liveDid)
const isValidException = exception ? exception.has(url.hostname) : false
const isValidForAnyone = config.defaultAllowedHosts.has(url.hostname)
return isValidException || isValidForAnyone
} else { } else {
return false return false
} }
+26 -17
View File
@@ -89,29 +89,38 @@ const DEFAULT_LIVE_ALLOWED_DOMAINS = [
'www.bluecast.app', 'www.bluecast.app',
] ]
export type LiveNowConfig = { export type LiveNowConfig = {
allowedDomains: Set<string> currentAccountAllowedHosts: Set<string>
allSupportedDomains: Set<string> defaultAllowedHosts: Set<string>
allowedHostsExceptionsByDid: Map<string, Set<string>>
} }
export function useLiveNowConfig(): LiveNowConfig { export function useLiveNowConfig(): LiveNowConfig {
const ctx = useContext(LiveNowContext) const ctx = useContext(LiveNowContext)
const canGoLive = useCanGoLive() const canGoLive = useCanGoLive()
const {currentAccount} = useSession() const {currentAccount} = useSession()
const allVipDomains = new Set(ctx.flatMap(live => live.domains)) return useMemo(() => {
const allSupportedDomains = new Set( const defaultAllowedHosts = new Set(DEFAULT_LIVE_ALLOWED_DOMAINS)
DEFAULT_LIVE_ALLOWED_DOMAINS.concat(Array.from(allVipDomains)), const allowedHostsExceptionsByDid = new Map<string, Set<string>>()
) for (const live of ctx) {
if (!currentAccount?.did || !canGoLive) allowedHostsExceptionsByDid.set(
return { live.did,
allowedDomains: new Set(), new Set(DEFAULT_LIVE_ALLOWED_DOMAINS.concat(live.domains)),
allSupportedDomains, )
} }
const vip = ctx.find(live => live.did === currentAccount.did) if (!currentAccount?.did || !canGoLive)
return { return {
allowedDomains: new Set( currentAccountAllowedHosts: new Set(),
DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), defaultAllowedHosts,
), allowedHostsExceptionsByDid,
allSupportedDomains, }
} const vip = ctx.find(live => live.did === currentAccount.did)
return {
currentAccountAllowedHosts: new Set(
DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []),
),
defaultAllowedHosts,
allowedHostsExceptionsByDid,
}
}, [ctx, currentAccount, canGoLive])
} }
export function useCanGoLive() { export function useCanGoLive() {