2022-01-08 18:13:56 +00:00
|
|
|
import { assertSuccessJsonResponse } from '../../assertSuccessJsonResponse'
|
|
|
|
import { z } from 'zod'
|
|
|
|
import { getDefaultTimeoutMilliseconds } from '../../getDefaultTimeoutMilliseconds'
|
2022-04-17 12:03:53 +00:00
|
|
|
import { NoMoreFeedsError } from '../NoMoreFeedsError'
|
|
|
|
import { FeedProviderMethod } from '../FeedProviderMethod'
|
2022-09-18 11:32:25 +00:00
|
|
|
import { FeedData } from '../FeedData'
|
|
|
|
import { FieldData } from '../FieldData'
|
2022-01-08 18:13:56 +00:00
|
|
|
|
|
|
|
const limit = 100
|
|
|
|
|
|
|
|
const emojiSchema = z.object({
|
|
|
|
name: z.string(),
|
|
|
|
url: z.string()
|
|
|
|
})
|
|
|
|
|
|
|
|
const schema = z.array(
|
|
|
|
z.object({
|
|
|
|
id: z.string(),
|
|
|
|
name: z.string().nullable(),
|
|
|
|
username: z.string(),
|
2022-01-08 18:25:44 +00:00
|
|
|
avatarUrl: z.string().nullable(),
|
2022-01-08 18:13:56 +00:00
|
|
|
isBot: z.boolean(),
|
|
|
|
emojis: z.array(emojiSchema),
|
|
|
|
createdAt: z.string(),
|
2022-01-08 18:25:44 +00:00
|
|
|
updatedAt: z.string().nullable(),
|
2022-01-08 18:13:56 +00:00
|
|
|
isLocked: z.boolean(),
|
|
|
|
description: z.string().nullable(),
|
|
|
|
location: z.string().nullable(),
|
|
|
|
birthday: z.string().nullable(),
|
|
|
|
lang: z.string().nullable(),
|
|
|
|
fields: z.array(
|
|
|
|
z.object({
|
|
|
|
name: z.string(),
|
|
|
|
value: z.string()
|
|
|
|
})
|
|
|
|
),
|
|
|
|
followersCount: z.number(),
|
|
|
|
followingCount: z.number(),
|
|
|
|
notesCount: z.number()
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
type Emoji = z.infer<typeof emojiSchema>
|
|
|
|
|
|
|
|
const replaceEmojis = (text: string, emojis: Emoji[]): string => {
|
2022-09-18 11:32:25 +00:00
|
|
|
emojis.forEach((emoji) => {
|
2022-01-08 18:13:56 +00:00
|
|
|
text = text.replace(
|
|
|
|
RegExp(`:${emoji.name}:`, 'gi'),
|
2022-09-18 11:32:25 +00:00
|
|
|
`<img draggable="false" class="emoji" title="${emoji.name}" alt="${emoji.name}" src="${emoji.url}" />`
|
2022-01-08 18:13:56 +00:00
|
|
|
)
|
|
|
|
})
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
|
2022-09-18 11:32:25 +00:00
|
|
|
const parseDescription = (description: string | null): string => {
|
2022-01-08 18:13:56 +00:00
|
|
|
if (typeof description !== 'string') {
|
|
|
|
return ''
|
|
|
|
}
|
2022-09-18 11:32:25 +00:00
|
|
|
return description
|
|
|
|
.split('\n\n')
|
|
|
|
.map((paragraph) => {
|
|
|
|
paragraph = paragraph.replace('\n', '</br>\n')
|
|
|
|
return `<p>${paragraph}</p>`
|
|
|
|
})
|
|
|
|
.join('\n')
|
2022-01-08 18:13:56 +00:00
|
|
|
}
|
|
|
|
|
2022-09-18 11:32:25 +00:00
|
|
|
export const retrieveUsersPage: FeedProviderMethod = async (
|
|
|
|
domain,
|
2022-11-22 15:37:11 +00:00
|
|
|
page,
|
|
|
|
robotsTxt
|
2022-09-18 11:32:25 +00:00
|
|
|
): Promise<FeedData[]> => {
|
2022-11-22 15:37:11 +00:00
|
|
|
const response = await robotsTxt.postIfAllowed(
|
|
|
|
`https://${domain}/api/users`,
|
2022-09-18 11:32:25 +00:00
|
|
|
{
|
|
|
|
state: 'all',
|
|
|
|
origin: 'local',
|
|
|
|
sort: '+createdAt',
|
|
|
|
limit,
|
|
|
|
offset: limit * page
|
|
|
|
},
|
|
|
|
{
|
|
|
|
timeout: getDefaultTimeoutMilliseconds()
|
|
|
|
}
|
|
|
|
)
|
2022-04-17 12:03:53 +00:00
|
|
|
assertSuccessJsonResponse(response)
|
|
|
|
const responseData = schema.parse(response.data)
|
|
|
|
if (responseData.length === 0) {
|
|
|
|
throw new NoMoreFeedsError('user')
|
2022-01-08 18:13:56 +00:00
|
|
|
}
|
2022-09-18 11:32:25 +00:00
|
|
|
return responseData.map((item) => {
|
|
|
|
return {
|
|
|
|
name: item.username,
|
|
|
|
displayName: replaceEmojis(item.name ?? item.username, item.emojis),
|
|
|
|
description: replaceEmojis(
|
|
|
|
parseDescription(item.description ?? ''),
|
|
|
|
item.emojis
|
|
|
|
),
|
|
|
|
followersCount: item.followersCount,
|
|
|
|
followingCount: item.followingCount,
|
|
|
|
statusesCount: item.notesCount,
|
|
|
|
bot: item.isBot,
|
|
|
|
url: `https://${domain}/@${item.username}`,
|
|
|
|
avatar: item.avatarUrl ?? undefined,
|
|
|
|
locked: item.isLocked,
|
|
|
|
lastStatusAt:
|
|
|
|
item.updatedAt !== null ? new Date(item.updatedAt) : undefined,
|
|
|
|
createdAt: new Date(item.createdAt),
|
|
|
|
fields: [
|
|
|
|
...item.fields.map((field) => {
|
|
|
|
return {
|
|
|
|
name: replaceEmojis(field.name, item.emojis),
|
|
|
|
value: replaceEmojis(field.value, item.emojis),
|
|
|
|
verifiedAt: undefined
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
...([
|
|
|
|
{ name: 'Location', value: item.location, verifiedAt: undefined },
|
|
|
|
{ name: 'Birthday', value: item.birthday, verifiedAt: undefined },
|
|
|
|
{ name: 'Language', value: item.lang, verifiedAt: undefined }
|
|
|
|
].filter((field) => field.value !== null) as FieldData[])
|
|
|
|
],
|
|
|
|
type: 'account',
|
2022-11-22 16:01:25 +00:00
|
|
|
parentFeed: undefined,
|
|
|
|
indexable: true
|
2022-04-17 12:03:53 +00:00
|
|
|
}
|
2022-09-18 11:32:25 +00:00
|
|
|
})
|
2022-01-08 18:13:56 +00:00
|
|
|
}
|