Merge branch 'api-refactor' into shigusegubu-themes3
This commit is contained in:
commit
6753de2986
9 changed files with 305 additions and 188 deletions
|
|
@ -106,7 +106,7 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
|
||||||
const swBundle = await build(config)
|
const swBundle = await build(config)
|
||||||
return swBundle.output[0]
|
return swBundle.output[0]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error building ServiceWorker:' , e)
|
console.error('Error building ServiceWorker:', e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -119,7 +119,7 @@ export const buildSwPlugin = ({ swSrc, swDest }) => {
|
||||||
try {
|
try {
|
||||||
await build(config)
|
await build(config)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error building ServiceWorker:' , e)
|
console.error('Error building ServiceWorker:', e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -798,8 +798,11 @@ const users = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useMergedConfigStore().mergedConfig.useStreamingApi) {
|
if (useMergedConfigStore().mergedConfig.useStreamingApi) {
|
||||||
dispatch('fetchTimeline', { timeline: 'friends', since: null })
|
dispatch('fetchTimeline', {
|
||||||
dispatch('fetchNotifications', { since: null })
|
timeline: 'friends',
|
||||||
|
sinceId: null,
|
||||||
|
})
|
||||||
|
dispatch('fetchNotifications', { sinceId: null })
|
||||||
dispatch('enableMastoSockets', true)
|
dispatch('enableMastoSockets', true)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(
|
console.error(
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import {
|
||||||
parseStatus,
|
parseStatus,
|
||||||
parseUser,
|
parseUser,
|
||||||
} from '../entity_normalizer/entity_normalizer.service.js'
|
} from '../entity_normalizer/entity_normalizer.service.js'
|
||||||
import { promisedRequest } from './helpers.js'
|
import { paramsString, promisedRequest } from './helpers.js'
|
||||||
|
|
||||||
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
|
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
|
||||||
|
|
||||||
|
|
@ -46,8 +46,16 @@ const MASTODON_UNRETWEET_URL = (id) => `/api/v1/statuses/${id}/unreblog`
|
||||||
const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}`
|
const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}`
|
||||||
const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow`
|
const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow`
|
||||||
const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow`
|
const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow`
|
||||||
const MASTODON_FOLLOWING_URL = (id) => `/api/v1/accounts/${id}/following`
|
const MASTODON_FOLLOWING_URL = (
|
||||||
const MASTODON_FOLLOWERS_URL = (id) => `/api/v1/accounts/${id}/followers`
|
id,
|
||||||
|
{ minId, maxId, sinceId, limit, withRelationships },
|
||||||
|
) =>
|
||||||
|
`/api/v1/accounts/${id}/following${paramsString({ minId, maxId, sinceId, limit, withRelationships })}`
|
||||||
|
const MASTODON_FOLLOWERS_URL = (
|
||||||
|
id,
|
||||||
|
{ minId, maxId, sinceId, limit, withRelationships },
|
||||||
|
) =>
|
||||||
|
`/api/v1/accounts/${id}/followers${paramsString({ minId, maxId, sinceId, limit, withRelationships })}`
|
||||||
const MASTODON_FOLLOW_REQUESTS_URL = '/api/v1/follow_requests'
|
const MASTODON_FOLLOW_REQUESTS_URL = '/api/v1/follow_requests'
|
||||||
const MASTODON_APPROVE_USER_URL = (id) =>
|
const MASTODON_APPROVE_USER_URL = (id) =>
|
||||||
`/api/v1/follow_requests/${id}/authorize`
|
`/api/v1/follow_requests/${id}/authorize`
|
||||||
|
|
@ -61,7 +69,8 @@ const MASTODON_STATUS_SOURCE_URL = (id) => `/api/v1/statuses/${id}/source`
|
||||||
const MASTODON_STATUS_HISTORY_URL = (id) => `/api/v1/statuses/${id}/history`
|
const MASTODON_STATUS_HISTORY_URL = (id) => `/api/v1/statuses/${id}/history`
|
||||||
const MASTODON_USER_URL = '/api/v1/accounts'
|
const MASTODON_USER_URL = '/api/v1/accounts'
|
||||||
const MASTODON_USER_LOOKUP_URL = '/api/v1/accounts/lookup'
|
const MASTODON_USER_LOOKUP_URL = '/api/v1/accounts/lookup'
|
||||||
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
|
const MASTODON_USER_RELATIONSHIPS_URL = ({ id, withSuspended }) =>
|
||||||
|
`/api/v1/accounts/relationships/${paramsString({ id, withSuspended })}`
|
||||||
const MASTODON_USER_TIMELINE_URL = (id) => `/api/v1/accounts/${id}/statuses`
|
const MASTODON_USER_TIMELINE_URL = (id) => `/api/v1/accounts/${id}/statuses`
|
||||||
const MASTODON_USER_IN_LISTS = (id) => `/api/v1/accounts/${id}/lists`
|
const MASTODON_USER_IN_LISTS = (id) => `/api/v1/accounts/${id}/lists`
|
||||||
const MASTODON_LIST_URL = (id) => `/api/v1/lists/${id}`
|
const MASTODON_LIST_URL = (id) => `/api/v1/lists/${id}`
|
||||||
|
|
@ -70,8 +79,20 @@ const MASTODON_LIST_ACCOUNTS_URL = (id) => `/api/v1/lists/${id}/accounts`
|
||||||
const MASTODON_TAG_TIMELINE_URL = (tag) => `/api/v1/timelines/tag/${tag}`
|
const MASTODON_TAG_TIMELINE_URL = (tag) => `/api/v1/timelines/tag/${tag}`
|
||||||
const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
|
const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
|
||||||
const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble'
|
const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble'
|
||||||
const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/'
|
const MASTODON_USER_BLOCKS_URL = ({
|
||||||
const MASTODON_USER_MUTES_URL = '/api/v1/mutes/'
|
maxId,
|
||||||
|
sinceId,
|
||||||
|
limit,
|
||||||
|
withRelationships,
|
||||||
|
}) =>
|
||||||
|
`/api/v1/blocks/${paramsString({ maxId, sinceId, limit, withRelationships })}`
|
||||||
|
const MASTODON_USER_MUTES_URL = ({
|
||||||
|
maxId,
|
||||||
|
sinceId,
|
||||||
|
limit,
|
||||||
|
withRelationships,
|
||||||
|
}) =>
|
||||||
|
`/api/v1/mutes/${paramsString({ maxId, sinceId, limit, withRelationships })}`
|
||||||
const MASTODON_BLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/block`
|
const MASTODON_BLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/block`
|
||||||
const MASTODON_UNBLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/unblock`
|
const MASTODON_UNBLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/unblock`
|
||||||
const MASTODON_MUTE_USER_URL = (id) => `/api/v1/accounts/${id}/mute`
|
const MASTODON_MUTE_USER_URL = (id) => `/api/v1/accounts/${id}/mute`
|
||||||
|
|
@ -113,12 +134,14 @@ const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) =>
|
||||||
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
`/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||||
const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats'
|
const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats'
|
||||||
const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}`
|
const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}`
|
||||||
const PLEROMA_CHAT_MESSAGES_URL = (id) => `/api/v1/pleroma/chats/${id}/messages`
|
const PLEROMA_CHAT_MESSAGES_URL = (id, { maxId, sinceId, limit }) =>
|
||||||
|
`/api/v1/pleroma/chats/${id}/messages${paramsString({ maxId, sinceId, limit })}`
|
||||||
const PLEROMA_CHAT_READ_URL = (id) => `/api/v1/pleroma/chats/${id}/read`
|
const PLEROMA_CHAT_READ_URL = (id) => `/api/v1/pleroma/chats/${id}/read`
|
||||||
const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) =>
|
const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) =>
|
||||||
`/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
|
`/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
|
||||||
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
|
const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups'
|
||||||
const PLEROMA_SCROBBLES_URL = (id) => `/api/v1/pleroma/accounts/${id}/scrobbles`
|
const PLEROMA_SCROBBLES_URL = (id, { maxId, sinceId, minId, limit, offset }) =>
|
||||||
|
`/api/v1/pleroma/accounts/${id}/scrobbles${paramsString({ maxId, sinceId, minId, limit, offset })}`
|
||||||
const PLEROMA_STATUS_QUOTES_URL = (id) =>
|
const PLEROMA_STATUS_QUOTES_URL = (id) =>
|
||||||
`/api/v1/pleroma/statuses/${id}/quotes`
|
`/api/v1/pleroma/statuses/${id}/quotes`
|
||||||
const PLEROMA_USER_FAVORITES_TIMELINE_URL = (id) =>
|
const PLEROMA_USER_FAVORITES_TIMELINE_URL = (id) =>
|
||||||
|
|
@ -128,20 +151,14 @@ const PLEROMA_BOOKMARK_FOLDER_URL = (id) =>
|
||||||
`/api/v1/pleroma/bookmark_folders/${id}`
|
`/api/v1/pleroma/bookmark_folders/${id}`
|
||||||
|
|
||||||
const EMOJI_PACKS_URL = (page, pageSize) =>
|
const EMOJI_PACKS_URL = (page, pageSize) =>
|
||||||
`/api/v1/pleroma/emoji/packs?page=${page}&page_size=${pageSize}`
|
`/api/v1/pleroma/emoji/packs${paramsString({ page, pageSize })}`
|
||||||
|
|
||||||
export const updateNotificationSettings = ({ credentials, settings }) => {
|
export const updateNotificationSettings = ({ credentials, settings }) => {
|
||||||
const form = new FormData()
|
|
||||||
|
|
||||||
each(settings, (value, key) => {
|
|
||||||
form.append(key, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: `${NOTIFICATION_SETTINGS_URL}?${new URLSearchParams(settings)}`,
|
url: NOTIFICATION_SETTINGS_URL,
|
||||||
credentials,
|
credentials,
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
formData: form,
|
payload: settings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -245,19 +262,19 @@ export const getCaptcha = () =>
|
||||||
})
|
})
|
||||||
|
|
||||||
export const followUser = ({ id, credentials, ...options }) => {
|
export const followUser = ({ id, credentials, ...options }) => {
|
||||||
const form = {}
|
const payload = {}
|
||||||
|
|
||||||
if (options.reblogs !== undefined) {
|
if (options.reblogs !== undefined) {
|
||||||
form.reblogs = options.reblogs
|
payload.reblogs = options.reblogs
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.notify !== undefined) {
|
if (options.notify !== undefined) {
|
||||||
form.notify = options.notify
|
payload.notify = options.notify
|
||||||
}
|
}
|
||||||
|
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: MASTODON_FOLLOW_URL(id),
|
url: MASTODON_FOLLOW_URL(id),
|
||||||
formData: form,
|
payload,
|
||||||
credentials,
|
credentials,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
})
|
})
|
||||||
|
|
@ -380,35 +397,17 @@ export const fetchUserByName = ({ name, credentials }) =>
|
||||||
})
|
})
|
||||||
.then((id) => fetchUser({ id, credentials }))
|
.then((id) => fetchUser({ id, credentials }))
|
||||||
|
|
||||||
export const fetchUserRelationship = ({ id, credentials }) =>
|
export const fetchUserRelationship = ({ id, withSuspended, credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
url: `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}`,
|
url: MASTODON_USER_RELATIONSHIPS_URL({ id, withSuspended }),
|
||||||
credentials,
|
credentials,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchFriends = ({
|
export const fetchFriends = ({ id, maxId, sinceId, limit = 20, credentials }) =>
|
||||||
id,
|
promisedRequest({
|
||||||
maxId,
|
url: MASTODON_FOLLOWING_URL(id, { maxId, sinceId, limit }),
|
||||||
sinceId,
|
|
||||||
limit = 20,
|
|
||||||
credentials,
|
|
||||||
}) => {
|
|
||||||
let url = MASTODON_FOLLOWING_URL(id)
|
|
||||||
const args = [
|
|
||||||
maxId && `max_id=${maxId}`,
|
|
||||||
sinceId && `since_id=${sinceId}`,
|
|
||||||
limit && `limit=${limit}`,
|
|
||||||
'with_relationships=true',
|
|
||||||
]
|
|
||||||
.filter((_) => _)
|
|
||||||
.join('&')
|
|
||||||
|
|
||||||
url = url + (args ? '?' + args : '')
|
|
||||||
return promisedRequest({
|
|
||||||
url,
|
|
||||||
credentials,
|
credentials,
|
||||||
}).then((data) => data.map(parseUser))
|
}).then((data) => data.map(parseUser))
|
||||||
}
|
|
||||||
|
|
||||||
export const exportFriends = ({ id, credentials }) => {
|
export const exportFriends = ({ id, credentials }) => {
|
||||||
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO refactor this
|
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO refactor this
|
||||||
|
|
@ -418,7 +417,12 @@ export const exportFriends = ({ id, credentials }) => {
|
||||||
let more = true
|
let more = true
|
||||||
while (more) {
|
while (more) {
|
||||||
const maxId = friends.length > 0 ? last(friends).id : undefined
|
const maxId = friends.length > 0 ? last(friends).id : undefined
|
||||||
const users = await fetchFriends({ id, maxId, credentials })
|
const users = await fetchFriends({
|
||||||
|
id,
|
||||||
|
maxId,
|
||||||
|
credentials,
|
||||||
|
withRelationships: true,
|
||||||
|
})
|
||||||
friends = concat(friends, users)
|
friends = concat(friends, users)
|
||||||
if (users.length === 0) {
|
if (users.length === 0) {
|
||||||
more = false
|
more = false
|
||||||
|
|
@ -437,23 +441,16 @@ export const fetchFollowers = ({
|
||||||
sinceId,
|
sinceId,
|
||||||
limit = 20,
|
limit = 20,
|
||||||
credentials,
|
credentials,
|
||||||
}) => {
|
}) =>
|
||||||
let url = MASTODON_FOLLOWERS_URL(id)
|
promisedRequest({
|
||||||
const args = [
|
url: MASTODON_FOLLOWERS_URL(id, {
|
||||||
maxId && `max_id=${maxId}`,
|
maxId,
|
||||||
sinceId && `since_id=${sinceId}`,
|
sinceId,
|
||||||
limit && `limit=${limit}`,
|
limit,
|
||||||
'with_relationships=true',
|
withRelationships: true,
|
||||||
]
|
}),
|
||||||
.filter((_) => _)
|
|
||||||
.join('&')
|
|
||||||
|
|
||||||
url += args ? '?' + args : ''
|
|
||||||
return promisedRequest({
|
|
||||||
url,
|
|
||||||
credentials,
|
credentials,
|
||||||
}).then((data) => data.map(parseUser))
|
}).then((data) => data.map(parseUser))
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchFollowRequests = ({ credentials }) =>
|
export const fetchFollowRequests = ({ credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
|
|
@ -567,17 +564,17 @@ export const fetchStatusHistory = ({ status, credentials }) =>
|
||||||
export const fetchTimeline = ({
|
export const fetchTimeline = ({
|
||||||
timeline,
|
timeline,
|
||||||
credentials,
|
credentials,
|
||||||
since = false,
|
sinceId,
|
||||||
minId = false,
|
minId,
|
||||||
until = false,
|
maxId,
|
||||||
userId = false,
|
userId,
|
||||||
listId = false,
|
listId,
|
||||||
statusId = false,
|
statusId,
|
||||||
tag = false,
|
tag,
|
||||||
withMuted = false,
|
withMuted,
|
||||||
replyVisibility = 'all',
|
replyVisibility = 'all',
|
||||||
includeTypes = [],
|
includeTypes = [],
|
||||||
bookmarkFolderId = false,
|
bookmarkFolderId,
|
||||||
}) => {
|
}) => {
|
||||||
const timelineUrls = {
|
const timelineUrls = {
|
||||||
public: MASTODON_PUBLIC_TIMELINE,
|
public: MASTODON_PUBLIC_TIMELINE,
|
||||||
|
|
@ -595,8 +592,14 @@ export const fetchTimeline = ({
|
||||||
quotes: PLEROMA_STATUS_QUOTES_URL,
|
quotes: PLEROMA_STATUS_QUOTES_URL,
|
||||||
bubble: AKKOMA_BUBBLE_TIMELINE_URL,
|
bubble: AKKOMA_BUBBLE_TIMELINE_URL,
|
||||||
}
|
}
|
||||||
|
|
||||||
const isNotifications = timeline === 'notifications'
|
const isNotifications = timeline === 'notifications'
|
||||||
const params = []
|
const params = {
|
||||||
|
minId,
|
||||||
|
sinceId,
|
||||||
|
maxId,
|
||||||
|
limit: 20,
|
||||||
|
}
|
||||||
|
|
||||||
let url = timelineUrls[timeline]
|
let url = timelineUrls[timeline]
|
||||||
|
|
||||||
|
|
@ -616,51 +619,34 @@ export const fetchTimeline = ({
|
||||||
url = url(statusId)
|
url = url(statusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minId) {
|
|
||||||
params.push(['min_id', minId])
|
|
||||||
}
|
|
||||||
if (since) {
|
|
||||||
params.push(['since_id', since])
|
|
||||||
}
|
|
||||||
if (until) {
|
|
||||||
params.push(['max_id', until])
|
|
||||||
}
|
|
||||||
if (tag) {
|
if (tag) {
|
||||||
url = url(tag)
|
url = url(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeline === 'media') {
|
if (timeline === 'media') {
|
||||||
params.push(['only_media', 1])
|
params.onlyMedia = 1
|
||||||
}
|
}
|
||||||
if (timeline === 'public') {
|
if (timeline === 'public') {
|
||||||
params.push(['local', true])
|
params.local = true
|
||||||
}
|
}
|
||||||
if (timeline === 'public' || timeline === 'publicAndExternal') {
|
if (timeline === 'public' || timeline === 'publicAndExternal') {
|
||||||
params.push(['only_media', false])
|
params.onlyMedia = false
|
||||||
}
|
}
|
||||||
if (timeline !== 'favorites' && timeline !== 'bookmarks') {
|
if (timeline !== 'favorites' && timeline !== 'bookmarks') {
|
||||||
params.push(['with_muted', withMuted])
|
params.withMuted = withMuted
|
||||||
}
|
}
|
||||||
if (replyVisibility !== 'all') {
|
if (replyVisibility !== 'all') {
|
||||||
params.push(['reply_visibility', replyVisibility])
|
params.replyVisibility = replyVisibility
|
||||||
}
|
}
|
||||||
if (includeTypes.size > 0) {
|
if (includeTypes.size > 0) {
|
||||||
includeTypes.forEach((type) => {
|
params.includeTypes = includeTypes
|
||||||
params.push(['include_types[]', type])
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (timeline === 'bookmarks' && bookmarkFolderId) {
|
if (timeline === 'bookmarks' && bookmarkFolderId) {
|
||||||
params.push(['folder_id', bookmarkFolderId])
|
params.folderId = bookmarkFolderId
|
||||||
}
|
}
|
||||||
|
|
||||||
params.push(['limit', 20])
|
|
||||||
|
|
||||||
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join(
|
|
||||||
'&',
|
|
||||||
)
|
|
||||||
url += `?${queryString}`
|
|
||||||
|
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url,
|
url: url + paramsString(params),
|
||||||
credentials,
|
credentials,
|
||||||
}).then(async (data) => {
|
}).then(async (data) => {
|
||||||
const pagination = parseLinkHeaderPagination(
|
const pagination = parseLinkHeaderPagination(
|
||||||
|
|
@ -1036,16 +1022,11 @@ export const generateMfaBackupCodes = ({ credentials }) =>
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchMutes = ({ maxId, credentials }) => {
|
export const fetchMutes = ({ maxId, credentials }) =>
|
||||||
const query = new URLSearchParams({ with_relationships: true })
|
promisedRequest({
|
||||||
if (maxId) {
|
url: MASTODON_USER_MUTES_URL({ maxId, withRelationships: true }),
|
||||||
query.append('max_id', maxId)
|
|
||||||
}
|
|
||||||
return promisedRequest({
|
|
||||||
url: `${MASTODON_USER_MUTES_URL}?${query.toString()}`,
|
|
||||||
credentials,
|
credentials,
|
||||||
}).then((users) => users.map(parseUser))
|
}).then((users) => users.map(parseUser))
|
||||||
}
|
|
||||||
|
|
||||||
export const muteUser = ({ id, expiresIn, credentials }) => {
|
export const muteUser = ({ id, expiresIn, credentials }) => {
|
||||||
const payload = {}
|
const payload = {}
|
||||||
|
|
@ -1068,16 +1049,11 @@ export const unmuteUser = ({ id, credentials }) =>
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchBlocks = ({ maxId, credentials }) => {
|
export const fetchBlocks = ({ maxId, credentials }) =>
|
||||||
const query = new URLSearchParams({ with_relationships: true })
|
promisedRequest({
|
||||||
if (maxId) {
|
url: MASTODON_USER_BLOCKS_URL({ maxId, withRelationships: true }),
|
||||||
query.append('max_id', maxId)
|
|
||||||
}
|
|
||||||
return promisedRequest({
|
|
||||||
url: `${MASTODON_USER_BLOCKS_URL}?${query.toString()}`,
|
|
||||||
credentials,
|
credentials,
|
||||||
}).then((users) => users.map(parseUser))
|
}).then((users) => users.map(parseUser))
|
||||||
}
|
|
||||||
|
|
||||||
export const addBackup = ({ credentials }) =>
|
export const addBackup = ({ credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
|
|
@ -1519,19 +1495,8 @@ export const chatMessages = ({
|
||||||
sinceId,
|
sinceId,
|
||||||
limit = 20,
|
limit = 20,
|
||||||
}) => {
|
}) => {
|
||||||
let url = PLEROMA_CHAT_MESSAGES_URL(id)
|
|
||||||
const args = [
|
|
||||||
maxId && `max_id=${maxId}`,
|
|
||||||
sinceId && `since_id=${sinceId}`,
|
|
||||||
limit && `limit=${limit}`,
|
|
||||||
]
|
|
||||||
.filter((_) => _)
|
|
||||||
.join('&')
|
|
||||||
|
|
||||||
url = url + (args ? '?' + args : '')
|
|
||||||
|
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url,
|
url: PLEROMA_CHAT_MESSAGES_URL(id, { maxId, sinceId, limit }),
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
credentials,
|
credentials,
|
||||||
})
|
})
|
||||||
|
|
@ -1584,15 +1549,10 @@ export const deleteChatMessage = ({ chatId, messageId, credentials }) =>
|
||||||
credentials,
|
credentials,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const fetchScrobbles = ({ accountId, limit = 1 }) => {
|
export const fetchScrobbles = ({ accountId, limit = 1 }) =>
|
||||||
let url = PLEROMA_SCROBBLES_URL(accountId)
|
promisedRequest({
|
||||||
const params = [['limit', limit]]
|
url: PLEROMA_SCROBBLES_URL(accountId, { limit }),
|
||||||
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join(
|
})
|
||||||
'&',
|
|
||||||
)
|
|
||||||
url += `?${queryString}`
|
|
||||||
return promisedRequest({ url })
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchBookmarkFolders = ({ credentials }) =>
|
export const fetchBookmarkFolders = ({ credentials }) =>
|
||||||
promisedRequest({
|
promisedRequest({
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,71 @@
|
||||||
|
import { snakeCase } from 'lodash'
|
||||||
|
|
||||||
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
|
import { RegistrationError, StatusCodeError } from 'src/services/errors/errors'
|
||||||
|
|
||||||
|
export const paramsString = (params = {}) => {
|
||||||
|
if (params == null || params === undefined) return ''
|
||||||
|
|
||||||
|
if (typeof params !== 'object' || Array.isArray(params)) {
|
||||||
|
throw new Error('Params are not an object!')
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries = (() => {
|
||||||
|
if (params instanceof Map) {
|
||||||
|
return params.entries()
|
||||||
|
} else {
|
||||||
|
return Object.entries(params)
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
if (entries.length === 0) return ''
|
||||||
|
|
||||||
|
const arrays = []
|
||||||
|
const nonArrays = []
|
||||||
|
|
||||||
|
entries.forEach(([k, v]) => {
|
||||||
|
if (v == null) return // Drop nulls
|
||||||
|
if (
|
||||||
|
(typeof v === 'object' && !Array.isArray(v)) ||
|
||||||
|
typeof v === 'function'
|
||||||
|
) {
|
||||||
|
throw new Error('Param cannot be non-primitive!')
|
||||||
|
}
|
||||||
|
if (Array.isArray(v)) {
|
||||||
|
arrays.push([k, v])
|
||||||
|
} else {
|
||||||
|
nonArrays.push([k, v])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
arrays.forEach(([k, array]) => {
|
||||||
|
array.forEach((v) => {
|
||||||
|
if (
|
||||||
|
typeof v === 'object' ||
|
||||||
|
typeof v === 'function' ||
|
||||||
|
typeof v === 'undefined'
|
||||||
|
)
|
||||||
|
throw new Error('Array param cannot contain non-primitives!')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
'?' +
|
||||||
|
[
|
||||||
|
...nonArrays.map(([k, v]) => [snakeCase(k), v]),
|
||||||
|
// turning [a,[1,2,3]] into [[a[],1],[a[],2],[a[],3]]
|
||||||
|
...arrays.reduce(
|
||||||
|
(acc, [k, arrayValue]) => [
|
||||||
|
...acc,
|
||||||
|
...arrayValue.map((v) => [snakeCase(k) + '[]', v]),
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.map(([k, v]) => `${k}=${window.encodeURIComponent(v)}`)
|
||||||
|
.join('&')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const promisedRequest = ({
|
export const promisedRequest = ({
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
|
|
@ -60,6 +126,12 @@ export const promisedRequest = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof json !== 'object') {
|
||||||
|
return resolve({
|
||||||
|
_response: response,
|
||||||
|
_value: json,
|
||||||
|
})
|
||||||
|
}
|
||||||
json._response = response
|
json._response = response
|
||||||
|
|
||||||
return resolve(json)
|
return resolve(json)
|
||||||
|
|
|
||||||
|
|
@ -35,42 +35,33 @@ const fetchRelationship = (attempt, userId, store) =>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const requestFollow = (userId, store) =>
|
export const requestFollow = async (userId, store) => {
|
||||||
new Promise((resolve) => {
|
const updated = await followUser({
|
||||||
followUser({
|
id: userId,
|
||||||
id: userId,
|
credentials: useOAuthStore().token,
|
||||||
credentials: useOAuthStore().token,
|
|
||||||
}).then((updated) => {
|
|
||||||
store.commit('updateUserRelationship', [updated])
|
|
||||||
|
|
||||||
if (updated.following || (updated.locked && updated.requested)) {
|
|
||||||
// If we get result immediately or the account is locked, just stop.
|
|
||||||
resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// But usually we don't get result immediately, so we ask server
|
|
||||||
// for updated user profile to confirm if we are following them
|
|
||||||
// Sometimes it takes several tries. Sometimes we end up not following
|
|
||||||
// user anyway, probably because they locked themselves and we
|
|
||||||
// don't know that yet.
|
|
||||||
// Recursive Promise, it will call itself up to 3 times.
|
|
||||||
|
|
||||||
return fetchRelationship(1, updated, store).then(() => {
|
|
||||||
resolve()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const requestUnfollow = (userId, store) =>
|
store.commit('updateUserRelationship', [updated])
|
||||||
new Promise((resolve) => {
|
|
||||||
unfollowUser({
|
if (updated.following || (updated.locked && updated.requested)) {
|
||||||
id: userId,
|
// If we get result immediately or the account is locked, just stop.
|
||||||
credentials: useOAuthStore().token,
|
return
|
||||||
}).then((updated) => {
|
}
|
||||||
store.commit('updateUserRelationship', [updated])
|
|
||||||
resolve({
|
// But usually we don't get result immediately, so we ask server
|
||||||
updated,
|
// for updated user profile to confirm if we are following them
|
||||||
})
|
// Sometimes it takes several tries. Sometimes we end up not following
|
||||||
})
|
// user anyway, probably because they locked themselves and we
|
||||||
|
// don't know that yet.
|
||||||
|
// Recursive Promise, it will call itself up to 3 times.
|
||||||
|
return await fetchRelationship(1, updated, store)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const requestUnfollow = async (userId, store) => {
|
||||||
|
const updated = await unfollowUser({
|
||||||
|
id: userId,
|
||||||
|
credentials: useOAuthStore().token,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return await store.commit('updateUserRelationship', [updated])
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ const mastoApiNotificationTypes = new Set([
|
||||||
'pleroma:report',
|
'pleroma:report',
|
||||||
])
|
])
|
||||||
|
|
||||||
const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
const fetchAndUpdate = ({ store, credentials, older = false, sinceId }) => {
|
||||||
const args = { credentials }
|
const args = { credentials }
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
const timelineData = rootState.notifications
|
const timelineData = rootState.notifications
|
||||||
|
|
@ -35,24 +35,24 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
||||||
mastoApiNotificationTypes.add('pleroma:chat_mention')
|
mastoApiNotificationTypes.add('pleroma:chat_mention')
|
||||||
}
|
}
|
||||||
|
|
||||||
args.includeTypes = mastoApiNotificationTypes
|
args.includeTypes = [...mastoApiNotificationTypes]
|
||||||
args.withMuted = !hideMutedPosts
|
args.withMuted = !hideMutedPosts
|
||||||
|
|
||||||
args.timeline = 'notifications'
|
args.timeline = 'notifications'
|
||||||
if (older) {
|
if (older) {
|
||||||
if (timelineData.minId !== Number.POSITIVE_INFINITY) {
|
if (timelineData.minId !== Number.POSITIVE_INFINITY) {
|
||||||
args.until = timelineData.minId
|
args.maxId = timelineData.minId
|
||||||
}
|
}
|
||||||
return fetchNotifications({ store, args, older })
|
return fetchNotifications({ store, args, older })
|
||||||
} else {
|
} else {
|
||||||
// fetch new notifications
|
// fetch new notifications
|
||||||
if (
|
if (
|
||||||
since === undefined &&
|
sinceId === undefined &&
|
||||||
timelineData.maxId !== Number.POSITIVE_INFINITY
|
timelineData.maxId !== Number.POSITIVE_INFINITY
|
||||||
) {
|
) {
|
||||||
args.since = timelineData.maxId
|
args.sinceId = timelineData.maxId
|
||||||
} else if (since !== null) {
|
} else if (sinceId !== null) {
|
||||||
args.since = since
|
args.sinceId = sinceId
|
||||||
}
|
}
|
||||||
const result = fetchNotifications({ store, args, older })
|
const result = fetchNotifications({ store, args, older })
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => {
|
||||||
if (readNotifsIds.length > 0 && readNotifsIds.length > 0) {
|
if (readNotifsIds.length > 0 && readNotifsIds.length > 0) {
|
||||||
const minId = Math.min(...unreadNotifsIds) // Oldest known unread notification
|
const minId = Math.min(...unreadNotifsIds) // Oldest known unread notification
|
||||||
if (minId !== Infinity) {
|
if (minId !== Infinity) {
|
||||||
args.since = false // Don't use since_id since it sorta conflicts with min_id
|
args.sinceId = null // Don't use since_id since it sorta conflicts with min_id
|
||||||
args.minId = minId - 1 // go beyond
|
args.minId = minId - 1 // go beyond
|
||||||
fetchNotifications({ store, args, older })
|
fetchNotifications({ store, args, older })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ const fetchAndUpdate = ({
|
||||||
bookmarkFolderId = false,
|
bookmarkFolderId = false,
|
||||||
tag = false,
|
tag = false,
|
||||||
until,
|
until,
|
||||||
since,
|
sinceId,
|
||||||
}) => {
|
}) => {
|
||||||
const args = { timeline, credentials }
|
const args = { timeline, credentials }
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
|
|
@ -53,10 +53,10 @@ const fetchAndUpdate = ({
|
||||||
if (older) {
|
if (older) {
|
||||||
args.until = until || timelineData.minId
|
args.until = until || timelineData.minId
|
||||||
} else {
|
} else {
|
||||||
if (since === undefined) {
|
if (sinceId === undefined) {
|
||||||
args.since = timelineData.maxId
|
args.sinceId = timelineData.maxId
|
||||||
} else if (since !== null) {
|
} else if (sinceId !== null) {
|
||||||
args.since = since
|
args.sinceId = sinceId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
90
test/unit/specs/services/api/helpers.spec.js
Normal file
90
test/unit/specs/services/api/helpers.spec.js
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { paramsString } from 'src/services/api/helpers.js'
|
||||||
|
|
||||||
|
describe('API Helpers', () => {
|
||||||
|
describe.only('paramsString', () => {
|
||||||
|
it('should return empty string when given empty object', () => {
|
||||||
|
const string = paramsString({})
|
||||||
|
|
||||||
|
expect(string).to.eq('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return empty string when given null', () => {
|
||||||
|
const string = paramsString(null)
|
||||||
|
|
||||||
|
expect(string).to.eq('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return empty string when given undefined', () => {
|
||||||
|
const string = paramsString(undefined)
|
||||||
|
|
||||||
|
expect(string).to.eq('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return URI param string for normal object', () => {
|
||||||
|
const string = paramsString({ a: 1, b: '3' })
|
||||||
|
|
||||||
|
expect(string).to.eq('?a=1&b=3')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should encode objects correctly', () => {
|
||||||
|
const string = paramsString({ foo: true, bar: [1, 2, 3] })
|
||||||
|
|
||||||
|
expect(string).to.eq('?foo=true&bar[]=1&bar[]=2&bar[]=3')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should drop nullish params', () => {
|
||||||
|
const string = paramsString({ present: 'yes', missing: null })
|
||||||
|
|
||||||
|
expect(string).to.eq('?present=yes')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should convert camelCase keys to snake_keys objects correctly', () => {
|
||||||
|
const string = paramsString({ isActive: true, MaybeNot: false })
|
||||||
|
|
||||||
|
expect(string).to.eq('?is_active=true&maybe_not=false')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should work with maps', () => {
|
||||||
|
const string = paramsString(
|
||||||
|
new Map([
|
||||||
|
['key', 'yes'],
|
||||||
|
['key2', 'also yes'],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(string).to.eq('?key=yes&key_2=also%20yes')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should escape components correctly', () => {
|
||||||
|
const string = paramsString({ gachi: '♂', muchi: 'Билли Геррингтон' })
|
||||||
|
|
||||||
|
expect(string).to.eq(
|
||||||
|
'?gachi=%E2%99%82&muchi=%D0%91%D0%B8%D0%BB%D0%BB%D0%B8%20%D0%93%D0%B5%D1%80%D1%80%D0%B8%D0%BD%D0%B3%D1%82%D0%BE%D0%BD',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw when passed a non-object', () => {
|
||||||
|
expect(() => {
|
||||||
|
paramsString('Totally an object')
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw when passed an array', () => {
|
||||||
|
expect(() => {
|
||||||
|
paramsString(['Totally an object'])
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw when array param is non-primitive', () => {
|
||||||
|
expect(() => {
|
||||||
|
paramsString({ a: [() => ''] })
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw when array param is nullish', () => {
|
||||||
|
expect(() => {
|
||||||
|
paramsString({ a: [1, null, 3] })
|
||||||
|
}).to.throw()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
import mastoapidata from '../../../../fixtures/mastoapi.json'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
parseLinkHeaderPagination,
|
parseLinkHeaderPagination,
|
||||||
parseNotification,
|
parseNotification,
|
||||||
parseStatus,
|
parseStatus,
|
||||||
parseUser,
|
parseUser,
|
||||||
} from '../../../../../src/services/entity_normalizer/entity_normalizer.service.js'
|
} from 'src/services/entity_normalizer/entity_normalizer.service.js'
|
||||||
import mastoapidata from '../../../../fixtures/mastoapi.json'
|
|
||||||
|
|
||||||
const makeMockUserMasto = (overrides = {}) => {
|
const makeMockUserMasto = (overrides = {}) => {
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue