diff options
Diffstat (limited to 'server/controllers/api/search/search-video-channels.ts')
-rw-r--r-- | server/controllers/api/search/search-video-channels.ts | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/server/controllers/api/search/search-video-channels.ts b/server/controllers/api/search/search-video-channels.ts deleted file mode 100644 index 1d2a9d235..000000000 --- a/server/controllers/api/search/search-video-channels.ts +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | import express from 'express' | ||
2 | import { sanitizeUrl } from '@server/helpers/core-utils' | ||
3 | import { pickSearchChannelQuery } from '@server/helpers/query' | ||
4 | import { doJSONRequest } from '@server/helpers/requests' | ||
5 | import { CONFIG } from '@server/initializers/config' | ||
6 | import { WEBSERVER } from '@server/initializers/constants' | ||
7 | import { findLatestAPRedirection } from '@server/lib/activitypub/activity' | ||
8 | import { Hooks } from '@server/lib/plugins/hooks' | ||
9 | import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search' | ||
10 | import { getServerActor } from '@server/models/application/application' | ||
11 | import { HttpStatusCode, ResultList, VideoChannel } from '@shared/models' | ||
12 | import { VideoChannelsSearchQueryAfterSanitize } from '../../../../shared/models/search' | ||
13 | import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils' | ||
14 | import { logger } from '../../../helpers/logger' | ||
15 | import { getFormattedObjects } from '../../../helpers/utils' | ||
16 | import { getOrCreateAPActor, loadActorUrlOrGetFromWebfinger } from '../../../lib/activitypub/actors' | ||
17 | import { | ||
18 | asyncMiddleware, | ||
19 | openapiOperationDoc, | ||
20 | optionalAuthenticate, | ||
21 | paginationValidator, | ||
22 | setDefaultPagination, | ||
23 | setDefaultSearchSort, | ||
24 | videoChannelsListSearchValidator, | ||
25 | videoChannelsSearchSortValidator | ||
26 | } from '../../../middlewares' | ||
27 | import { VideoChannelModel } from '../../../models/video/video-channel' | ||
28 | import { MChannelAccountDefault } from '../../../types/models' | ||
29 | import { searchLocalUrl } from './shared' | ||
30 | |||
31 | const searchChannelsRouter = express.Router() | ||
32 | |||
33 | searchChannelsRouter.get('/video-channels', | ||
34 | openapiOperationDoc({ operationId: 'searchChannels' }), | ||
35 | paginationValidator, | ||
36 | setDefaultPagination, | ||
37 | videoChannelsSearchSortValidator, | ||
38 | setDefaultSearchSort, | ||
39 | optionalAuthenticate, | ||
40 | videoChannelsListSearchValidator, | ||
41 | asyncMiddleware(searchVideoChannels) | ||
42 | ) | ||
43 | |||
44 | // --------------------------------------------------------------------------- | ||
45 | |||
46 | export { searchChannelsRouter } | ||
47 | |||
48 | // --------------------------------------------------------------------------- | ||
49 | |||
50 | function searchVideoChannels (req: express.Request, res: express.Response) { | ||
51 | const query = pickSearchChannelQuery(req.query) | ||
52 | const search = query.search || '' | ||
53 | |||
54 | const parts = search.split('@') | ||
55 | |||
56 | // Handle strings like @toto@example.com | ||
57 | if (parts.length === 3 && parts[0].length === 0) parts.shift() | ||
58 | const isWebfingerSearch = parts.length === 2 && parts.every(p => p && !p.includes(' ')) | ||
59 | |||
60 | if (isURISearch(search) || isWebfingerSearch) return searchVideoChannelURI(search, res) | ||
61 | |||
62 | // @username -> username to search in DB | ||
63 | if (search.startsWith('@')) query.search = search.replace(/^@/, '') | ||
64 | |||
65 | if (isSearchIndexSearch(query)) { | ||
66 | return searchVideoChannelsIndex(query, res) | ||
67 | } | ||
68 | |||
69 | return searchVideoChannelsDB(query, res) | ||
70 | } | ||
71 | |||
72 | async function searchVideoChannelsIndex (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) { | ||
73 | const result = await buildMutedForSearchIndex(res) | ||
74 | |||
75 | const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-channels.index.list.params') | ||
76 | |||
77 | const url = sanitizeUrl(CONFIG.SEARCH.SEARCH_INDEX.URL) + '/api/v1/search/video-channels' | ||
78 | |||
79 | try { | ||
80 | logger.debug('Doing video channels search index request on %s.', url, { body }) | ||
81 | |||
82 | const { body: searchIndexResult } = await doJSONRequest<ResultList<VideoChannel>>(url, { method: 'POST', json: body }) | ||
83 | const jsonResult = await Hooks.wrapObject(searchIndexResult, 'filter:api.search.video-channels.index.list.result') | ||
84 | |||
85 | return res.json(jsonResult) | ||
86 | } catch (err) { | ||
87 | logger.warn('Cannot use search index to make video channels search.', { err }) | ||
88 | |||
89 | return res.fail({ | ||
90 | status: HttpStatusCode.INTERNAL_SERVER_ERROR_500, | ||
91 | message: 'Cannot use search index to make video channels search' | ||
92 | }) | ||
93 | } | ||
94 | } | ||
95 | |||
96 | async function searchVideoChannelsDB (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) { | ||
97 | const serverActor = await getServerActor() | ||
98 | |||
99 | const apiOptions = await Hooks.wrapObject({ | ||
100 | ...query, | ||
101 | |||
102 | actorId: serverActor.id | ||
103 | }, 'filter:api.search.video-channels.local.list.params') | ||
104 | |||
105 | const resultList = await Hooks.wrapPromiseFun( | ||
106 | VideoChannelModel.searchForApi, | ||
107 | apiOptions, | ||
108 | 'filter:api.search.video-channels.local.list.result' | ||
109 | ) | ||
110 | |||
111 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
112 | } | ||
113 | |||
114 | async function searchVideoChannelURI (search: string, res: express.Response) { | ||
115 | let videoChannel: MChannelAccountDefault | ||
116 | let uri = search | ||
117 | |||
118 | if (!isURISearch(search)) { | ||
119 | try { | ||
120 | uri = await loadActorUrlOrGetFromWebfinger(search) | ||
121 | } catch (err) { | ||
122 | logger.warn('Cannot load actor URL or get from webfinger.', { search, err }) | ||
123 | |||
124 | return res.json({ total: 0, data: [] }) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (isUserAbleToSearchRemoteURI(res)) { | ||
129 | try { | ||
130 | const latestUri = await findLatestAPRedirection(uri) | ||
131 | |||
132 | const actor = await getOrCreateAPActor(latestUri, 'all', true, true) | ||
133 | videoChannel = actor.VideoChannel | ||
134 | } catch (err) { | ||
135 | logger.info('Cannot search remote video channel %s.', uri, { err }) | ||
136 | } | ||
137 | } else { | ||
138 | videoChannel = await searchLocalUrl(sanitizeLocalUrl(uri), url => VideoChannelModel.loadByUrlAndPopulateAccount(url)) | ||
139 | } | ||
140 | |||
141 | return res.json({ | ||
142 | total: videoChannel ? 1 : 0, | ||
143 | data: videoChannel ? [ videoChannel.toFormattedJSON() ] : [] | ||
144 | }) | ||
145 | } | ||
146 | |||
147 | function sanitizeLocalUrl (url: string) { | ||
148 | if (!url) return '' | ||
149 | |||
150 | // Handle alternative channel URLs | ||
151 | return url.replace(new RegExp('^' + WEBSERVER.URL + '/c/'), WEBSERVER.URL + '/video-channels/') | ||
152 | } | ||