mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {useEffect, useState} from 'react'
2
3import {logger} from '#/logger'
4import {useFetchDid} from '#/state/queries/handle'
5import {useGetPost} from '#/state/queries/post'
6import {useAgent} from '#/state/session'
7import * as apilib from 'lib/api/index'
8import {POST_IMG_MAX} from 'lib/constants'
9import {
10 getFeedAsEmbed,
11 getListAsEmbed,
12 getPostAsQuote,
13 getStarterPackAsEmbed,
14} from 'lib/link-meta/bsky'
15import {getLinkMeta} from 'lib/link-meta/link-meta'
16import {resolveShortLink} from 'lib/link-meta/resolve-short-link'
17import {downloadAndResize} from 'lib/media/manip'
18import {
19 isBskyCustomFeedUrl,
20 isBskyListUrl,
21 isBskyPostUrl,
22 isBskyStarterPackUrl,
23 isBskyStartUrl,
24 isShortLink,
25} from 'lib/strings/url-helpers'
26import {ImageModel} from 'state/models/media/image'
27import {ComposerOpts} from 'state/shell/composer'
28
29export function useExternalLinkFetch({
30 setQuote,
31}: {
32 setQuote: (opts: ComposerOpts['quote']) => void
33}) {
34 const [extLink, setExtLink] = useState<apilib.ExternalEmbedDraft | undefined>(
35 undefined,
36 )
37 const getPost = useGetPost()
38 const fetchDid = useFetchDid()
39 const agent = useAgent()
40
41 useEffect(() => {
42 let aborted = false
43 const cleanup = () => {
44 aborted = true
45 }
46 if (!extLink) {
47 return cleanup
48 }
49 if (!extLink.meta) {
50 if (isBskyPostUrl(extLink.uri)) {
51 getPostAsQuote(getPost, extLink.uri).then(
52 newQuote => {
53 if (aborted) {
54 return
55 }
56 setQuote(newQuote)
57 setExtLink(undefined)
58 },
59 err => {
60 logger.error('Failed to fetch post for quote embedding', {
61 message: err.toString(),
62 })
63 setExtLink(undefined)
64 },
65 )
66 } else if (isBskyCustomFeedUrl(extLink.uri)) {
67 getFeedAsEmbed(agent, fetchDid, extLink.uri).then(
68 ({embed, meta}) => {
69 if (aborted) {
70 return
71 }
72 setExtLink({
73 uri: extLink.uri,
74 isLoading: false,
75 meta,
76 embed,
77 })
78 },
79 err => {
80 logger.error('Failed to fetch feed for embedding', {message: err})
81 setExtLink(undefined)
82 },
83 )
84 } else if (isBskyListUrl(extLink.uri)) {
85 getListAsEmbed(agent, fetchDid, extLink.uri).then(
86 ({embed, meta}) => {
87 if (aborted) {
88 return
89 }
90 setExtLink({
91 uri: extLink.uri,
92 isLoading: false,
93 meta,
94 embed,
95 })
96 },
97 err => {
98 logger.error('Failed to fetch list for embedding', {message: err})
99 setExtLink(undefined)
100 },
101 )
102 } else if (
103 isBskyStartUrl(extLink.uri) ||
104 isBskyStarterPackUrl(extLink.uri)
105 ) {
106 getStarterPackAsEmbed(agent, fetchDid, extLink.uri).then(
107 ({embed, meta}) => {
108 if (aborted) {
109 return
110 }
111 setExtLink({
112 uri: extLink.uri,
113 isLoading: false,
114 meta,
115 embed,
116 })
117 },
118 )
119 } else if (isShortLink(extLink.uri)) {
120 if (isShortLink(extLink.uri)) {
121 resolveShortLink(extLink.uri).then(res => {
122 if (res && res !== extLink.uri) {
123 setExtLink({
124 uri: res,
125 isLoading: true,
126 })
127 }
128 })
129 }
130 } else {
131 getLinkMeta(agent, extLink.uri).then(meta => {
132 if (aborted) {
133 return
134 }
135 setExtLink({
136 uri: extLink.uri,
137 isLoading: !!meta.image,
138 meta,
139 })
140 })
141 }
142 return cleanup
143 }
144 if (extLink.isLoading && extLink.meta?.image && !extLink.localThumb) {
145 downloadAndResize({
146 uri: extLink.meta.image,
147 width: POST_IMG_MAX.width,
148 height: POST_IMG_MAX.height,
149 mode: 'contain',
150 maxSize: POST_IMG_MAX.size,
151 timeout: 15e3,
152 })
153 .catch(() => undefined)
154 .then(localThumb => {
155 if (aborted) {
156 return
157 }
158 setExtLink({
159 ...extLink,
160 isLoading: false, // done
161 localThumb: localThumb ? new ImageModel(localThumb) : undefined,
162 })
163 })
164 return cleanup
165 }
166 if (extLink.isLoading) {
167 setExtLink({
168 ...extLink,
169 isLoading: false, // done
170 })
171 }
172 return cleanup
173 }, [extLink, setQuote, getPost, fetchDid, agent])
174
175 return {extLink, setExtLink}
176}