diff options
Diffstat (limited to 'src/services/api')
| -rw-r--r-- | src/services/api/api.service.js | 275 |
1 files changed, 170 insertions, 105 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 2de87026..030c2f5e 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -1,39 +1,15 @@ /* eslint-env browser */ const LOGIN_URL = '/api/account/verify_credentials.json' -const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json' const ALL_FOLLOWING_URL = '/api/qvitter/allfollowing' -const PUBLIC_TIMELINE_URL = '/api/statuses/public_timeline.json' -const PUBLIC_AND_EXTERNAL_TIMELINE_URL = '/api/statuses/public_and_external_timeline.json' -const TAG_TIMELINE_URL = '/api/statusnet/tags/timeline' -const FAVORITE_URL = '/api/favorites/create' -const UNFAVORITE_URL = '/api/favorites/destroy' -const RETWEET_URL = '/api/statuses/retweet' -const UNRETWEET_URL = '/api/statuses/unretweet' -const STATUS_UPDATE_URL = '/api/statuses/update.json' -const STATUS_DELETE_URL = '/api/statuses/destroy' -const STATUS_URL = '/api/statuses/show' -const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload' -const CONVERSATION_URL = '/api/statusnet/conversation' const MENTIONS_URL = '/api/statuses/mentions.json' -const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json' -const FOLLOWERS_URL = '/api/statuses/followers.json' -const FRIENDS_URL = '/api/statuses/friends.json' -const BLOCKS_URL = '/api/statuses/blocks.json' -const FOLLOWING_URL = '/api/friendships/create.json' -const UNFOLLOWING_URL = '/api/friendships/destroy.json' -const QVITTER_USER_PREF_URL = '/api/qvitter/set_profile_pref.json' const REGISTRATION_URL = '/api/account/register.json' const AVATAR_UPDATE_URL = '/api/qvitter/update_avatar.json' const BG_UPDATE_URL = '/api/qvitter/update_background_image.json' const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json' const PROFILE_UPDATE_URL = '/api/account/update_profile.json' const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json' -const QVITTER_USER_TIMELINE_URL = '/api/qvitter/statuses/user_timeline.json' const QVITTER_USER_NOTIFICATIONS_URL = '/api/qvitter/statuses/notifications.json' const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json' -const BLOCKING_URL = '/api/blocks/create.json' -const UNBLOCKING_URL = '/api/blocks/destroy.json' -const USER_URL = '/api/users/show.json' const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import' const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account' const CHANGE_PASSWORD_URL = '/api/pleroma/change_password' @@ -43,9 +19,35 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny' const SUGGESTIONS_URL = '/api/v1/suggestions' const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' +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 => `/api/v1/accounts/${id}/following` +const MASTODON_FOLLOWERS_URL = id => `/api/v1/accounts/${id}/followers` +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}` +const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context` +const MASTODON_USER_URL = '/api/v1/accounts' +const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships' +const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses` +const MASTODON_TAG_TIMELINE_URL = tag => `/api/v1/timelines/tag/${tag}` +const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/' +const MASTODON_USER_MUTES_URL = '/api/v1/mutes/' +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_POST_STATUS_URL = '/api/v1/statuses' +const MASTODON_MEDIA_UPLOAD_URL = '/api/v1/media' import { each, map } from 'lodash' -import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js' +import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js' import 'whatwg-fetch' import { StatusCodeError } from '../errors/errors' @@ -59,6 +61,19 @@ let fetch = (url, options) => { return oldfetch(fullUrl, options) } +const promisedRequest = (url, options) => { + return fetch(url, options) + .then((response) => { + return new Promise((resolve, reject) => response.json() + .then((json) => { + if (!response.ok) { + return reject(new StatusCodeError(response.status, json, { url, options }, response)) + } + return resolve(json) + })) + }) +} + // Params // cropH // cropW @@ -195,7 +210,7 @@ const externalProfile = ({profileUrl, credentials}) => { } const followUser = ({id, credentials}) => { - let url = `${FOLLOWING_URL}?user_id=${id}` + let url = MASTODON_FOLLOW_URL(id) return fetch(url, { headers: authHeaders(credentials), method: 'POST' @@ -203,7 +218,7 @@ const followUser = ({id, credentials}) => { } const unfollowUser = ({id, credentials}) => { - let url = `${UNFOLLOWING_URL}?user_id=${id}` + let url = MASTODON_UNFOLLOW_URL(id) return fetch(url, { headers: authHeaders(credentials), method: 'POST' @@ -211,16 +226,14 @@ const unfollowUser = ({id, credentials}) => { } const blockUser = ({id, credentials}) => { - let url = `${BLOCKING_URL}?user_id=${id}` - return fetch(url, { + return fetch(MASTODON_BLOCK_USER_URL(id), { headers: authHeaders(credentials), method: 'POST' }).then((data) => data.json()) } const unblockUser = ({id, credentials}) => { - let url = `${UNBLOCKING_URL}?user_id=${id}` - return fetch(url, { + return fetch(MASTODON_UNBLOCK_USER_URL(id), { headers: authHeaders(credentials), method: 'POST' }).then((data) => data.json()) @@ -243,7 +256,13 @@ const denyUser = ({id, credentials}) => { } const fetchUser = ({id, credentials}) => { - let url = `${USER_URL}?user_id=${id}` + let url = `${MASTODON_USER_URL}/${id}` + return promisedRequest(url, { headers: authHeaders(credentials) }) + .then((data) => parseUser(data)) +} + +const fetchUserRelationship = ({id, credentials}) => { + let url = `${MASTODON_USER_RELATIONSHIPS_URL}/?id=${id}` return fetch(url, { headers: authHeaders(credentials) }) .then((response) => { return new Promise((resolve, reject) => response.json() @@ -254,31 +273,38 @@ const fetchUser = ({id, credentials}) => { return resolve(json) })) }) - .then((data) => parseUser(data)) } -const fetchFriends = ({id, page, credentials}) => { - let url = `${FRIENDS_URL}?user_id=${id}` - if (page) { - url = url + `&page=${page}` - } +const fetchFriends = ({id, maxId, sinceId, limit = 20, credentials}) => { + let url = MASTODON_FOLLOWING_URL(id) + const args = [ + maxId && `max_id=${maxId}`, + sinceId && `since_id=${sinceId}`, + limit && `limit=${limit}` + ].filter(_ => _).join('&') + + url = url + (args ? '?' + args : '') return fetch(url, { headers: authHeaders(credentials) }) .then((data) => data.json()) .then((data) => data.map(parseUser)) } const exportFriends = ({id, credentials}) => { - let url = `${FRIENDS_URL}?user_id=${id}&all=true` + let url = MASTODON_FOLLOWING_URL(id) + `?all=true` return fetch(url, { headers: authHeaders(credentials) }) .then((data) => data.json()) .then((data) => data.map(parseUser)) } -const fetchFollowers = ({id, page, credentials}) => { - let url = `${FOLLOWERS_URL}?user_id=${id}` - if (page) { - url = url + `&page=${page}` - } +const fetchFollowers = ({id, maxId, sinceId, limit = 20, credentials}) => { + let url = MASTODON_FOLLOWERS_URL(id) + const args = [ + maxId && `max_id=${maxId}`, + sinceId && `since_id=${sinceId}`, + limit && `limit=${limit}` + ].filter(_ => _).join('&') + + url += args ? '?' + args : '' return fetch(url, { headers: authHeaders(credentials) }) .then((data) => data.json()) .then((data) => data.map(parseUser)) @@ -298,8 +324,8 @@ const fetchFollowRequests = ({credentials}) => { } const fetchConversation = ({id, credentials}) => { - let url = `${CONVERSATION_URL}/${id}.json?count=100` - return fetch(url, { headers: authHeaders(credentials) }) + let urlContext = MASTODON_STATUS_CONTEXT_URL(id) + return fetch(urlContext, { headers: authHeaders(credentials) }) .then((data) => { if (data.ok) { return data @@ -307,11 +333,14 @@ const fetchConversation = ({id, credentials}) => { throw new Error('Error fetching timeline', data) }) .then((data) => data.json()) - .then((data) => data.map(parseStatus)) + .then(({ancestors, descendants}) => ({ + ancestors: ancestors.map(parseStatus), + descendants: descendants.map(parseStatus) + })) } const fetchStatus = ({id, credentials}) => { - let url = `${STATUS_URL}/${id}.json` + let url = MASTODON_STATUS_URL(id) return fetch(url, { headers: authHeaders(credentials) }) .then((data) => { if (data.ok) { @@ -323,57 +352,49 @@ const fetchStatus = ({id, credentials}) => { .then((data) => parseStatus(data)) } -const setUserMute = ({id, credentials, muted = true}) => { - const form = new FormData() - - const muteInteger = muted ? 1 : 0 - - form.append('namespace', 'qvitter') - form.append('data', muteInteger) - form.append('topic', `mute:${id}`) - - return fetch(QVITTER_USER_PREF_URL, { - method: 'POST', - headers: authHeaders(credentials), - body: form - }) -} - -const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => { +const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false, withMuted = false}) => { const timelineUrls = { - public: PUBLIC_TIMELINE_URL, - friends: FRIENDS_TIMELINE_URL, + public: MASTODON_PUBLIC_TIMELINE, + friends: MASTODON_USER_HOME_TIMELINE_URL, mentions: MENTIONS_URL, - dms: DM_TIMELINE_URL, + dms: MASTODON_DIRECT_MESSAGES_TIMELINE_URL, notifications: QVITTER_USER_NOTIFICATIONS_URL, - 'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL, - user: QVITTER_USER_TIMELINE_URL, - media: QVITTER_USER_TIMELINE_URL, + 'publicAndExternal': MASTODON_PUBLIC_TIMELINE, + user: MASTODON_USER_TIMELINE_URL, + media: MASTODON_USER_TIMELINE_URL, favorites: MASTODON_USER_FAVORITES_TIMELINE_URL, - tag: TAG_TIMELINE_URL + tag: MASTODON_TAG_TIMELINE_URL } const isNotifications = timeline === 'notifications' const params = [] let url = timelineUrls[timeline] + if (timeline === 'user' || timeline === 'media') { + url = url(userId) + } + if (since) { params.push(['since_id', since]) } if (until) { params.push(['max_id', until]) } - if (userId) { - params.push(['user_id', userId]) - } if (tag) { - url += `/${tag}.json` + url = url(tag) } if (timeline === 'media') { params.push(['only_media', 1]) } + if (timeline === 'public') { + params.push(['local', true]) + } + if (timeline === 'public' || timeline === 'publicAndExternal') { + params.push(['only_media', false]) + } params.push(['count', 20]) + params.push(['with_muted', withMuted]) const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') url += `?${queryString}` @@ -407,50 +428,82 @@ const verifyCredentials = (user) => { } const favorite = ({ id, credentials }) => { - return fetch(`${FAVORITE_URL}/${id}.json`, { + return fetch(MASTODON_FAVORITE_URL(id), { headers: authHeaders(credentials), method: 'POST' }) + .then(response => { + if (response.ok) { + return response.json() + } else { + throw new Error('Error favoriting post') + } + }) + .then((data) => parseStatus(data)) } const unfavorite = ({ id, credentials }) => { - return fetch(`${UNFAVORITE_URL}/${id}.json`, { + return fetch(MASTODON_UNFAVORITE_URL(id), { headers: authHeaders(credentials), method: 'POST' }) + .then(response => { + if (response.ok) { + return response.json() + } else { + throw new Error('Error removing favorite') + } + }) + .then((data) => parseStatus(data)) } const retweet = ({ id, credentials }) => { - return fetch(`${RETWEET_URL}/${id}.json`, { + return fetch(MASTODON_RETWEET_URL(id), { headers: authHeaders(credentials), method: 'POST' }) + .then(response => { + if (response.ok) { + return response.json() + } else { + throw new Error('Error repeating post') + } + }) + .then((data) => parseStatus(data)) } const unretweet = ({ id, credentials }) => { - return fetch(`${UNRETWEET_URL}/${id}.json`, { + return fetch(MASTODON_UNRETWEET_URL(id), { headers: authHeaders(credentials), method: 'POST' }) + .then(response => { + if (response.ok) { + return response.json() + } else { + throw new Error('Error removing repeat') + } + }) + .then((data) => parseStatus(data)) } -const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds, inReplyToStatusId, contentType, noAttachmentLinks}) => { - const idsText = mediaIds.join(',') +const postStatus = ({credentials, status, spoilerText, visibility, sensitive, mediaIds = [], inReplyToStatusId, contentType}) => { const form = new FormData() form.append('status', status) form.append('source', 'Pleroma FE') - if (noAttachmentLinks) form.append('no_attachment_links', noAttachmentLinks) 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) - form.append('media_ids', idsText) + mediaIds.forEach(val => { + form.append('media_ids[]', val) + }) if (inReplyToStatusId) { - form.append('in_reply_to_status_id', inReplyToStatusId) + form.append('in_reply_to_id', inReplyToStatusId) } - return fetch(STATUS_UPDATE_URL, { + return fetch(MASTODON_POST_STATUS_URL, { body: form, method: 'POST', headers: authHeaders(credentials) @@ -468,20 +521,20 @@ const postStatus = ({credentials, status, spoilerText, visibility, sensitive, me } const deleteStatus = ({ id, credentials }) => { - return fetch(`${STATUS_DELETE_URL}/${id}.json`, { + return fetch(MASTODON_DELETE_URL(id), { headers: authHeaders(credentials), - method: 'POST' + method: 'DELETE' }) } const uploadMedia = ({formData, credentials}) => { - return fetch(MEDIA_UPLOAD_URL, { + return fetch(MASTODON_MEDIA_UPLOAD_URL, { body: formData, method: 'POST', headers: authHeaders(credentials) }) - .then((response) => response.text()) - .then((text) => (new DOMParser()).parseFromString(text, 'application/xml')) + .then((data) => data.json()) + .then((data) => parseAttachment(data)) } const followImport = ({params, credentials}) => { @@ -522,30 +575,40 @@ const changePassword = ({credentials, password, newPassword, newPasswordConfirma } const fetchMutes = ({credentials}) => { - const url = '/api/qvitter/mutes.json' + return promisedRequest(MASTODON_USER_MUTES_URL, { headers: authHeaders(credentials) }) + .then((users) => users.map(parseUser)) +} - return fetch(url, { - headers: authHeaders(credentials) - }).then((data) => data.json()) +const muteUser = ({id, credentials}) => { + return promisedRequest(MASTODON_MUTE_USER_URL(id), { + headers: authHeaders(credentials), + method: 'POST' + }) } -const fetchBlocks = ({page, credentials}) => { - return fetch(BLOCKS_URL, { - headers: authHeaders(credentials) - }).then((data) => { - if (data.ok) { - return data.json() - } - throw new Error('Error fetching blocks', data) +const unmuteUser = ({id, credentials}) => { + return promisedRequest(MASTODON_UNMUTE_USER_URL(id), { + headers: authHeaders(credentials), + method: 'POST' }) } +const fetchBlocks = ({credentials}) => { + return promisedRequest(MASTODON_USER_BLOCKS_URL, { headers: authHeaders(credentials) }) + .then((users) => users.map(parseUser)) +} + const fetchOAuthTokens = ({credentials}) => { const url = '/api/oauth_tokens.json' return fetch(url, { headers: authHeaders(credentials) - }).then((data) => data.json()) + }).then((data) => { + if (data.ok) { + return data.json() + } + throw new Error('Error fetching auth tokens', data) + }) } const revokeOAuthToken = ({id, credentials}) => { @@ -588,6 +651,7 @@ const apiService = { blockUser, unblockUser, fetchUser, + fetchUserRelationship, favorite, unfavorite, retweet, @@ -596,8 +660,9 @@ const apiService = { deleteStatus, uploadMedia, fetchAllFollowing, - setUserMute, fetchMutes, + muteUser, + unmuteUser, fetchBlocks, fetchOAuthTokens, revokeOAuthToken, |
