aboutsummaryrefslogtreecommitdiff
path: root/src/services/api/api.service.js
diff options
context:
space:
mode:
authorMark Felder <feld@FreeBSD.org>2020-07-13 13:25:23 -0500
committerMark Felder <feld@FreeBSD.org>2020-07-13 13:25:23 -0500
commitda94935aaa18f16ac7fbe715c4610427d68ccf72 (patch)
tree52691b7cbac2773858b245e596d56c1c5e6ea74b /src/services/api/api.service.js
parent2eda3d687e8c986a982057c6f5eb969aa8d403d5 (diff)
parent3e09a708f600b47dde831eeddb412828b38a0cf4 (diff)
Merge branch 'develop' into refactor/notification_settings
Diffstat (limited to 'src/services/api/api.service.js')
-rw-r--r--src/services/api/api.service.js194
1 files changed, 152 insertions, 42 deletions
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index dfffc291..40ea5bd9 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,5 +1,5 @@
import { each, map, concat, last, get } from 'lodash'
-import { parseStatus, parseUser, parseNotification, parseAttachment } from '../entity_normalizer/entity_normalizer.service.js'
+import { parseStatus, parseUser, parseNotification, parseAttachment, parseChat, parseLinkHeaderPagination } from '../entity_normalizer/entity_normalizer.service.js'
import { RegistrationError, StatusCodeError } from '../errors/errors'
/* eslint-env browser */
@@ -50,6 +50,7 @@ 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_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
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`
@@ -58,6 +59,8 @@ const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe`
const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe`
+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`
@@ -78,6 +81,11 @@ const MASTODON_KNOWN_DOMAIN_LIST_URL = '/api/v1/instance/peers'
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 => `/api/v1/pleroma/chats/${id}/messages`
+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 oldfetch = window.fetch
@@ -138,20 +146,11 @@ const updateNotificationSettings = ({ credentials, settings }) => {
}).then((data) => data.json())
}
-const updateAvatar = ({ credentials, avatar }) => {
+const updateProfileImages = ({ credentials, avatar = null, banner = null, background = null }) => {
const form = new FormData()
- form.append('avatar', avatar)
- return fetch(MASTODON_PROFILE_UPDATE_URL, {
- headers: authHeaders(credentials),
- method: 'PATCH',
- body: form
- }).then((data) => data.json())
- .then((data) => parseUser(data))
-}
-
-const updateBg = ({ credentials, background }) => {
- const form = new FormData()
- form.append('pleroma_background_image', background)
+ if (avatar !== null) form.append('avatar', avatar)
+ if (banner !== null) form.append('header', banner)
+ if (background !== null) form.append('pleroma_background_image', background)
return fetch(MASTODON_PROFILE_UPDATE_URL, {
headers: authHeaders(credentials),
method: 'PATCH',
@@ -161,17 +160,6 @@ const updateBg = ({ credentials, background }) => {
.then((data) => parseUser(data))
}
-const updateBanner = ({ credentials, banner }) => {
- const form = new FormData()
- form.append('header', banner)
- return fetch(MASTODON_PROFILE_UPDATE_URL, {
- headers: authHeaders(credentials),
- method: 'PATCH',
- body: form
- }).then((data) => data.json())
- .then((data) => parseUser(data))
-}
-
const updateProfile = ({ credentials, params }) => {
return promisedRequest({
url: MASTODON_PROFILE_UPDATE_URL,
@@ -498,7 +486,8 @@ const fetchTimeline = ({
until = false,
userId = false,
tag = false,
- withMuted = false
+ withMuted = false,
+ replyVisibility = 'all'
}) => {
const timelineUrls = {
public: MASTODON_PUBLIC_TIMELINE,
@@ -509,7 +498,8 @@ const fetchTimeline = ({
user: MASTODON_USER_TIMELINE_URL,
media: MASTODON_USER_TIMELINE_URL,
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
- tag: MASTODON_TAG_TIMELINE_URL
+ tag: MASTODON_TAG_TIMELINE_URL,
+ bookmarks: MASTODON_BOOKMARK_TIMELINE_URL
}
const isNotifications = timeline === 'notifications'
const params = []
@@ -538,9 +528,12 @@ const fetchTimeline = ({
if (timeline === 'public' || timeline === 'publicAndExternal') {
params.push(['only_media', false])
}
- if (timeline !== 'favorites') {
+ if (timeline !== 'favorites' && timeline !== 'bookmarks') {
params.push(['with_muted', withMuted])
}
+ if (replyVisibility !== 'all') {
+ params.push(['reply_visibility', replyVisibility])
+ }
params.push(['limit', 20])
@@ -548,16 +541,20 @@ const fetchTimeline = ({
url += `?${queryString}`
let status = ''
let statusText = ''
+ let pagination = {}
return fetch(url, { headers: authHeaders(credentials) })
.then((data) => {
status = data.status
statusText = data.statusText
+ pagination = parseLinkHeaderPagination(data.headers.get('Link'), {
+ flakeId: timeline !== 'bookmarks' && timeline !== 'notifications'
+ })
return data
})
.then((data) => data.json())
.then((data) => {
if (!data.error) {
- return data.map(isNotifications ? parseNotification : parseStatus)
+ return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination }
} else {
data.status = status
data.statusText = statusText
@@ -608,6 +605,22 @@ const unretweet = ({ id, credentials }) => {
.then((data) => parseStatus(data))
}
+const bookmarkStatus = ({ id, credentials }) => {
+ return promisedRequest({
+ url: MASTODON_BOOKMARK_STATUS_URL(id),
+ headers: authHeaders(credentials),
+ method: 'POST'
+ })
+}
+
+const unbookmarkStatus = ({ id, credentials }) => {
+ return promisedRequest({
+ url: MASTODON_UNBOOKMARK_STATUS_URL(id),
+ headers: authHeaders(credentials),
+ method: 'POST'
+ })
+}
+
const postStatus = ({
credentials,
status,
@@ -617,7 +630,8 @@ const postStatus = ({
poll,
mediaIds = [],
inReplyToStatusId,
- contentType
+ contentType,
+ preview
}) => {
const form = new FormData()
const pollOptions = poll.options || []
@@ -647,6 +661,9 @@ const postStatus = ({
if (inReplyToStatusId) {
form.append('in_reply_to_id', inReplyToStatusId)
}
+ if (preview) {
+ form.append('preview', 'true')
+ }
return fetch(MASTODON_POST_STATUS_URL, {
body: form,
@@ -654,13 +671,7 @@ const postStatus = ({
headers: authHeaders(credentials)
})
.then((response) => {
- if (response.ok) {
- return response.json()
- } else {
- return {
- error: response
- }
- }
+ return response.json()
})
.then((data) => data.error ? data : parseStatus(data))
}
@@ -682,6 +693,17 @@ const uploadMedia = ({ formData, credentials }) => {
.then((data) => parseAttachment(data))
}
+const setMediaDescription = ({ id, description, credentials }) => {
+ return promisedRequest({
+ url: `${MASTODON_MEDIA_UPLOAD_URL}/${id}`,
+ method: 'PUT',
+ headers: authHeaders(credentials),
+ payload: {
+ description
+ }
+ }).then((data) => parseAttachment(data))
+}
+
const importBlocks = ({ file, credentials }) => {
const formData = new FormData()
formData.append('list', file)
@@ -1050,6 +1072,10 @@ const MASTODON_STREAMING_EVENTS = new Set([
'filters_changed'
])
+const PLEROMA_STREAMING_EVENTS = new Set([
+ 'pleroma:chat_update'
+])
+
// A thin wrapper around WebSocket API that allows adding a pre-processor to it
// Uses EventTarget and a CustomEvent to proxy events
export const ProcessedWS = ({
@@ -1106,7 +1132,7 @@ export const handleMastoWS = (wsEvent) => {
if (!data) return
const parsedEvent = JSON.parse(data)
const { event, payload } = parsedEvent
- if (MASTODON_STREAMING_EVENTS.has(event)) {
+ if (MASTODON_STREAMING_EVENTS.has(event) || PLEROMA_STREAMING_EVENTS.has(event)) {
// MastoBE and PleromaBE both send payload for delete as a PLAIN string
if (event === 'delete') {
return { event, id: payload }
@@ -1116,6 +1142,8 @@ export const handleMastoWS = (wsEvent) => {
return { event, status: parseStatus(data) }
} else if (event === 'notification') {
return { event, notification: parseNotification(data) }
+ } else if (event === 'pleroma:chat_update') {
+ return { event, chatUpdate: parseChat(data) }
}
} else {
console.warn('Unknown event', wsEvent)
@@ -1123,6 +1151,81 @@ export const handleMastoWS = (wsEvent) => {
}
}
+export const WSConnectionStatus = Object.freeze({
+ 'JOINED': 1,
+ 'CLOSED': 2,
+ 'ERROR': 3
+})
+
+const chats = ({ credentials }) => {
+ return fetch(PLEROMA_CHATS_URL, { headers: authHeaders(credentials) })
+ .then((data) => data.json())
+ .then((data) => {
+ return { chats: data.map(parseChat).filter(c => c) }
+ })
+}
+
+const getOrCreateChat = ({ accountId, credentials }) => {
+ return promisedRequest({
+ url: PLEROMA_CHAT_URL(accountId),
+ method: 'POST',
+ credentials
+ })
+}
+
+const chatMessages = ({ id, credentials, maxId, sinceId, limit = 20 }) => {
+ let url = PLEROMA_CHAT_MESSAGES_URL(id)
+ const args = [
+ maxId && `max_id=${maxId}`,
+ sinceId && `since_id=${sinceId}`,
+ limit && `limit=${limit}`
+ ].filter(_ => _).join('&')
+
+ url = url + (args ? '?' + args : '')
+
+ return promisedRequest({
+ url,
+ method: 'GET',
+ credentials
+ })
+}
+
+const sendChatMessage = ({ id, content, mediaId = null, credentials }) => {
+ const payload = {
+ 'content': content
+ }
+
+ if (mediaId) {
+ payload['media_id'] = mediaId
+ }
+
+ return promisedRequest({
+ url: PLEROMA_CHAT_MESSAGES_URL(id),
+ method: 'POST',
+ payload: payload,
+ credentials
+ })
+}
+
+const readChat = ({ id, lastReadId, credentials }) => {
+ return promisedRequest({
+ url: PLEROMA_CHAT_READ_URL(id),
+ method: 'POST',
+ payload: {
+ 'last_read_id': lastReadId
+ },
+ credentials
+ })
+}
+
+const deleteChatMessage = ({ chatId, messageId, credentials }) => {
+ return promisedRequest({
+ url: PLEROMA_DELETE_CHAT_MESSAGE_URL(chatId, messageId),
+ method: 'DELETE',
+ credentials
+ })
+}
+
const apiService = {
verifyCredentials,
fetchTimeline,
@@ -1146,9 +1249,12 @@ const apiService = {
unfavorite,
retweet,
unretweet,
+ bookmarkStatus,
+ unbookmarkStatus,
postStatus,
deleteStatus,
uploadMedia,
+ setMediaDescription,
fetchMutes,
muteUser,
unmuteUser,
@@ -1166,10 +1272,8 @@ const apiService = {
deactivateUser,
register,
getCaptcha,
- updateAvatar,
- updateBg,
+ updateProfileImages,
updateProfile,
- updateBanner,
importBlocks,
importFollows,
deleteAccount,
@@ -1200,7 +1304,13 @@ const apiService = {
fetchKnownDomains,
fetchDomainMutes,
muteDomain,
- unmuteDomain
+ unmuteDomain,
+ chats,
+ getOrCreateChat,
+ chatMessages,
+ sendChatMessage,
+ readChat,
+ deleteChatMessage
}
export default apiService