From ebf70406625a2e5988d383eb21407acb6675d263 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 17 Jun 2026 14:26:41 +0300 Subject: [PATCH] separate authenticated endpoints to user.js --- .../bookmark_folder_edit.js | 2 +- src/components/chat/chat.js | 2 +- src/components/chat_new/chat_new.js | 2 +- .../follow_request_card.js | 2 +- src/components/notification/notification.js | 2 +- .../settings_modal/tabs/appearance_tab.js | 2 +- .../settings_modal/tabs/composing_tab.js | 2 +- .../tabs/data_import_export_tab.js | 2 +- .../settings_modal/tabs/general_tab.js | 2 +- .../tabs/mutes_and_blocks_tab.js | 2 +- .../settings_modal/tabs/notifications_tab.js | 2 +- .../settings_modal/tabs/profile_tab.js | 2 +- .../settings_modal/tabs/security_tab/mfa.js | 2 +- .../tabs/security_tab/mfa_totp.js | 2 +- .../tabs/security_tab/security_tab.js | 2 +- src/components/user_card/user_card.js | 2 +- .../user_reporting_modal.js | 2 +- src/modules/chats.js | 6 +- src/modules/notifications.js | 4 +- src/modules/profileConfig.js | 2 +- src/modules/statuses.js | 20 +- src/modules/users.js | 16 +- src/services/api/api.service.js | 993 +----------------- src/services/api/chats.js | 86 ++ src/services/api/helpers.js | 20 +- src/services/api/user.js | 926 ++++++++++++++++ .../follow_manipulate/follow_manipulate.js | 2 +- .../follow_request_fetcher.service.js | 4 +- .../status_poster/status_poster.service.js | 2 +- src/stores/announcements.js | 6 +- src/stores/bookmark_folders.js | 2 +- src/stores/lists.js | 2 +- src/stores/oauth_tokens.js | 5 +- src/stores/polls.js | 3 +- src/stores/sync_config.js | 2 +- src/stores/user_highlight.js | 2 +- 36 files changed, 1082 insertions(+), 1055 deletions(-) create mode 100644 src/services/api/chats.js create mode 100644 src/services/api/user.js diff --git a/src/components/bookmark_folder_edit/bookmark_folder_edit.js b/src/components/bookmark_folder_edit/bookmark_folder_edit.js index bc30790f6..74bcf3109 100644 --- a/src/components/bookmark_folder_edit/bookmark_folder_edit.js +++ b/src/components/bookmark_folder_edit/bookmark_folder_edit.js @@ -4,7 +4,7 @@ import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js' import { useInterfaceStore } from 'src/stores/interface.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { fetchBookmarkFolders } from 'src/services/api/api.service.js' +import { fetchBookmarkFolders } from 'src/services/api/user.js' const BookmarkFolderEdit = { data() { diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index bd71c2b5d..3ea9e3fd6 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -23,7 +23,7 @@ import { chatMessages, getOrCreateChat, sendChatMessage, -} from 'src/services/api/api.service.js' +} from 'src/services/api/chats.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronDown, faChevronLeft } from '@fortawesome/free-solid-svg-icons' diff --git a/src/components/chat_new/chat_new.js b/src/components/chat_new/chat_new.js index 7b08d3163..3e0cc8db3 100644 --- a/src/components/chat_new/chat_new.js +++ b/src/components/chat_new/chat_new.js @@ -5,7 +5,7 @@ import UserAvatar from 'src/components/user_avatar/user_avatar.vue' import { useOAuthStore } from 'src/stores/oauth.js' -import { chats } from 'src/services/api/api.service.js' +import { chats } from 'src/services/api/chats.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronLeft, faSearch } from '@fortawesome/free-solid-svg-icons' diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js index 178f36894..1ee9b5c3b 100644 --- a/src/components/follow_request_card/follow_request_card.js +++ b/src/components/follow_request_card/follow_request_card.js @@ -6,7 +6,7 @@ import BasicUserCard from '../basic_user_card/basic_user_card.vue' import { useMergedConfigStore } from 'src/stores/merged_config.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { approveUser, denyUser } from 'src/services/api/api.service.js' +import { approveUser, denyUser } from 'src/services/api/user.js' const FollowRequestCard = { props: ['user'], diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 8fc77d91d..55311255e 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -18,7 +18,7 @@ import { useMergedConfigStore } from 'src/stores/merged_config.js' import { useOAuthStore } from 'src/stores/oauth.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js' -import { approveUser, denyUser } from 'src/services/api/api.service.js' +import { approveUser, denyUser } from 'src/services/api/user.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import { library } from '@fortawesome/fontawesome-svg-core' diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index 77686b736..75f0d74aa 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -14,7 +14,7 @@ import { useInstanceStore } from 'src/stores/instance.js' import { normalizeThemeData, useInterfaceStore } from 'src/stores/interface.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { updateProfileImages } from 'src/services/api/api.service.js' +import { updateProfileImages } from 'src/services/api/user.js' import { newImporter } from 'src/services/export_import/export_import.js' import { adoptStyleSheets, diff --git a/src/components/settings_modal/tabs/composing_tab.js b/src/components/settings_modal/tabs/composing_tab.js index 90d80cbf6..31d0a5706 100644 --- a/src/components/settings_modal/tabs/composing_tab.js +++ b/src/components/settings_modal/tabs/composing_tab.js @@ -17,7 +17,7 @@ import { useMergedConfigStore } from 'src/stores/merged_config.js' import { useOAuthStore } from 'src/stores/oauth.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' -import { updateProfile } from 'src/services/api/api.service.js' +import { updateProfile } from 'src/services/api/user.js' import localeService from 'src/services/locale/locale.service.js' import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js' diff --git a/src/components/settings_modal/tabs/data_import_export_tab.js b/src/components/settings_modal/tabs/data_import_export_tab.js index 05af7d27c..0329ff125 100644 --- a/src/components/settings_modal/tabs/data_import_export_tab.js +++ b/src/components/settings_modal/tabs/data_import_export_tab.js @@ -16,7 +16,7 @@ import { importFollows, importMutes, listBackups, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' const DataImportExportTab = { data() { diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 893833866..48bbd67c7 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -15,7 +15,7 @@ import { useMergedConfigStore } from 'src/stores/merged_config.js' import { useOAuthStore } from 'src/stores/oauth.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' -import { updateProfile } from 'src/services/api/api.service.js' +import { updateProfile } from 'src/services/api/user.js' import localeService from 'src/services/locale/locale.service.js' const GeneralTab = { diff --git a/src/components/settings_modal/tabs/mutes_and_blocks_tab.js b/src/components/settings_modal/tabs/mutes_and_blocks_tab.js index d1f5bff12..da9a8cbb7 100644 --- a/src/components/settings_modal/tabs/mutes_and_blocks_tab.js +++ b/src/components/settings_modal/tabs/mutes_and_blocks_tab.js @@ -13,7 +13,7 @@ import { useInstanceStore } from 'src/stores/instance.js' import { useOAuthStore } from 'src/stores/oauth.js' import { useOAuthTokensStore } from 'src/stores/oauth_tokens.js' -import { importBlocks, importFollows } from 'src/services/api/api.service.js' +import { importBlocks, importFollows } from 'src/services/api/user.js' const MutesAndBlocks = { data() { diff --git a/src/components/settings_modal/tabs/notifications_tab.js b/src/components/settings_modal/tabs/notifications_tab.js index 6ef8e0ab7..5fd1e8483 100644 --- a/src/components/settings_modal/tabs/notifications_tab.js +++ b/src/components/settings_modal/tabs/notifications_tab.js @@ -3,7 +3,7 @@ import SharedComputedObject from '../helpers/shared_computed_object.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { updateNotificationSettings } from 'src/services/api/api.service.js' +import { updateNotificationSettings } from 'src/services/api/user.js' const NotificationsTab = { data() { diff --git a/src/components/settings_modal/tabs/profile_tab.js b/src/components/settings_modal/tabs/profile_tab.js index 586ca30a8..b03c2012f 100644 --- a/src/components/settings_modal/tabs/profile_tab.js +++ b/src/components/settings_modal/tabs/profile_tab.js @@ -5,7 +5,7 @@ import SharedComputedObject from '../helpers/shared_computed_object.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { updateProfile } from 'src/services/api/api.service.js' +import { updateProfile } from 'src/services/api/user.js' import { library } from '@fortawesome/fontawesome-svg-core' import { diff --git a/src/components/settings_modal/tabs/security_tab/mfa.js b/src/components/settings_modal/tabs/security_tab/mfa.js index bba2a2ff9..32ce9ed21 100644 --- a/src/components/settings_modal/tabs/security_tab/mfa.js +++ b/src/components/settings_modal/tabs/security_tab/mfa.js @@ -12,7 +12,7 @@ import { mfaConfirmOTP, mfaSetupOTP, settingsMFA, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' const Mfa = { data: () => ({ diff --git a/src/components/settings_modal/tabs/security_tab/mfa_totp.js b/src/components/settings_modal/tabs/security_tab/mfa_totp.js index b7a1426ab..393a36249 100644 --- a/src/components/settings_modal/tabs/security_tab/mfa_totp.js +++ b/src/components/settings_modal/tabs/security_tab/mfa_totp.js @@ -4,7 +4,7 @@ import Confirm from './confirm.vue' import { useOAuthStore } from 'src/stores/oauth.js' -import { mfaDisableOTP } from 'src/services/api/api.service.js' +import { mfaDisableOTP } from 'src/services/api/user.js' export default { props: ['settings'], diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.js b/src/components/settings_modal/tabs/security_tab/security_tab.js index ca959ded5..35576e0d0 100644 --- a/src/components/settings_modal/tabs/security_tab/security_tab.js +++ b/src/components/settings_modal/tabs/security_tab/security_tab.js @@ -15,7 +15,7 @@ import { deleteAlias, listAliases, moveAccount, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' import localeService from 'src/services/locale/locale.service.js' const SecurityTab = { diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index 1a35c019b..0ae234afe 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -26,7 +26,7 @@ import { useOAuthStore } from 'src/stores/oauth.js' import { usePostStatusStore } from 'src/stores/post_status' import { useUserHighlightStore } from 'src/stores/user_highlight.js' -import { updateProfile } from 'src/services/api/api.service.js' +import { updateProfile } from 'src/services/api/user.js' import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js' import localeService from 'src/services/locale/locale.service.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' diff --git a/src/components/user_reporting_modal/user_reporting_modal.js b/src/components/user_reporting_modal/user_reporting_modal.js index 49e569f23..68e30903e 100644 --- a/src/components/user_reporting_modal/user_reporting_modal.js +++ b/src/components/user_reporting_modal/user_reporting_modal.js @@ -8,7 +8,7 @@ import UserLink from 'src/components/user_link/user_link.vue' import { useOAuthStore } from 'src/stores/oauth.js' import { useReportsStore } from 'src/stores/reports.js' -import { reportUser } from 'src/services/api/api.service.js' +import { reportUser } from 'src/services/api/user.js' const UserReportingModal = { components: { diff --git a/src/modules/chats.js b/src/modules/chats.js index 4ad82eccd..8bd353a70 100644 --- a/src/modules/chats.js +++ b/src/modules/chats.js @@ -11,11 +11,7 @@ import { promiseInterval } from '../services/promise_interval/promise_interval.j import { useOAuthStore } from 'src/stores/oauth.js' -import { - chats, - deleteChatMessage, - readChat, -} from 'src/services/api/api.service.js' +import { chats, deleteChatMessage, readChat } from 'src/services/api/chats.js' const emptyChatList = () => ({ data: [], diff --git a/src/modules/notifications.js b/src/modules/notifications.js index 3d5f787cf..d759be83b 100644 --- a/src/modules/notifications.js +++ b/src/modules/notifications.js @@ -1,4 +1,4 @@ -import { markNotificationsAsSeen } from '../services/api/api.service.js' +import { markNotificationsAsSeen } from '../services/api/user.js' import { closeAllDesktopNotifications, closeDesktopNotification, @@ -15,7 +15,7 @@ import { useOAuthStore } from 'src/stores/oauth.js' import { useReportsStore } from 'src/stores/reports.js' import { useSyncConfigStore } from 'src/stores/sync_config.js' -import { dismissNotification } from 'src/services/api/api.service.js' +import { dismissNotification } from 'src/services/api/user.js' const emptyNotifications = () => ({ desktopNotificationSilence: true, diff --git a/src/modules/profileConfig.js b/src/modules/profileConfig.js index 0f125e976..a7f3e73d8 100644 --- a/src/modules/profileConfig.js +++ b/src/modules/profileConfig.js @@ -5,7 +5,7 @@ import { useOAuthStore } from 'src/stores/oauth.js' import { updateNotificationSettings, updateProfile, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' const defaultApi = ({ rootState, commit }, { path, value }) => { const params = {} diff --git a/src/modules/statuses.js b/src/modules/statuses.js index ef6aedcbc..c0cffb7ed 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -13,10 +13,11 @@ import { slice, } from 'lodash' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' +import { useInterfaceStore } from 'src/stores/interface.js' +import { useOAuthStore } from 'src/stores/oauth.js' + import { - bookmarkStatus, - deleteStatus, - favorite, fetchEmojiReactions, fetchFavoritedByUsers, fetchPinnedStatuses, @@ -25,22 +26,23 @@ import { fetchStatus, fetchStatusHistory, fetchStatusSource, + search2, +} from 'src/services/api/api.service.js' +import { + bookmarkStatus, + deleteStatus, + favorite, muteConversation, pinOwnStatus, reactWithEmoji, retweet, - search2, unbookmarkStatus, unfavorite, unmuteConversation, unpinOwnStatus, unreactWithEmoji, unretweet, -} from '../services/api/api.service.js' - -import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' -import { useInterfaceStore } from 'src/stores/interface.js' -import { useOAuthStore } from 'src/stores/oauth.js' +} from 'src/services/api/user.js' const emptyTl = (userId = 0) => ({ statuses: [], diff --git a/src/modules/users.js b/src/modules/users.js index 471c19289..c4aa9a1c5 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -32,21 +32,23 @@ import { useSyncConfigStore } from 'src/stores/sync_config.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { - fetchBlocks, - fetchDomainMutes, fetchFollowers, fetchFriends, - fetchMutes, fetchUser, fetchUserByName, - fetchUserInLists, - fetchUserRelationship, - followUser, getCaptcha, - muteUser, searchUsers, verifyCredentials, } from 'src/services/api/api.service.js' +import { + fetchBlocks, + fetchDomainMutes, + fetchMutes, + fetchUserInLists, + fetchUserRelationship, + followUser, + muteUser, +} from 'src/services/api/user.js' // TODO: Unify with mergeOrAdd in statuses.js export const mergeOrAdd = (arr, obj, item) => { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 864123f5f..66847a32b 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -13,39 +13,12 @@ import { paramsString, promisedRequest } from './helpers.js' import { RegistrationError, StatusCodeError } from 'src/services/errors/errors' -/* eslint-env browser */ -const MUTES_IMPORT_URL = '/api/pleroma/mutes_import' -const BLOCKS_IMPORT_URL = '/api/pleroma/blocks_import' -const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import' -const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account' -const CHANGE_EMAIL_URL = '/api/pleroma/change_email' -const CHANGE_PASSWORD_URL = '/api/pleroma/change_password' -const MOVE_ACCOUNT_URL = '/api/pleroma/move_account' -const ALIASES_URL = '/api/pleroma/aliases' const SUGGESTIONS_URL = '/api/v1/suggestions' -const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings' -const NOTIFICATION_READ_URL = '/api/v1/pleroma/notifications/read' - -const MFA_SETTINGS_URL = '/api/pleroma/accounts/mfa' -const MFA_BACKUP_CODES_URL = '/api/pleroma/accounts/mfa/backup_codes' - -const MFA_SETUP_OTP_URL = '/api/pleroma/accounts/mfa/setup/totp' -const MFA_CONFIRM_OTP_URL = '/api/pleroma/accounts/mfa/confirm/totp' -const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp' - +/* eslint-env browser */ const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials' const MASTODON_REGISTRATION_URL = '/api/v1/accounts' const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications' -const MASTODON_DISMISS_NOTIFICATION_URL = (id) => - `/api/v1/notifications/${id}/dismiss` -const MASTODON_FAVORITE_URL = (id) => `/api/v1/statuses/${id}/favourite` -const MASTODON_UNFAVORITE_URL = (id) => `/api/v1/statuses/${id}/unfavourite` -const MASTODON_RETWEET_URL = (id) => `/api/v1/statuses/${id}/reblog` -const MASTODON_UNRETWEET_URL = (id) => `/api/v1/statuses/${id}/unreblog` -const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}` -const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow` -const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow` const MASTODON_FOLLOWING_URL = ( id, { minId, maxId, sinceId, limit, withRelationships }, @@ -56,178 +29,42 @@ const MASTODON_FOLLOWERS_URL = ( { 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_APPROVE_USER_URL = (id) => - `/api/v1/follow_requests/${id}/authorize` -const MASTODON_DENY_USER_URL = (id) => `/api/v1/follow_requests/${id}/reject` +const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home' +const MASTODON_LIST_TIMELINE_URL = (id) => `/api/v1/timelines/list/${id}` +const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks' const MASTODON_DIRECT_MESSAGES_TIMELINE_URL = '/api/v1/timelines/direct' const MASTODON_PUBLIC_TIMELINE = '/api/v1/timelines/public' -const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home' -const MASTODON_STATUS_URL = (id) => `/api/v1/statuses/${id}` +export const MASTODON_STATUS_URL = (id) => `/api/v1/statuses/${id}` const MASTODON_STATUS_CONTEXT_URL = (id) => `/api/v1/statuses/${id}/context` const MASTODON_STATUS_SOURCE_URL = (id) => `/api/v1/statuses/${id}/source` const MASTODON_STATUS_HISTORY_URL = (id) => `/api/v1/statuses/${id}/history` const MASTODON_USER_URL = '/api/v1/accounts' const MASTODON_USER_LOOKUP_URL = '/api/v1/accounts/lookup' -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_IN_LISTS = (id) => `/api/v1/accounts/${id}/lists` -const MASTODON_LIST_URL = (id) => `/api/v1/lists/${id}` -const MASTODON_LIST_TIMELINE_URL = (id) => `/api/v1/timelines/list/${id}` -const MASTODON_LIST_ACCOUNTS_URL = (id) => `/api/v1/lists/${id}/accounts` const MASTODON_TAG_TIMELINE_URL = (tag) => `/api/v1/timelines/tag/${tag}` -const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks' const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble' -const MASTODON_USER_BLOCKS_URL = ({ - 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_UNBLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/unblock` -const MASTODON_MUTE_USER_URL = (id) => `/api/v1/accounts/${id}/mute` -const MASTODON_UNMUTE_USER_URL = (id) => `/api/v1/accounts/${id}/unmute` -const MASTODON_REMOVE_USER_FROM_FOLLOWERS = (id) => - `/api/v1/accounts/${id}/remove_from_followers` -const MASTODON_USER_NOTE_URL = (id) => `/api/v1/accounts/${id}/note` -const MASTODON_BOOKMARK_STATUS_URL = (id) => `/api/v1/statuses/${id}/bookmark` -const MASTODON_UNBOOKMARK_STATUS_URL = (id) => - `/api/v1/statuses/${id}/unbookmark` -const MASTODON_POST_STATUS_URL = '/api/v1/statuses' -const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media' -const MASTODON_VOTE_URL = (id) => `/api/v1/polls/${id}/votes` const MASTODON_POLL_URL = (id) => `/api/v1/polls/${id}` const MASTODON_STATUS_FAVORITEDBY_URL = (id) => `/api/v1/statuses/${id}/favourited_by` const MASTODON_STATUS_REBLOGGEDBY_URL = (id) => `/api/v1/statuses/${id}/reblogged_by` -const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials' -const MASTODON_REPORT_USER_URL = '/api/v1/reports' -const MASTODON_PIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/pin` -const MASTODON_UNPIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/unpin` -const MASTODON_MUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/mute` -const MASTODON_UNMUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/unmute` const MASTODON_SEARCH_2 = '/api/v2/search' const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search' -const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks' -const MASTODON_LISTS_URL = '/api/v1/lists' const MASTODON_STREAMING = '/api/v1/streaming' const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers' const MASTODON_ANNOUNCEMENTS_URL = '/api/v1/announcements' -const MASTODON_ANNOUNCEMENTS_DISMISS_URL = (id) => - `/api/v1/announcements/${id}/dismiss` const PLEROMA_EMOJI_REACTIONS_URL = (id) => `/api/v1/pleroma/statuses/${id}/reactions` -const PLEROMA_EMOJI_REACT_URL = (id, emoji) => - `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` -const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => - `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` -const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats' -const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}` -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_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => - `/api/v1/pleroma/chats/${chatId}/messages/${messageId}` -const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups' 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) => `/api/v1/pleroma/statuses/${id}/quotes` const PLEROMA_USER_FAVORITES_TIMELINE_URL = (id) => `/api/v1/pleroma/accounts/${id}/favourites` -const PLEROMA_BOOKMARK_FOLDERS_URL = '/api/v1/pleroma/bookmark_folders' -const PLEROMA_BOOKMARK_FOLDER_URL = (id) => - `/api/v1/pleroma/bookmark_folders/${id}` const EMOJI_PACKS_URL = (page, pageSize) => `/api/v1/pleroma/emoji/packs${paramsString({ page, pageSize })}` -export const updateNotificationSettings = ({ credentials, settings }) => { - return promisedRequest({ - url: NOTIFICATION_SETTINGS_URL, - credentials, - method: 'PUT', - payload: settings, - }) -} - -export const updateProfileImages = ({ - credentials, - avatar = null, - avatarName = null, - banner = null, - background = null, -}) => { - const form = new FormData() - if (avatar !== null) { - if (avatarName !== null) { - form.append('avatar', avatar, avatarName) - } else { - form.append('avatar', avatar) - } - } - if (banner !== null) form.append('header', banner) - if (background !== null) form.append('pleroma_background_image', background) - return promisedRequest({ - url: MASTODON_PROFILE_UPDATE_URL, - credentials, - method: 'PATCH', - formData: form, - }).then((data) => { - if (data.error) { - throw new Error(data.error) - } - return parseUser(data) - }) -} - -export const updateProfile = ({ credentials, params }) => { - const formData = new FormData() - - for (const name in params) { - if (name === 'fields_attributes') { - params[name].forEach((param, i) => { - formData.append(name + `[${i}][name]`, param.name) - formData.append(name + `[${i}][value]`, param.value) - }) - } else { - if (typeof params[name] === 'object') { - console.warn( - 'Object detected in updateProfile API call. This will not work, use updateProfileJSON instead.', - ) - console.warn('Object:\n' + JSON.stringify(params[name], null, 2)) - } - formData.append(name, params[name]) - } - } - - return promisedRequest({ - url: MASTODON_PROFILE_UPDATE_URL, - credentials, - method: 'PATCH', - formData, - }).then((data) => parseUser(data)) -} - -export const updateProfileJSON = ({ credentials, params }) => - promisedRequest({ - url: MASTODON_PROFILE_UPDATE_URL, - credentials, - payload: params, - method: 'PATCH', - }).then((data) => parseUser(data)) - // Params needed: // nickname // email @@ -261,118 +98,6 @@ export const getCaptcha = () => url: '/api/pleroma/captcha', }) -export const followUser = ({ id, credentials, ...options }) => { - const payload = {} - - if (options.reblogs !== undefined) { - payload.reblogs = options.reblogs - } - - if (options.notify !== undefined) { - payload.notify = options.notify - } - - return promisedRequest({ - url: MASTODON_FOLLOW_URL(id), - payload, - credentials, - method: 'POST', - }) -} - -export const unfollowUser = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNFOLLOW_URL(id), - credentials, - method: 'POST', - }) - -export const fetchUserInLists = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_USER_IN_LISTS(id), - credentials, - }) - -export const pinOwnStatus = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_PIN_OWN_STATUS(id), - credentials, - method: 'POST', - }).then((data) => parseStatus(data)) - -export const unpinOwnStatus = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNPIN_OWN_STATUS(id), - credentials, - method: 'POST', - }).then((data) => parseStatus(data)) - -export const muteConversation = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_MUTE_CONVERSATION(id), - credentials, - method: 'POST', - }).then((data) => parseStatus(data)) - -export const unmuteConversation = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNMUTE_CONVERSATION(id), - credentials, - method: 'POST', - }).then((data) => parseStatus(data)) - -export const blockUser = ({ id, expiresIn, credentials }) => { - const payload = {} - if (expiresIn) { - payload.duration = expiresIn - } - - return promisedRequest({ - url: MASTODON_BLOCK_USER_URL(id), - credentials, - method: 'POST', - payload, - }) -} - -export const unblockUser = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNBLOCK_USER_URL(id), - credentials, - method: 'POST', - }) - -export const removeUserFromFollowers = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_REMOVE_USER_FROM_FOLLOWERS(id), - credentials, - method: 'POST', - }) - -export const editUserNote = ({ id, credentials, comment }) => - promisedRequest({ - url: MASTODON_USER_NOTE_URL(id), - credentials, - payload: { - comment, - }, - method: 'POST', - }) - -export const approveUser = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_APPROVE_USER_URL(id), - credentials, - method: 'POST', - }) - -export const denyUser = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_DENY_USER_URL(id), - credentials, - method: 'POST', - }) - export const fetchUser = ({ id, credentials }) => promisedRequest({ url: `${MASTODON_USER_URL}/${id}`, @@ -397,44 +122,12 @@ export const fetchUserByName = ({ name, credentials }) => }) .then((id) => fetchUser({ id, credentials })) -export const fetchUserRelationship = ({ id, withSuspended, credentials }) => - promisedRequest({ - url: MASTODON_USER_RELATIONSHIPS_URL({ id, withSuspended }), - credentials, - }) - export const fetchFriends = ({ id, maxId, sinceId, limit = 20, credentials }) => promisedRequest({ url: MASTODON_FOLLOWING_URL(id, { maxId, sinceId, limit }), credentials, }).then((data) => data.map(parseUser)) -export const exportFriends = ({ id, credentials }) => { - // biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO refactor this - return new Promise(async (resolve, reject) => { - try { - let friends = [] - let more = true - while (more) { - const maxId = friends.length > 0 ? last(friends).id : undefined - const users = await fetchFriends({ - id, - maxId, - credentials, - withRelationships: true, - }) - friends = concat(friends, users) - if (users.length === 0) { - more = false - } - } - resolve(friends) - } catch (err) { - reject(err) - } - }) -} - export const fetchFollowers = ({ id, maxId, @@ -452,70 +145,6 @@ export const fetchFollowers = ({ credentials, }).then((data) => data.map(parseUser)) -export const fetchFollowRequests = ({ credentials }) => - promisedRequest({ - url: MASTODON_FOLLOW_REQUESTS_URL, - credentials, - }).then((data) => data.map(parseUser)) - -export const fetchLists = ({ credentials }) => - promisedRequest({ - url: MASTODON_LISTS_URL, - credentials, - }) - -export const createList = ({ title, credentials }) => - promisedRequest({ - url: MASTODON_LISTS_URL, - credentials, - method: 'POST', - payload: { title }, - }) - -export const getList = ({ listId, credentials }) => - promisedRequest({ - url: MASTODON_LIST_URL(listId), - credentials, - }) - -export const updateList = ({ listId, title, credentials }) => - promisedRequest({ - url: MASTODON_LIST_URL(listId), - - credentials, - method: 'PUT', - payload: { title }, - }) - -export const getListAccounts = ({ listId, credentials }) => - promisedRequest({ - url: MASTODON_LIST_ACCOUNTS_URL(listId), - credentials, - }).then((data) => data.map(({ id }) => id)) - -export const addAccountsToList = ({ listId, accountIds, credentials }) => - promisedRequest({ - url: MASTODON_LIST_ACCOUNTS_URL(listId), - credentials, - method: 'POST', - payload: { account_ids: accountIds }, - }) - -export const removeAccountsFromList = ({ listId, accountIds, credentials }) => - promisedRequest({ - url: MASTODON_LIST_ACCOUNTS_URL(listId), - credentials, - method: 'DELETE', - payload: { account_ids: accountIds }, - }) - -export const deleteList = ({ listId, credentials }) => - promisedRequest({ - url: MASTODON_LIST_URL(listId), - method: 'DELETE', - credentials, - }) - export const fetchConversation = ({ id, credentials }) => promisedRequest({ url: MASTODON_STATUS_CONTEXT_URL(id), @@ -680,452 +309,12 @@ export const verifyCredentials = ({ credentials }) => credentials, }).then((data) => (data.error ? data : parseUser(data))) -export const favorite = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_FAVORITE_URL(id), - method: 'POST', - credentials, - }).then((data) => parseStatus(data)) - -export const unfavorite = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNFAVORITE_URL(id), - method: 'POST', - credentials, - }).then((data) => parseStatus(data)) - -export const retweet = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_RETWEET_URL(id), - method: 'POST', - credentials, - }).then((data) => parseStatus(data)) - -export const unretweet = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNRETWEET_URL(id), - method: 'POST', - credentials, - }).then((data) => parseStatus(data)) - -export const bookmarkStatus = ({ id, credentials, ...options }) => - promisedRequest({ - url: MASTODON_BOOKMARK_STATUS_URL(id), - credentials, - method: 'POST', - payload: { - folder_id: options.folder_id, - }, - }) - -export const unbookmarkStatus = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNBOOKMARK_STATUS_URL(id), - credentials, - method: 'POST', - }) - -export const postStatus = ({ - credentials, - status, - spoilerText, - visibility, - sensitive, - poll, - mediaIds = [], - inReplyToStatusId, - quoteId, - contentType, - preview, - idempotencyKey, -}) => { - const form = new FormData() - const pollOptions = poll.options || [] - - form.append('status', status) - form.append('source', 'Pleroma FE') - if (spoilerText) form.append('spoiler_text', spoilerText) - if (visibility) form.append('visibility', visibility) - if (sensitive) form.append('sensitive', sensitive) - if (contentType) form.append('content_type', contentType) - mediaIds.forEach((val) => { - form.append('media_ids[]', val) - }) - if (pollOptions.some((option) => option !== '')) { - const normalizedPoll = { - expires_in: parseInt(poll.expiresIn, 10), - multiple: poll.multiple, - } - Object.keys(normalizedPoll).forEach((key) => { - form.append(`poll[${key}]`, normalizedPoll[key]) - }) - - pollOptions.forEach((option) => { - form.append('poll[options][]', option) - }) - } - if (inReplyToStatusId) { - form.append('in_reply_to_id', inReplyToStatusId) - } - if (quoteId) { - form.append('quote_id', quoteId) - } - if (preview) { - form.append('preview', 'true') - } - - const headers = {} - if (idempotencyKey) { - headers['idempotency-key'] = idempotencyKey - } - - return promisedRequest({ - url: MASTODON_POST_STATUS_URL, - formData: form, - method: 'POST', - credentials, - headers, - }).then((data) => (data.error ? data : parseStatus(data))) -} - -export const editStatus = ({ - id, - credentials, - status, - spoilerText, - sensitive, - poll, - mediaIds = [], - contentType, -}) => { - const form = new FormData() - const pollOptions = poll.options || [] - - form.append('status', status) - if (spoilerText) form.append('spoiler_text', spoilerText) - if (sensitive) form.append('sensitive', sensitive) - if (contentType) form.append('content_type', contentType) - mediaIds.forEach((val) => { - form.append('media_ids[]', val) - }) - - if (pollOptions.some((option) => option !== '')) { - const normalizedPoll = { - expires_in: parseInt(poll.expiresIn, 10), - multiple: poll.multiple, - } - Object.keys(normalizedPoll).forEach((key) => { - form.append(`poll[${key}]`, normalizedPoll[key]) - }) - - pollOptions.forEach((option) => { - form.append('poll[options][]', option) - }) - } - - return promisedRequest({ - url: MASTODON_STATUS_URL(id), - formData: form, - method: 'PUT', - credentials, - }).then((data) => (data.error ? data : parseStatus(data))) -} - -export const deleteStatus = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_DELETE_URL(id), - credentials, - method: 'DELETE', - }) - -export const uploadMedia = ({ formData, credentials }) => - promisedRequest({ - url: MASTODON_MEDIA_UPLOAD_URL, - formData, - method: 'POST', - credentials, - }).then((data) => parseAttachment(data)) - -export const setMediaDescription = ({ id, description, credentials }) => - promisedRequest({ - url: `${MASTODON_MEDIA_UPLOAD_URL}/${id}`, - method: 'PUT', - credentials, - payload: { - description, - }, - }).then((data) => parseAttachment(data)) - -export const importMutes = ({ file, credentials }) => { - const formData = new FormData() - formData.append('list', file) - return promisedRequest({ - url: MUTES_IMPORT_URL, - formData, - method: 'POST', - credentials, - }).then((response) => response.ok) -} - -export const importBlocks = ({ file, credentials }) => { - const formData = new FormData() - formData.append('list', file) - return promisedRequest({ - url: BLOCKS_IMPORT_URL, - formData, - method: 'POST', - credentials, - }).then((response) => response.ok) -} - -export const importFollows = ({ file, credentials }) => { - const formData = new FormData() - formData.append('list', file) - return promisedRequest({ - url: FOLLOW_IMPORT_URL, - formData, - method: 'POST', - credentials, - }).then((response) => response.ok) -} - -export const deleteAccount = ({ credentials, password }) => { - const formData = new FormData() - - formData.append('password', password) - - return promisedRequest({ - url: DELETE_ACCOUNT_URL, - formData, - method: 'POST', - credentials, - }) -} - -export const changeEmail = ({ credentials, email, password }) => { - const form = new FormData() - - form.append('email', email) - form.append('password', password) - - return promisedRequest({ - url: CHANGE_EMAIL_URL, - formData: form, - method: 'POST', - credentials, - }) -} - -export const moveAccount = ({ credentials, password, targetAccount }) => { - const form = new FormData() - - form.append('password', password) - form.append('target_account', targetAccount) - - return promisedRequest({ - url: MOVE_ACCOUNT_URL, - formData: form, - method: 'POST', - credentials, - }) -} - -export const addAlias = ({ credentials, alias }) => - promisedRequest({ - url: ALIASES_URL, - method: 'PUT', - credentials, - payload: { alias }, - }) - -export const deleteAlias = ({ credentials, alias }) => - promisedRequest({ - url: ALIASES_URL, - method: 'DELETE', - credentials, - payload: { alias }, - }) - -export const listAliases = ({ credentials }) => - promisedRequest({ - url: ALIASES_URL, - method: 'GET', - credentials, - params: { - _cacheBooster: new Date().getTime(), - }, - }) - -export const changePassword = ({ - credentials, - password, - newPassword, - newPasswordConfirmation, -}) => { - const form = new FormData() - - form.append('password', password) - form.append('new_password', newPassword) - form.append('new_password_confirmation', newPasswordConfirmation) - - return promisedRequest({ - url: CHANGE_PASSWORD_URL, - formData: form, - method: 'POST', - credentials, - }) -} - -export const settingsMFA = ({ credentials }) => - promisedRequest({ - url: MFA_SETTINGS_URL, - credentials, - method: 'GET', - }) - -export const mfaDisableOTP = ({ credentials, password }) => { - const form = new FormData() - - form.append('password', password) - - return promisedRequest({ - url: MFA_DISABLE_OTP_URL, - formData: form, - method: 'DELETE', - credentials, - }) -} - -export const mfaConfirmOTP = ({ credentials, password, token }) => { - const form = new FormData() - - form.append('password', password) - form.append('code', token) - - return promisedRequest({ - url: MFA_CONFIRM_OTP_URL, - formData: form, - credentials, - method: 'POST', - }) -} -export const mfaSetupOTP = ({ credentials }) => - promisedRequest({ - url: MFA_SETUP_OTP_URL, - credentials, - method: 'GET', - }) -export const generateMfaBackupCodes = ({ credentials }) => - promisedRequest({ - url: MFA_BACKUP_CODES_URL, - credentials, - method: 'GET', - }) - -export const fetchMutes = ({ maxId, credentials }) => - promisedRequest({ - url: MASTODON_USER_MUTES_URL({ maxId, withRelationships: true }), - credentials, - }).then((users) => users.map(parseUser)) - -export const muteUser = ({ id, expiresIn, credentials }) => { - const payload = {} - if (expiresIn) { - payload.expires_in = expiresIn - } - - return promisedRequest({ - url: MASTODON_MUTE_USER_URL(id), - credentials, - method: 'POST', - payload, - }) -} - -export const unmuteUser = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_UNMUTE_USER_URL(id), - credentials, - method: 'POST', - }) - -export const fetchBlocks = ({ maxId, credentials }) => - promisedRequest({ - url: MASTODON_USER_BLOCKS_URL({ maxId, withRelationships: true }), - credentials, - }).then((users) => users.map(parseUser)) - -export const addBackup = ({ credentials }) => - promisedRequest({ - url: PLEROMA_BACKUP_URL, - method: 'POST', - credentials, - }) - -export const listBackups = ({ credentials }) => - promisedRequest({ - url: PLEROMA_BACKUP_URL, - method: 'GET', - credentials, - params: { - _cacheBooster: new Date().getTime(), - }, - }) - -export const fetchOAuthTokens = ({ credentials }) => - promisedRequest({ - url: '/api/oauth_tokens.json', - credentials, - }) - -export const revokeOAuthToken = ({ id, credentials }) => - promisedRequest({ - url: `/api/oauth_tokens/${id}`, - credentials, - method: 'DELETE', - }) - export const suggestions = ({ credentials }) => promisedRequest({ url: SUGGESTIONS_URL, credentials, }) -export const markNotificationsAsSeen = ({ - id, - credentials, - single = false, -}) => { - const formData = new FormData() - - if (single) { - formData.append('id', id) - } else { - formData.append('max_id', id) - } - - return promisedRequest({ - url: NOTIFICATION_READ_URL, - formData, - credentials, - method: 'POST', - }) -} - -export const vote = ({ pollId, choices, credentials }) => { - const form = new FormData() - form.append('choices', choices) - - return promisedRequest({ - url: MASTODON_VOTE_URL(encodeURIComponent(pollId)), - method: 'POST', - credentials, - payload: { - choices, - }, - }) -} - export const fetchPoll = ({ pollId, credentials }) => promisedRequest({ url: MASTODON_POLL_URL(encodeURIComponent(pollId)), @@ -1158,39 +347,6 @@ export const fetchEmojiReactions = ({ id, credentials }) => }), ) -export const reactWithEmoji = ({ id, emoji, credentials }) => - promisedRequest({ - url: PLEROMA_EMOJI_REACT_URL(id, emoji), - method: 'PUT', - credentials, - }).then(parseStatus) - -export const unreactWithEmoji = ({ id, emoji, credentials }) => - promisedRequest({ - url: PLEROMA_EMOJI_UNREACT_URL(id, emoji), - method: 'DELETE', - credentials, - }).then(parseStatus) - -export const reportUser = ({ - credentials, - userId, - statusIds, - comment, - forward, -}) => - promisedRequest({ - url: MASTODON_REPORT_USER_URL, - method: 'POST', - payload: { - account_id: userId, - status_ids: statusIds, - comment, - forward, - }, - credentials, - }) - export const searchUsers = ({ credentials, query }) => promisedRequest({ url: MASTODON_USER_SEARCH_URL, @@ -1261,43 +417,9 @@ export const search2 = ({ export const fetchKnownDomains = ({ credentials }) => promisedRequest({ url: MASTODON_KNOWN_DOMAIN_LIST_URL, credentials }) -export const fetchDomainMutes = ({ credentials }) => - promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials }) - -export const muteDomain = ({ domain, credentials }) => - promisedRequest({ - url: MASTODON_DOMAIN_BLOCKS_URL, - method: 'POST', - payload: { domain }, - credentials, - }) - -export const unmuteDomain = ({ domain, credentials }) => - promisedRequest({ - url: MASTODON_DOMAIN_BLOCKS_URL, - method: 'DELETE', - payload: { domain }, - credentials, - }) - -export const dismissNotification = ({ credentials, id }) => - promisedRequest({ - url: MASTODON_DISMISS_NOTIFICATION_URL(id), - method: 'POST', - payload: { id }, - credentials, - }) - export const getAnnouncements = ({ credentials }) => promisedRequest({ url: MASTODON_ANNOUNCEMENTS_URL, credentials }) -export const dismissAnnouncement = ({ id, credentials }) => - promisedRequest({ - url: MASTODON_ANNOUNCEMENTS_DISMISS_URL(id), - credentials, - method: 'POST', - }) - export const getMastodonSocketURI = ( { credentials, stream, args = {} }, base, @@ -1473,112 +595,7 @@ export const WSConnectionStatus = Object.freeze({ STARTING_INITIAL: 6, }) -export const chats = ({ credentials }) => - promisedRequest({ - url: PLEROMA_CHATS_URL, - credentials, - }).then((data) => ({ - chatList: data.map(parseChat).filter((c) => c), - })) - -export const getOrCreateChat = ({ accountId, credentials }) => - promisedRequest({ - url: PLEROMA_CHAT_URL(accountId), - method: 'POST', - credentials, - }) - -export const chatMessages = ({ - id, - credentials, - maxId, - sinceId, - limit = 20, -}) => { - return promisedRequest({ - url: PLEROMA_CHAT_MESSAGES_URL(id, { maxId, sinceId, limit }), - method: 'GET', - credentials, - }) -} - -export const sendChatMessage = ({ - id, - content, - mediaId = null, - idempotencyKey, - credentials, -}) => { - const payload = { - content, - } - - if (mediaId) { - payload.media_id = mediaId - } - - const headers = {} - - if (idempotencyKey) { - headers['idempotency-key'] = idempotencyKey - } - - return promisedRequest({ - url: PLEROMA_CHAT_MESSAGES_URL(id), - method: 'POST', - payload, - credentials, - headers, - }) -} - -export const readChat = ({ id, lastReadId, credentials }) => - promisedRequest({ - url: PLEROMA_CHAT_READ_URL(id), - method: 'POST', - payload: { - last_read_id: lastReadId, - }, - credentials, - }) - -export const deleteChatMessage = ({ chatId, messageId, credentials }) => - promisedRequest({ - url: PLEROMA_DELETE_CHAT_MESSAGE_URL(chatId, messageId), - method: 'DELETE', - credentials, - }) - export const fetchScrobbles = ({ accountId, limit = 1 }) => promisedRequest({ url: PLEROMA_SCROBBLES_URL(accountId, { limit }), }) - -export const fetchBookmarkFolders = ({ credentials }) => - promisedRequest({ - url: PLEROMA_BOOKMARK_FOLDERS_URL, - credentials, - }) - -export const createBookmarkFolder = ({ name, emoji, credentials }) => - promisedRequest({ - url: PLEROMA_BOOKMARK_FOLDERS_URL, - credentials, - method: 'POST', - payload: { name, emoji }, - }) - -export const updateBookmarkFolder = ({ folderId, name, emoji, credentials }) => - promisedRequest({ - url: PLEROMA_BOOKMARK_FOLDER_URL(folderId), - credentials, - method: 'PATCH', - payload: { name, emoji }, - }) - -export const deleteBookmarkFolder = ({ folderId, credentials }) => - promisedRequest({ - url: PLEROMA_BOOKMARK_FOLDER_URL(folderId), - method: 'DELETE', - credentials, - }) diff --git a/src/services/api/chats.js b/src/services/api/chats.js new file mode 100644 index 000000000..61be62c52 --- /dev/null +++ b/src/services/api/chats.js @@ -0,0 +1,86 @@ +import { parseChat } from '../entity_normalizer/entity_normalizer.service.js' +import { paramsString, promisedRequest } from './helpers.js' + +const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats' +const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}` +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_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => + `/api/v1/pleroma/chats/${chatId}/messages/${messageId}` + +export const chats = ({ credentials }) => + promisedRequest({ + url: PLEROMA_CHATS_URL, + credentials, + }).then((data) => ({ + chatList: data.map(parseChat).filter((c) => c), + })) + +export const getOrCreateChat = ({ accountId, credentials }) => + promisedRequest({ + url: PLEROMA_CHAT_URL(accountId), + method: 'POST', + credentials, + }) + +export const chatMessages = ({ + id, + credentials, + maxId, + sinceId, + limit = 20, +}) => { + return promisedRequest({ + url: PLEROMA_CHAT_MESSAGES_URL(id, { maxId, sinceId, limit }), + method: 'GET', + credentials, + }) +} + +export const sendChatMessage = ({ + id, + content, + mediaId = null, + idempotencyKey, + credentials, +}) => { + const payload = { + content, + } + + if (mediaId) { + payload.media_id = mediaId + } + + const headers = {} + + if (idempotencyKey) { + headers['idempotency-key'] = idempotencyKey + } + + return promisedRequest({ + url: PLEROMA_CHAT_MESSAGES_URL(id), + method: 'POST', + payload, + credentials, + headers, + }) +} + +export const readChat = ({ id, lastReadId, credentials }) => + promisedRequest({ + url: PLEROMA_CHAT_READ_URL(id), + method: 'POST', + payload: { + last_read_id: lastReadId, + }, + credentials, + }) + +export const deleteChatMessage = ({ chatId, messageId, credentials }) => + promisedRequest({ + url: PLEROMA_DELETE_CHAT_MESSAGE_URL(chatId, messageId), + method: 'DELETE', + credentials, + }) diff --git a/src/services/api/helpers.js b/src/services/api/helpers.js index c01f2958c..1e8f257fb 100644 --- a/src/services/api/helpers.js +++ b/src/services/api/helpers.js @@ -83,9 +83,11 @@ export const promisedRequest = async ({ ...headers, }, } + if (!formData) { options.headers['Content-Type'] = 'application/json' } + if (params) { url += '?' + @@ -112,15 +114,6 @@ export const promisedRequest = async ({ // 204 is "No content", which fails to parse json (as you'd might think) if (response.ok && response.status === 204) return { _response: response } - if (!response.ok) { - throw new StatusCodeError( - response.status, - json, - { url, options }, - response, - ) - } - try { const json = await response.json() @@ -133,6 +126,15 @@ export const promisedRequest = async ({ json._response = response + if (!response.ok) { + throw new StatusCodeError( + response.status, + json, + { url, options }, + response, + ) + } + return json } catch (error) { throw new StatusCodeError( diff --git a/src/services/api/user.js b/src/services/api/user.js new file mode 100644 index 000000000..bdfc8f295 --- /dev/null +++ b/src/services/api/user.js @@ -0,0 +1,926 @@ +import { concat, each, last, map } from 'lodash' + +import { + parseAttachment, + parseNotification, + parseSource, + parseStatus, + parseUser, +} from '../entity_normalizer/entity_normalizer.service.js' +import { fetchFriends, MASTODON_STATUS_URL } from './api.service.js' +import { paramsString, promisedRequest } from './helpers.js' + +const MUTES_IMPORT_URL = '/api/pleroma/mutes_import' +const BLOCKS_IMPORT_URL = '/api/pleroma/blocks_import' +const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import' +const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account' +const CHANGE_EMAIL_URL = '/api/pleroma/change_email' +const CHANGE_PASSWORD_URL = '/api/pleroma/change_password' +const MOVE_ACCOUNT_URL = '/api/pleroma/move_account' +const ALIASES_URL = '/api/pleroma/aliases' +const NOTIFICATION_SETTINGS_URL = '/api/pleroma/notification_settings' +const NOTIFICATION_READ_URL = '/api/v1/pleroma/notifications/read' + +const MFA_SETTINGS_URL = '/api/pleroma/accounts/mfa' +const MFA_BACKUP_CODES_URL = '/api/pleroma/accounts/mfa/backup_codes' + +const MFA_SETUP_OTP_URL = '/api/pleroma/accounts/mfa/setup/totp' +const MFA_CONFIRM_OTP_URL = '/api/pleroma/accounts/mfa/confirm/totp' +const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp' + +const MASTODON_DISMISS_NOTIFICATION_URL = (id) => + `/api/v1/notifications/${id}/dismiss` +const MASTODON_FAVORITE_URL = (id) => `/api/v1/statuses/${id}/favourite` +const MASTODON_UNFAVORITE_URL = (id) => `/api/v1/statuses/${id}/unfavourite` +const MASTODON_RETWEET_URL = (id) => `/api/v1/statuses/${id}/reblog` +const MASTODON_UNRETWEET_URL = (id) => `/api/v1/statuses/${id}/unreblog` +const MASTODON_DELETE_URL = (id) => `/api/v1/statuses/${id}` +const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow` +const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow` + +const MASTODON_FOLLOW_REQUESTS_URL = '/api/v1/follow_requests' +const MASTODON_APPROVE_USER_URL = (id) => + `/api/v1/follow_requests/${id}/authorize` +const MASTODON_DENY_USER_URL = (id) => `/api/v1/follow_requests/${id}/reject` +const MASTODON_USER_RELATIONSHIPS_URL = ({ id, withSuspended }) => + `/api/v1/accounts/relationships/${paramsString({ id, withSuspended })}` +const MASTODON_USER_IN_LISTS = (id) => `/api/v1/accounts/${id}/lists` +const MASTODON_LIST_URL = (id) => `/api/v1/lists/${id}` +const MASTODON_LIST_ACCOUNTS_URL = (id) => `/api/v1/lists/${id}/accounts` +const MASTODON_USER_BLOCKS_URL = ({ + 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_UNBLOCK_USER_URL = (id) => `/api/v1/accounts/${id}/unblock` +const MASTODON_MUTE_USER_URL = (id) => `/api/v1/accounts/${id}/mute` +const MASTODON_UNMUTE_USER_URL = (id) => `/api/v1/accounts/${id}/unmute` +const MASTODON_REMOVE_USER_FROM_FOLLOWERS = (id) => + `/api/v1/accounts/${id}/remove_from_followers` +const MASTODON_USER_NOTE_URL = (id) => `/api/v1/accounts/${id}/note` +const MASTODON_BOOKMARK_STATUS_URL = (id) => `/api/v1/statuses/${id}/bookmark` +const MASTODON_UNBOOKMARK_STATUS_URL = (id) => + `/api/v1/statuses/${id}/unbookmark` +const MASTODON_POST_STATUS_URL = '/api/v1/statuses' +const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media' +const MASTODON_VOTE_URL = (id) => `/api/v1/polls/${id}/votes` +const MASTODON_PROFILE_UPDATE_URL = '/api/v1/accounts/update_credentials' +const MASTODON_REPORT_USER_URL = '/api/v1/reports' +const MASTODON_PIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/pin` +const MASTODON_UNPIN_OWN_STATUS = (id) => `/api/v1/statuses/${id}/unpin` +const MASTODON_MUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/mute` +const MASTODON_UNMUTE_CONVERSATION = (id) => `/api/v1/statuses/${id}/unmute` +const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks' +const MASTODON_LISTS_URL = '/api/v1/lists' +const MASTODON_ANNOUNCEMENTS_DISMISS_URL = (id) => + `/api/v1/announcements/${id}/dismiss` +const PLEROMA_EMOJI_REACT_URL = (id, emoji) => + `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` +const PLEROMA_EMOJI_UNREACT_URL = (id, emoji) => + `/api/v1/pleroma/statuses/${id}/reactions/${emoji}` +const PLEROMA_BACKUP_URL = '/api/v1/pleroma/backups' +const PLEROMA_BOOKMARK_FOLDERS_URL = '/api/v1/pleroma/bookmark_folders' +const PLEROMA_BOOKMARK_FOLDER_URL = (id) => + `/api/v1/pleroma/bookmark_folders/${id}` + +// #Posts +export const favorite = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_FAVORITE_URL(id), + method: 'POST', + credentials, + }).then((data) => parseStatus(data)) + +export const unfavorite = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNFAVORITE_URL(id), + method: 'POST', + credentials, + }).then((data) => parseStatus(data)) + +export const retweet = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_RETWEET_URL(id), + method: 'POST', + credentials, + }).then((data) => parseStatus(data)) + +export const unretweet = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNRETWEET_URL(id), + method: 'POST', + credentials, + }).then((data) => parseStatus(data)) + +export const reactWithEmoji = ({ id, emoji, credentials }) => + promisedRequest({ + url: PLEROMA_EMOJI_REACT_URL(id, emoji), + method: 'PUT', + credentials, + }).then(parseStatus) + +export const unreactWithEmoji = ({ id, emoji, credentials }) => + promisedRequest({ + url: PLEROMA_EMOJI_UNREACT_URL(id, emoji), + method: 'DELETE', + credentials, + }).then(parseStatus) + +export const bookmarkStatus = ({ id, credentials, ...options }) => + promisedRequest({ + url: MASTODON_BOOKMARK_STATUS_URL(id), + credentials, + method: 'POST', + payload: { + folder_id: options.folder_id, + }, + }) + +export const unbookmarkStatus = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNBOOKMARK_STATUS_URL(id), + credentials, + method: 'POST', + }) + +export const pinOwnStatus = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_PIN_OWN_STATUS(id), + credentials, + method: 'POST', + }).then((data) => parseStatus(data)) + +export const unpinOwnStatus = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNPIN_OWN_STATUS(id), + credentials, + method: 'POST', + }).then((data) => parseStatus(data)) + +export const muteConversation = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_MUTE_CONVERSATION(id), + credentials, + method: 'POST', + }).then((data) => parseStatus(data)) + +export const unmuteConversation = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNMUTE_CONVERSATION(id), + credentials, + method: 'POST', + }).then((data) => parseStatus(data)) + +export const vote = ({ pollId, choices, credentials }) => { + const form = new FormData() + form.append('choices', choices) + + return promisedRequest({ + url: MASTODON_VOTE_URL(encodeURIComponent(pollId)), + method: 'POST', + credentials, + payload: { + choices, + }, + }) +} + +// #Posting +export const postStatus = ({ + credentials, + status, + spoilerText, + visibility, + sensitive, + poll, + mediaIds = [], + inReplyToStatusId, + quoteId, + contentType, + preview, + idempotencyKey, +}) => { + const form = new FormData() + const pollOptions = poll.options || [] + + form.append('status', status) + form.append('source', 'Pleroma FE') + if (spoilerText) form.append('spoiler_text', spoilerText) + if (visibility) form.append('visibility', visibility) + if (sensitive) form.append('sensitive', sensitive) + if (contentType) form.append('content_type', contentType) + mediaIds.forEach((val) => { + form.append('media_ids[]', val) + }) + if (pollOptions.some((option) => option !== '')) { + const normalizedPoll = { + expires_in: parseInt(poll.expiresIn, 10), + multiple: poll.multiple, + } + Object.keys(normalizedPoll).forEach((key) => { + form.append(`poll[${key}]`, normalizedPoll[key]) + }) + + pollOptions.forEach((option) => { + form.append('poll[options][]', option) + }) + } + if (inReplyToStatusId) { + form.append('in_reply_to_id', inReplyToStatusId) + } + if (quoteId) { + form.append('quote_id', quoteId) + } + if (preview) { + form.append('preview', 'true') + } + + const headers = {} + if (idempotencyKey) { + headers['idempotency-key'] = idempotencyKey + } + + return promisedRequest({ + url: MASTODON_POST_STATUS_URL, + formData: form, + method: 'POST', + credentials, + headers, + }).then((data) => (data.error ? data : parseStatus(data))) +} + +export const editStatus = ({ + id, + credentials, + status, + spoilerText, + sensitive, + poll, + mediaIds = [], + contentType, +}) => { + const form = new FormData() + const pollOptions = poll.options || [] + + form.append('status', status) + if (spoilerText) form.append('spoiler_text', spoilerText) + if (sensitive) form.append('sensitive', sensitive) + if (contentType) form.append('content_type', contentType) + mediaIds.forEach((val) => { + form.append('media_ids[]', val) + }) + + if (pollOptions.some((option) => option !== '')) { + const normalizedPoll = { + expires_in: parseInt(poll.expiresIn, 10), + multiple: poll.multiple, + } + Object.keys(normalizedPoll).forEach((key) => { + form.append(`poll[${key}]`, normalizedPoll[key]) + }) + + pollOptions.forEach((option) => { + form.append('poll[options][]', option) + }) + } + + return promisedRequest({ + url: MASTODON_STATUS_URL(id), + formData: form, + method: 'PUT', + credentials, + }).then((data) => (data.error ? data : parseStatus(data))) +} + +export const deleteStatus = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_DELETE_URL(id), + credentials, + method: 'DELETE', + }) + +export const uploadMedia = ({ formData, credentials }) => + promisedRequest({ + url: MASTODON_MEDIA_UPLOAD_URL, + formData, + method: 'POST', + credentials, + }).then((data) => parseAttachment(data)) + +export const setMediaDescription = ({ id, description, credentials }) => + promisedRequest({ + url: `${MASTODON_MEDIA_UPLOAD_URL}/${id}`, + method: 'PUT', + credentials, + payload: { + description, + }, + }).then((data) => parseAttachment(data)) + +// #Notifications +export const dismissNotification = ({ credentials, id }) => + promisedRequest({ + url: MASTODON_DISMISS_NOTIFICATION_URL(id), + method: 'POST', + payload: { id }, + credentials, + }) + +export const dismissAnnouncement = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_ANNOUNCEMENTS_DISMISS_URL(id), + credentials, + method: 'POST', + }) + +export const markNotificationsAsSeen = ({ + id, + credentials, + single = false, +}) => { + const formData = new FormData() + + if (single) { + formData.append('id', id) + } else { + formData.append('max_id', id) + } + + return promisedRequest({ + url: NOTIFICATION_READ_URL, + formData, + credentials, + method: 'POST', + }) +} + +// #Imports +export const importMutes = ({ file, credentials }) => { + const formData = new FormData() + formData.append('list', file) + return promisedRequest({ + url: MUTES_IMPORT_URL, + formData, + method: 'POST', + credentials, + }).then((response) => response.ok) +} + +export const importBlocks = ({ file, credentials }) => { + const formData = new FormData() + formData.append('list', file) + return promisedRequest({ + url: BLOCKS_IMPORT_URL, + formData, + method: 'POST', + credentials, + }).then((response) => response.ok) +} + +export const importFollows = ({ file, credentials }) => { + const formData = new FormData() + formData.append('list', file) + return promisedRequest({ + url: FOLLOW_IMPORT_URL, + formData, + method: 'POST', + credentials, + }).then((response) => response.ok) +} + +export const exportFriends = ({ id, credentials }) => { + // biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO refactor this + return new Promise(async (resolve, reject) => { + try { + let friends = [] + let more = true + while (more) { + const maxId = friends.length > 0 ? last(friends).id : undefined + const users = await fetchFriends({ + id, + maxId, + credentials, + withRelationships: true, + }) + friends = concat(friends, users) + if (users.length === 0) { + more = false + } + } + resolve(friends) + } catch (err) { + reject(err) + } + }) +} + +// #Profile settings +export const updateNotificationSettings = ({ credentials, settings }) => { + return promisedRequest({ + url: NOTIFICATION_SETTINGS_URL, + credentials, + method: 'PUT', + payload: settings, + }) +} + +export const updateProfileImages = ({ + credentials, + avatar = null, + avatarName = null, + banner = null, + background = null, +}) => { + const form = new FormData() + if (avatar !== null) { + if (avatarName !== null) { + form.append('avatar', avatar, avatarName) + } else { + form.append('avatar', avatar) + } + } + if (banner !== null) form.append('header', banner) + if (background !== null) form.append('pleroma_background_image', background) + return promisedRequest({ + url: MASTODON_PROFILE_UPDATE_URL, + credentials, + method: 'PATCH', + formData: form, + }).then((data) => { + if (data.error) { + throw new Error(data.error) + } + return parseUser(data) + }) +} + +export const updateProfile = ({ credentials, params }) => { + const formData = new FormData() + + for (const name in params) { + if (name === 'fields_attributes') { + params[name].forEach((param, i) => { + formData.append(name + `[${i}][name]`, param.name) + formData.append(name + `[${i}][value]`, param.value) + }) + } else { + if (typeof params[name] === 'object') { + console.warn( + 'Object detected in updateProfile API call. This will not work, use updateProfileJSON instead.', + ) + console.warn('Object:\n' + JSON.stringify(params[name], null, 2)) + } + formData.append(name, params[name]) + } + } + + return promisedRequest({ + url: MASTODON_PROFILE_UPDATE_URL, + credentials, + method: 'PATCH', + formData, + }).then((data) => parseUser(data)) +} + +export const updateProfileJSON = ({ credentials, params }) => + promisedRequest({ + url: MASTODON_PROFILE_UPDATE_URL, + credentials, + payload: params, + method: 'PATCH', + }).then((data) => parseUser(data)) + +export const changeEmail = ({ credentials, email, password }) => { + const form = new FormData() + + form.append('email', email) + form.append('password', password) + + return promisedRequest({ + url: CHANGE_EMAIL_URL, + formData: form, + method: 'POST', + credentials, + }) +} + +export const moveAccount = ({ credentials, password, targetAccount }) => { + const form = new FormData() + + form.append('password', password) + form.append('target_account', targetAccount) + + return promisedRequest({ + url: MOVE_ACCOUNT_URL, + formData: form, + method: 'POST', + credentials, + }) +} + +export const changePassword = ({ + credentials, + password, + newPassword, + newPasswordConfirmation, +}) => { + const form = new FormData() + + form.append('password', password) + form.append('new_password', newPassword) + form.append('new_password_confirmation', newPasswordConfirmation) + + return promisedRequest({ + url: CHANGE_PASSWORD_URL, + formData: form, + method: 'POST', + credentials, + }) +} + +// #MFA +export const settingsMFA = ({ credentials }) => + promisedRequest({ + url: MFA_SETTINGS_URL, + credentials, + method: 'GET', + }) + +export const mfaDisableOTP = ({ credentials, password }) => { + const form = new FormData() + + form.append('password', password) + + return promisedRequest({ + url: MFA_DISABLE_OTP_URL, + formData: form, + method: 'DELETE', + credentials, + }) +} + +export const mfaConfirmOTP = ({ credentials, password, token }) => { + const form = new FormData() + + form.append('password', password) + form.append('code', token) + + return promisedRequest({ + url: MFA_CONFIRM_OTP_URL, + formData: form, + credentials, + method: 'POST', + }) +} +export const mfaSetupOTP = ({ credentials }) => + promisedRequest({ + url: MFA_SETUP_OTP_URL, + credentials, + method: 'GET', + }) +export const generateMfaBackupCodes = ({ credentials }) => + promisedRequest({ + url: MFA_BACKUP_CODES_URL, + credentials, + method: 'GET', + }) + +// #Aliases +export const addAlias = ({ credentials, alias }) => + promisedRequest({ + url: ALIASES_URL, + method: 'PUT', + credentials, + payload: { alias }, + }) + +export const deleteAlias = ({ credentials, alias }) => + promisedRequest({ + url: ALIASES_URL, + method: 'DELETE', + credentials, + payload: { alias }, + }) + +export const listAliases = ({ credentials }) => + promisedRequest({ + url: ALIASES_URL, + method: 'GET', + credentials, + params: { + _cacheBooster: new Date().getTime(), + }, + }) + +// User manipulation +export const fetchUserRelationship = ({ id, withSuspended, credentials }) => + promisedRequest({ + url: MASTODON_USER_RELATIONSHIPS_URL({ id, withSuspended }), + credentials, + }) + +export const followUser = ({ id, credentials, ...options }) => { + const payload = {} + + if (options.reblogs !== undefined) { + payload.reblogs = options.reblogs + } + + if (options.notify !== undefined) { + payload.notify = options.notify + } + + return promisedRequest({ + url: MASTODON_FOLLOW_URL(id), + payload, + credentials, + method: 'POST', + }) +} + +export const unfollowUser = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNFOLLOW_URL(id), + credentials, + method: 'POST', + }) +export const fetchUserInLists = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_USER_IN_LISTS(id), + credentials, + }) + +export const removeUserFromFollowers = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_REMOVE_USER_FROM_FOLLOWERS(id), + credentials, + method: 'POST', + }) + +export const fetchFollowRequests = ({ credentials }) => + promisedRequest({ + url: MASTODON_FOLLOW_REQUESTS_URL, + credentials, + }).then((data) => data.map(parseUser)) + +export const approveUser = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_APPROVE_USER_URL(id), + credentials, + method: 'POST', + }) + +export const denyUser = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_DENY_USER_URL(id), + credentials, + method: 'POST', + }) + +export const editUserNote = ({ id, credentials, comment }) => + promisedRequest({ + url: MASTODON_USER_NOTE_URL(id), + credentials, + payload: { + comment, + }, + method: 'POST', + }) + +export const fetchMutes = ({ maxId, credentials }) => + promisedRequest({ + url: MASTODON_USER_MUTES_URL({ maxId, withRelationships: true }), + credentials, + }).then((users) => users.map(parseUser)) + +export const muteUser = ({ id, expiresIn, credentials }) => { + const payload = {} + if (expiresIn) { + payload.expires_in = expiresIn + } + + return promisedRequest({ + url: MASTODON_MUTE_USER_URL(id), + credentials, + method: 'POST', + payload, + }) +} + +export const unmuteUser = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNMUTE_USER_URL(id), + credentials, + method: 'POST', + }) + +export const fetchBlocks = ({ maxId, credentials }) => + promisedRequest({ + url: MASTODON_USER_BLOCKS_URL({ maxId, withRelationships: true }), + credentials, + }).then((users) => users.map(parseUser)) + +export const blockUser = ({ id, expiresIn, credentials }) => { + const payload = {} + if (expiresIn) { + payload.duration = expiresIn + } + + return promisedRequest({ + url: MASTODON_BLOCK_USER_URL(id), + credentials, + method: 'POST', + payload, + }) +} + +export const unblockUser = ({ id, credentials }) => + promisedRequest({ + url: MASTODON_UNBLOCK_USER_URL(id), + credentials, + method: 'POST', + }) + +export const reportUser = ({ + credentials, + userId, + statusIds, + comment, + forward, +}) => + promisedRequest({ + url: MASTODON_REPORT_USER_URL, + method: 'POST', + payload: { + account_id: userId, + status_ids: statusIds, + comment, + forward, + }, + credentials, + }) + +// #Domain mutes +export const fetchDomainMutes = ({ credentials }) => + promisedRequest({ url: MASTODON_DOMAIN_BLOCKS_URL, credentials }) + +export const muteDomain = ({ domain, credentials }) => + promisedRequest({ + url: MASTODON_DOMAIN_BLOCKS_URL, + method: 'POST', + payload: { domain }, + credentials, + }) + +export const unmuteDomain = ({ domain, credentials }) => + promisedRequest({ + url: MASTODON_DOMAIN_BLOCKS_URL, + method: 'DELETE', + payload: { domain }, + credentials, + }) + +// #Backups +export const addBackup = ({ credentials }) => + promisedRequest({ + url: PLEROMA_BACKUP_URL, + method: 'POST', + credentials, + }) + +export const listBackups = ({ credentials }) => + promisedRequest({ + url: PLEROMA_BACKUP_URL, + method: 'GET', + credentials, + params: { + _cacheBooster: new Date().getTime(), + }, + }) + +// #OAuth +export const fetchOAuthTokens = ({ credentials }) => + promisedRequest({ + url: '/api/oauth_tokens.json', + credentials, + }) + +export const revokeOAuthToken = ({ id, credentials }) => + promisedRequest({ + url: `/api/oauth_tokens/${id}`, + credentials, + method: 'DELETE', + }) + +// #Lists +export const fetchLists = ({ credentials }) => + promisedRequest({ + url: MASTODON_LISTS_URL, + credentials, + }) + +export const createList = ({ title, credentials }) => + promisedRequest({ + url: MASTODON_LISTS_URL, + credentials, + method: 'POST', + payload: { title }, + }) + +export const getList = ({ listId, credentials }) => + promisedRequest({ + url: MASTODON_LIST_URL(listId), + credentials, + }) + +export const updateList = ({ listId, title, credentials }) => + promisedRequest({ + url: MASTODON_LIST_URL(listId), + + credentials, + method: 'PUT', + payload: { title }, + }) + +export const getListAccounts = ({ listId, credentials }) => + promisedRequest({ + url: MASTODON_LIST_ACCOUNTS_URL(listId), + credentials, + }).then((data) => data.map(({ id }) => id)) + +export const addAccountsToList = ({ listId, accountIds, credentials }) => + promisedRequest({ + url: MASTODON_LIST_ACCOUNTS_URL(listId), + credentials, + method: 'POST', + payload: { account_ids: accountIds }, + }) + +export const removeAccountsFromList = ({ listId, accountIds, credentials }) => + promisedRequest({ + url: MASTODON_LIST_ACCOUNTS_URL(listId), + credentials, + method: 'DELETE', + payload: { account_ids: accountIds }, + }) + +export const deleteList = ({ listId, credentials }) => + promisedRequest({ + url: MASTODON_LIST_URL(listId), + method: 'DELETE', + credentials, + }) + +// #Bookmarks +export const fetchBookmarkFolders = ({ credentials }) => + promisedRequest({ + url: PLEROMA_BOOKMARK_FOLDERS_URL, + credentials, + }) + +export const createBookmarkFolder = ({ name, emoji, credentials }) => + promisedRequest({ + url: PLEROMA_BOOKMARK_FOLDERS_URL, + credentials, + method: 'POST', + payload: { name, emoji }, + }) + +export const updateBookmarkFolder = ({ folderId, name, emoji, credentials }) => + promisedRequest({ + url: PLEROMA_BOOKMARK_FOLDER_URL(folderId), + credentials, + method: 'PATCH', + payload: { name, emoji }, + }) + +export const deleteBookmarkFolder = ({ folderId, credentials }) => + promisedRequest({ + url: PLEROMA_BOOKMARK_FOLDER_URL(folderId), + method: 'DELETE', + credentials, + }) + +// #So long and thanks for all the fish +export const deleteAccount = ({ credentials, password }) => { + const formData = new FormData() + + formData.append('password', password) + + return promisedRequest({ + url: DELETE_ACCOUNT_URL, + formData, + method: 'POST', + credentials, + }) +} diff --git a/src/services/follow_manipulate/follow_manipulate.js b/src/services/follow_manipulate/follow_manipulate.js index 1a3b2395c..d4af7f8c2 100644 --- a/src/services/follow_manipulate/follow_manipulate.js +++ b/src/services/follow_manipulate/follow_manipulate.js @@ -4,7 +4,7 @@ import { fetchUserRelationship, followUser, unfollowUser, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' const fetchRelationship = (attempt, userId, store) => new Promise((resolve, reject) => { diff --git a/src/services/follow_request_fetcher/follow_request_fetcher.service.js b/src/services/follow_request_fetcher/follow_request_fetcher.service.js index 015eb55ed..a6521601c 100644 --- a/src/services/follow_request_fetcher/follow_request_fetcher.service.js +++ b/src/services/follow_request_fetcher/follow_request_fetcher.service.js @@ -1,5 +1,5 @@ -import { fetchFollowRequests } from '../api/api.service.js' -import { promiseInterval } from '../promise_interval/promise_interval.js' +import { fetchFollowRequests } from 'src/services/api/user.js' +import { promiseInterval } from 'src/services/promise_interval/promise_interval.js' const fetchAndUpdate = ({ store, credentials }) => { return fetchFollowRequests({ credentials }) diff --git a/src/services/status_poster/status_poster.service.js b/src/services/status_poster/status_poster.service.js index 1a814ec7c..8b50e0f35 100644 --- a/src/services/status_poster/status_poster.service.js +++ b/src/services/status_poster/status_poster.service.js @@ -5,7 +5,7 @@ import { postStatus as apiPostStatus, setMediaDescription as apiSetMediaDescription, uploadMedia as apiUploadMedia, -} from '../api/api.service.js' +} from 'src/services/api/user.js' const postStatus = ({ store, diff --git a/src/stores/announcements.js b/src/stores/announcements.js index 87d83813a..27a25d195 100644 --- a/src/stores/announcements.js +++ b/src/stores/announcements.js @@ -8,10 +8,8 @@ import { editAnnouncement, postAnnouncement, } from 'src/services/api/admin.js' -import { - dismissAnnouncement, - getAnnouncements, -} from 'src/services/api/api.service.js' +import { getAnnouncements } from 'src/services/api/api.service.js' +import { dismissAnnouncement } from 'src/services/api/user.js' const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5 diff --git a/src/stores/bookmark_folders.js b/src/stores/bookmark_folders.js index 3e16121b1..c5c884f82 100644 --- a/src/stores/bookmark_folders.js +++ b/src/stores/bookmark_folders.js @@ -8,7 +8,7 @@ import { deleteBookmarkFolder, fetchBookmarkFolders, updateBookmarkFolder, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' import { promiseInterval } from 'src/services/promise_interval/promise_interval.js' export const useBookmarkFoldersStore = defineStore('bookmarkFolders', { diff --git a/src/stores/lists.js b/src/stores/lists.js index c361b6e5e..6431e1d2f 100644 --- a/src/stores/lists.js +++ b/src/stores/lists.js @@ -12,7 +12,7 @@ import { getListAccounts, removeAccountsFromList, updateList, -} from 'src/services/api/api.service.js' +} from 'src/services/api/user.js' import { promiseInterval } from 'src/services/promise_interval/promise_interval.js' export const useListsStore = defineStore('lists', { diff --git a/src/stores/oauth_tokens.js b/src/stores/oauth_tokens.js index 3f9138cec..55914386b 100644 --- a/src/stores/oauth_tokens.js +++ b/src/stores/oauth_tokens.js @@ -2,10 +2,7 @@ import { defineStore } from 'pinia' import { useOAuthStore } from 'src/stores/oauth.js' -import { - fetchOAuthTokens, - revokeOAuthToken, -} from 'src/services/api/api.service.js' +import { fetchOAuthTokens, revokeOAuthToken } from 'src/services/api/user.js' export const useOAuthTokensStore = defineStore('oauthTokens', { state: () => ({ diff --git a/src/stores/polls.js b/src/stores/polls.js index 78ccd059b..db09101ae 100644 --- a/src/stores/polls.js +++ b/src/stores/polls.js @@ -3,7 +3,8 @@ import { defineStore } from 'pinia' import { useOAuthStore } from 'src/stores/oauth.js' -import { fetchPoll, vote } from 'src/services/api/api.service.js' +import { fetchPoll } from 'src/services/api/api.service.js' +import { vote } from 'src/services/api/user.js' export const usePollsStore = defineStore('polls', { state: () => ({ diff --git a/src/stores/sync_config.js b/src/stores/sync_config.js index 348579b72..bdcc6cdb9 100644 --- a/src/stores/sync_config.js +++ b/src/stores/sync_config.js @@ -32,7 +32,7 @@ import { validateSetting, } from 'src/modules/default_config_state.js' import { oldDefaultConfigSync } from 'src/modules/old_default_config_state.js' -import { updateProfileJSON } from 'src/services/api/api.service.js' +import { updateProfileJSON } from 'src/services/api/user.js' export const VERSION = 2 export const NEW_USER_DATE = new Date('2026-03-16') // date of writing this, basically diff --git a/src/stores/user_highlight.js b/src/stores/user_highlight.js index b2cd680f5..08b739d09 100644 --- a/src/stores/user_highlight.js +++ b/src/stores/user_highlight.js @@ -17,7 +17,7 @@ import { toRaw } from 'vue' import { useOAuthStore } from 'src/stores/oauth.js' import { storage } from 'src/lib/storage.js' -import { updateProfileJSON } from 'src/services/api/api.service.js' +import { updateProfileJSON } from 'src/services/api/user.js' export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically