sepia-search-motore-di-rice.../server/lib/meilisearch/meilisearch-channels.ts

153 lines
4.6 KiB
TypeScript

import { createHash } from 'crypto'
import { logger } from '../../helpers/logger'
import { client } from '../../helpers/meilisearch'
import { CONFIG } from '../../initializers/constants'
import { DBChannel, APIVideoChannel, IndexableChannel } from '../../types/channel.model'
import { ChannelsSearchQuery } from '../../types/search-query/channel-search.model'
import { buildInValuesArray, buildSort, extractSearchQueryResult } from './meilisearch-queries'
import {
formatActorImageForAPI,
formatActorImageForDB,
formatActorImagesForAPI,
formatActorImagesForDB
} from './shared/meilisearch-avatar'
export async function queryChannels (search: ChannelsSearchQuery) {
const filter: string[] = [ 'videosCount != 0' ]
if (search.host) filter.push(`host = '${search.host}'`)
if (search.blockedAccounts && search.blockedAccounts.length !== 0) {
filter.push(`ownerAccount.handle NOT IN ${buildInValuesArray(search.blockedAccounts)}`)
}
if (search.handles && search.handles.length !== 0) {
filter.push(`handle IN ${buildInValuesArray(search.handles)}`)
}
if (search.blockedHosts && search.blockedHosts.length !== 0) {
filter.push(`host NOT IN ${buildInValuesArray(search.blockedHosts)}`)
}
logger.debug({ filter }, 'Will query Meilisearch for channels.')
const result = await client.index(CONFIG.MEILISEARCH.INDEXES.CHANNELS).search(search.search, {
offset: search.start,
limit: search.count,
sort: buildSort(search.sort),
showRankingScore: true,
filter
})
return extractSearchQueryResult(result)
}
export function formatChannelForAPI (c: DBChannel, fromHost?: string): APIVideoChannel {
return {
id: c.id,
score: c._rankingScore,
url: c.url,
name: c.name,
host: c.host,
followingCount: c.followingCount,
followersCount: c.followersCount,
createdAt: new Date(c.createdAt),
updatedAt: new Date(c.updatedAt),
avatar: formatActorImageForAPI(c.avatar),
avatars: formatActorImagesForAPI(c.avatars, c.avatar),
banner: formatActorImageForAPI(c.banner),
banners: formatActorImagesForAPI(c.banners, c.banner),
displayName: c.displayName,
description: c.description,
support: c.support,
isLocal: fromHost === c.host,
videosCount: c.videosCount || 0,
ownerAccount: {
id: c.ownerAccount.id,
url: c.ownerAccount.url,
displayName: c.ownerAccount.displayName,
description: c.ownerAccount.description,
name: c.ownerAccount.name,
host: c.ownerAccount.host,
followingCount: c.ownerAccount.followingCount,
followersCount: c.ownerAccount.followersCount,
createdAt: new Date(c.ownerAccount.createdAt),
updatedAt: new Date(c.ownerAccount.updatedAt),
avatar: formatActorImageForAPI(c.ownerAccount.avatar),
avatars: formatActorImagesForAPI(c.ownerAccount.avatars, c.ownerAccount.avatar)
}
}
}
export function formatChannelForDB (c: IndexableChannel): DBChannel {
if (!c.ownerAccount) return undefined
return {
primaryKey: buildDBChannelPrimaryKey(c),
id: c.id,
name: c.name,
host: c.host,
url: c.url,
avatar: formatActorImageForDB(c.avatar, c.host),
avatars: formatActorImagesForDB(c.avatars, c.host),
banner: formatActorImageForDB(c.banner, c.host),
banners: formatActorImagesForDB(c.banners, c.host),
displayName: c.displayName,
indexedAt: new Date().getTime(),
createdAt: new Date(c.createdAt).getTime(),
updatedAt: new Date(c.updatedAt).getTime(),
followingCount: c.followingCount,
followersCount: c.followersCount,
description: c.description,
support: c.support,
videosCount: c.videosCount,
handle: `${c.name}@${c.host}`,
ownerAccount: {
id: c.ownerAccount.id,
url: c.ownerAccount.url,
displayName: c.ownerAccount.displayName,
description: c.ownerAccount.description,
name: c.ownerAccount.name,
host: c.ownerAccount.host,
followingCount: c.ownerAccount.followingCount,
followersCount: c.ownerAccount.followersCount,
createdAt: new Date(c.ownerAccount.createdAt).getTime(),
updatedAt: new Date(c.ownerAccount.updatedAt).getTime(),
handle: `${c.ownerAccount.name}@${c.ownerAccount.host}`,
avatar: formatActorImageForDB(c.ownerAccount.avatar, c.ownerAccount.host),
avatars: formatActorImagesForDB(c.ownerAccount.avatars, c.ownerAccount.host)
}
}
}
export function buildDBChannelPrimaryKey (c: { id: number, host: string }) {
return `${c.id}_${md5(c.host)}`
}
// Collisions are fine, we just want to generate a primary key in an efficient way
function md5 (value: string) {
return createHash('md5').update(value).digest('hex')
}