diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-05-17 01:38:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-16 15:38:34 -0700 |
commit | 1cdbfc709235ed1933ba51403d941762f384690b (patch) | |
tree | f55aa9a16f05645bcc5c2d63839113725b1ca308 /src/components/live | |
parent | 75ffb3d243a5415d173f2bca8a5334b70451a1f4 (diff) | |
download | voidsky-1cdbfc709235ed1933ba51403d941762f384690b.tar.zst |
Live via service config (#8378)
* add config (with temp config) * only allow whitelisted domains in form * move config to generic config * use array-based config * update deps * rm expect-error
Diffstat (limited to 'src/components/live')
-rw-r--r-- | src/components/live/GoLiveDialog.tsx | 21 | ||||
-rw-r--r-- | src/components/live/temp.ts | 41 |
2 files changed, 18 insertions, 44 deletions
diff --git a/src/components/live/GoLiveDialog.tsx b/src/components/live/GoLiveDialog.tsx index 2fad009fd..027447272 100644 --- a/src/components/live/GoLiveDialog.tsx +++ b/src/components/live/GoLiveDialog.tsx @@ -10,7 +10,8 @@ import {cleanError} from '#/lib/strings/errors' import {toNiceDomain} from '#/lib/strings/url-helpers' import {definitelyUrl} from '#/lib/strings/url-helpers' import {useModerationOpts} from '#/state/preferences/moderation-opts' -import {useAgent} from '#/state/session' +import {useLiveNowConfig} from '#/state/service-config' +import {useAgent, useSession} from '#/state/session' import {useTickEveryMinute} from '#/state/shell' import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' import {atoms as a, ios, native, platform, useTheme, web} from '#/alf' @@ -58,6 +59,10 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { const [duration, setDuration] = useState(60) const moderationOpts = useModerationOpts() const tick = useTickEveryMinute() + const liveNowConfig = useLiveNowConfig() + const {currentAccount} = useSession() + + const config = liveNowConfig.find(cfg => cfg.did === currentAccount?.did) const time = useCallback( (offset: number) => { @@ -79,7 +84,6 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { const liveLinkUrl = definitelyUrl(liveLink) const debouncedUrl = useDebouncedValue(liveLinkUrl, 500) - const hasLink = !!debouncedUrl const { data: linkMeta, @@ -91,6 +95,13 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { queryKey: ['link-meta', debouncedUrl], queryFn: async () => { if (!debouncedUrl) return null + if (!config) throw new Error(_(msg`You are not allowed to go live`)) + + const urlp = new URL(debouncedUrl) + if (!config.domains.includes(urlp.hostname)) { + throw new Error(_(msg`${urlp.hostname} is not a valid URL`)) + } + return getLinkMeta(agent, debouncedUrl) }, }) @@ -101,6 +112,10 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { error: goLiveError, } = useUpsertLiveStatusMutation(duration, linkMeta) + const isSourceInvalid = !!liveLinkError || !!linkMetaError + + const hasLink = !!debouncedUrl && !isSourceInvalid + return ( <Dialog.ScrollableInner label={_(msg`Go Live`)} @@ -136,7 +151,7 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { <TextField.LabelText> <Trans>Live link</Trans> </TextField.LabelText> - <TextField.Root isInvalid={!!liveLinkError || !!linkMetaError}> + <TextField.Root isInvalid={isSourceInvalid}> <TextField.Input label={_(msg`Live link`)} placeholder={_(msg`www.mylivestream.tv`)} diff --git a/src/components/live/temp.ts b/src/components/live/temp.ts deleted file mode 100644 index fb26b8c06..000000000 --- a/src/components/live/temp.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {type AppBskyActorDefs, AppBskyEmbedExternal} from '@atproto/api' - -import {DISCOVER_DEBUG_DIDS} from '#/lib/constants' -import type * as bsky from '#/types/bsky' - -export const LIVE_DIDS: Record<string, true> = { - 'did:plc:7sfnardo5xxznxc6esxc5ooe': true, // nba.com - 'did:plc:gx6fyi3jcfxd7ammq2t7mzp2': true, // rtgame.bsky.social -} - -export const LIVE_SOURCES: Record<string, true> = { - 'nba.com': true, - 'twitch.tv': true, -} - -// TEMP: dumb gating -export function temp__canBeLive(profile: bsky.profile.AnyProfileView) { - if (__DEV__) - return !!DISCOVER_DEBUG_DIDS[profile.did] || !!LIVE_DIDS[profile.did] - return !!LIVE_DIDS[profile.did] -} - -export function temp__canGoLive(profile: bsky.profile.AnyProfileView) { - if (__DEV__) return true - return !!LIVE_DIDS[profile.did] -} - -// status must have a embed, and the embed must be an approved host for the status to be valid -export function temp__isStatusValid(status: AppBskyActorDefs.StatusView) { - if (status.status !== 'app.bsky.actor.status#live') return false - try { - if (AppBskyEmbedExternal.isView(status.embed)) { - const url = new URL(status.embed.external.uri) - return !!LIVE_SOURCES[url.hostname] - } else { - return false - } - } catch { - return false - } -} |