personal web client for Bluesky
typescript solidjs bluesky atcute
at trunk 2.4 kB view raw
1import { isDid, isHandle, isRecordKey, isTid } from '@atcute/lexicons/syntax'; 2 3import { safeUrlParse } from '~/api/utils/strings'; 4 5import { 6 BSKY_FEED_LINK_RE, 7 BSKY_GO_SHORTLINK_RE, 8 BSKY_HASHTAG_LINK_RE, 9 BSKY_LIST_LINK_RE, 10 BSKY_POST_LINK_RE, 11 BSKY_PROFILE_LINK_RE, 12 BSKY_SEARCH_LINK_RE, 13 BSKY_STARTERPACK_LINK_RE, 14} from './bsky/url'; 15 16export const redirectBskyUrl = (rawUrl: string): string | null | undefined => { 17 const url = safeUrlParse(rawUrl); 18 if (!url) { 19 return; 20 } 21 22 const host = url.host; 23 const pathname = url.pathname; 24 let match: RegExpExecArray | null | undefined; 25 26 if (host === 'bsky.app' || host === 'staging.bsky.app' || host === 'main.bsky.dev') { 27 if ((match = BSKY_PROFILE_LINK_RE.exec(pathname))) { 28 const [, actor] = match; 29 30 if (!isHandle(actor) && !isDid(actor)) { 31 return null; 32 } 33 34 return `/${match[1]}`; 35 } 36 37 if ((match = BSKY_POST_LINK_RE.exec(pathname))) { 38 const [, actor, rkey] = match; 39 40 if (!isHandle(actor) && !isDid(actor)) { 41 return null; 42 } 43 if (!isTid(rkey)) { 44 return null; 45 } 46 47 return `/${actor}/${rkey}`; 48 } 49 50 if ((match = BSKY_FEED_LINK_RE.exec(pathname))) { 51 const [, actor, rkey] = match; 52 53 if (!isHandle(actor) && !isDid(actor)) { 54 return null; 55 } 56 if (!isRecordKey(rkey)) { 57 return null; 58 } 59 60 return `/${actor}/feeds/${rkey}`; 61 } 62 63 if ((match = BSKY_LIST_LINK_RE.exec(pathname))) { 64 const [, actor, rkey] = match; 65 66 if (!isHandle(actor) && !isDid(actor)) { 67 return null; 68 } 69 if (!isRecordKey(rkey)) { 70 return null; 71 } 72 73 return `/${actor}/lists/${rkey}`; 74 } 75 76 if ((match = BSKY_STARTERPACK_LINK_RE.exec(pathname))) { 77 const [, _page, actor, rkey] = match; 78 79 if (!isHandle(actor) && !isDid(actor)) { 80 return null; 81 } 82 if (!isRecordKey(rkey)) { 83 return null; 84 } 85 86 return `/${actor}/packs/${rkey}`; 87 } 88 89 if ((match = BSKY_SEARCH_LINK_RE.exec(pathname))) { 90 const query = url.searchParams.get('q'); 91 92 if (!query) { 93 return null; 94 } 95 96 return `/search?q=${encodeURIComponent(query)}`; 97 } 98 99 if ((match = BSKY_HASHTAG_LINK_RE.exec(pathname))) { 100 const [, tag] = match; 101 102 return `/search?q=${encodeURIComponent('#' + tag)}`; 103 } 104 105 return null; 106 } 107 108 if (host === 'go.bsky.app') { 109 if ((match = BSKY_GO_SHORTLINK_RE.exec(pathname))) { 110 const [, id] = match; 111 112 return `/go/${id}`; 113 } 114 } 115 116 return; 117};