@cutls/megalodon
Version:
Mastodon, Pleroma, Misskey API client for node.js and browser
1,780 lines (1,779 loc) • 45.2 kB
JavaScript
import { OAuth2Client } from '@badgateway/oauth2-client'
import FormData from 'form-data'
import dayjs from 'dayjs'
import { parseLinkHeader } from './parse_link_header.js'
import PixelfedAPI from './pixelfed/api_client.js'
import { NotImplementedError } from './megalodon.js'
import * as PixelfedOAuth from './pixelfed/oauth.js'
import { NO_REDIRECT, DEFAULT_SCOPE, DEFAULT_UA } from './default.js'
import { UnknownNotificationTypeError } from './notification.js'
export default class Pixelfed {
client
baseUrl
constructor(baseUrl, accessToken = null, userAgent = DEFAULT_UA) {
let token = ''
if (accessToken) {
token = accessToken
}
let agent = DEFAULT_UA
if (userAgent) {
agent = userAgent
}
this.client = new PixelfedAPI.Client(baseUrl, token, agent)
this.baseUrl = baseUrl
}
cancel() {
return this.client.cancel()
}
async registerApp(client_name, options) {
const scopes = options.scopes || DEFAULT_SCOPE
return this.createApp(client_name, options).then(async (appData) => {
return this.generateAuthUrl(appData.client_id, appData.client_secret, {
scope: scopes,
redirect_uri: appData.redirect_uri
}).then((url) => {
appData.url = url
return appData
})
})
}
async createApp(client_name, options) {
const scopes = options.scopes || DEFAULT_SCOPE
const redirect_uris = options.redirect_uris || NO_REDIRECT
const params = {
client_name: client_name,
redirect_uris: redirect_uris,
scopes: scopes.join(' ')
}
if (options.website) params.website = options.website
return this.client.post('/api/v1/apps', params).then((res) => PixelfedOAuth.toAppData(res.data))
}
generateAuthUrl(clientId, clientSecret, options) {
const scope = options.scope || DEFAULT_SCOPE
const redirect_uri = options.redirect_uri || NO_REDIRECT
return new Promise((resolve) => {
const oauthClient = new OAuth2Client({
server: this.baseUrl,
clientId: clientId,
clientSecret: clientSecret,
tokenEndpoint: '/oauth/token',
authorizationEndpoint: '/oauth/authorize'
})
const url = oauthClient.authorizationCode.getAuthorizeUri({
redirectUri: redirect_uri,
scope: scope
})
resolve(url)
})
}
verifyAppCredentials() {
return this.client.get('/api/v1/apps/verify_credentials')
}
async fetchAccessToken(client_id, client_secret, code, redirect_uri = NO_REDIRECT) {
if (!client_id) {
throw new Error('client_id is required')
}
return this.client
.post('/oauth/token', {
client_id,
client_secret,
code,
redirect_uri,
grant_type: 'authorization_code'
})
.then((res) => PixelfedOAuth.toTokenData(res.data))
}
async refreshToken(client_id, client_secret, refresh_token) {
return this.client
.post('/oauth/token', {
client_id,
client_secret,
refresh_token,
grant_type: 'refresh_token'
})
.then((res) => PixelfedOAuth.toTokenData(res.data))
}
async revokeToken(client_id, client_secret, token) {
return this.client.post('/oauth/revoke', {
client_id,
client_secret,
token
})
}
async registerAccount(username, email, password, agreement, locale, reason) {
let params = {
username: username,
email: email,
password: password,
agreement: agreement,
locale: locale
}
if (reason) {
params = Object.assign(params, {
reason: reason
})
}
return this.client.post('/api/v1/accounts', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.token(res.data)
})
})
}
async verifyAccountCredentials() {
return this.client.get('/api/v1/accounts/verify_credentials').then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.account(res.data)
})
})
}
async updateCredentials(options) {
let params = {}
if (options) {
if (options.discoverable !== undefined) {
params = Object.assign(params, {
discoverable: options.discoverable
})
}
if (options.bot !== undefined) {
params = Object.assign(params, {
bot: options.bot
})
}
if (options.display_name) {
params = Object.assign(params, {
display_name: options.display_name
})
}
if (options.note) {
params = Object.assign(params, {
note: options.note
})
}
if (options.avatar) {
params = Object.assign(params, {
avatar: options.avatar
})
}
if (options.header) {
params = Object.assign(params, {
header: options.header
})
}
if (options.locked !== undefined) {
params = Object.assign(params, {
locked: options.locked
})
}
if (options.source) {
params = Object.assign(params, {
source: options.source
})
}
if (options.fields_attributes) {
params = Object.assign(params, {
fields_attributes: options.fields_attributes
})
}
}
return this.client.patch('/api/v1/accounts/update_credentials', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.account(res.data)
})
})
}
async getAccount(id) {
return this.client.get(`/api/v1/accounts/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.account(res.data)
})
})
}
async getAccountStatuses(id, options) {
let params = {}
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.pinned) {
params = Object.assign(params, {
pinned: options.pinned
})
}
if (options.exclude_replies) {
params = Object.assign(params, {
exclude_replies: options.exclude_replies
})
}
if (options.exclude_reblogs) {
params = Object.assign(params, {
exclude_reblogs: options.exclude_reblogs
})
}
if (options.only_media) {
params = Object.assign(params, {
only_media: options.only_media
})
}
}
return this.client.get(`/api/v1/accounts/${id}/statuses`, params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
getAccountFavourites(_id, _options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async subscribeAccount(id) {
const params = {
notify: true
}
return this.client.post(`/api/v1/accounts/${id}/follow`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async unsubscribeAccount(id) {
const params = {
notify: false
}
return this.client.post(`/api/v1/accounts/${id}/follow`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async getAccountFollowers(id, options) {
let params = {}
if (options) {
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.urlToAccounts(`/api/v1/accounts/${id}/followers`, params, options?.get_all || false, options?.sleep_ms || 0)
}
async getAccountFollowing(id, options) {
let params = {}
if (options) {
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.urlToAccounts(`/api/v1/accounts/${id}/following`, params, options?.get_all || false, options?.sleep_ms || 0)
}
async urlToAccounts(url, params, get_all, sleep_ms) {
const res = await this.client.get(url, params)
let converted = Object.assign({}, res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
if (get_all && converted.headers.link) {
let parsed = parseLinkHeader(converted.headers.link)
while (parsed['next']) {
const nextRes = await this.client.get(parsed['next'], undefined, undefined, true)
converted = Object.assign({}, converted, {
data: [...converted.data, ...nextRes.data.map((a) => PixelfedAPI.Converter.account(a))]
})
if (nextRes.headers.link === undefined) {
break
}
parsed = parseLinkHeader(nextRes.headers.link)
if (sleep_ms) {
await new Promise((converted) => setTimeout(converted, sleep_ms))
}
}
}
return converted
}
async getAccountLists(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getIdentityProof(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async followAccount(id, options) {
let params = {}
if (options) {
if (options.reblog !== undefined) {
params = Object.assign(params, {
reblog: options.reblog
})
}
}
return this.client.post(`/api/v1/accounts/${id}/follow`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async unfollowAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unfollow`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async blockAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/block`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async unblockAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unblock`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async muteAccount(id, notifications = true) {
return this.client
.post(`/api/v1/accounts/${id}/mute`, {
notifications: notifications
})
.then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async unmuteAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unmute`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async pinAccount(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async unpinAccount(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async setAccountNote(_id, _note) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getRelationship(id) {
return this.client
.get('/api/v1/accounts/relationships', {
id: [id]
})
.then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data[0])
})
})
}
async getRelationships(ids) {
return this.client
.get('/api/v1/accounts/relationships', {
id: ids
})
.then((res) => {
return Object.assign(res, {
data: res.data.map((r) => PixelfedAPI.Converter.relationship(r))
})
})
}
async searchAccount(q, options) {
let params = { q: q }
if (options) {
if (options.following !== undefined && options.following !== null) {
params = Object.assign(params, {
following: options.following
})
}
if (options.resolve !== undefined && options.resolve !== null) {
params = Object.assign(params, {
resolve: options.resolve
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/accounts/search', params).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async lookupAccount(_acct) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getBookmarks(options) {
let params = {}
if (options) {
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
}
return this.client.get('/api/v1/bookmarks', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getFavourites(options) {
let params = {}
if (options) {
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/favourites', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getMutes(options) {
let params = {}
if (options) {
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/mutes', params).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async getBlocks(options) {
let params = {}
if (options) {
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/blocks', params).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async getDomainBlocks(options) {
let params = {}
if (options) {
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/domain_blocks', params)
}
blockDomain(domain) {
return this.client.post('/api/v1/domain_blocks', {
domain: domain
})
}
unblockDomain(domain) {
return this.client.del('/api/v1/domain_blocks', {
domain: domain
})
}
async getFilters() {
return this.client.get('/api/v1/filters').then((res) => {
return Object.assign(res, {
data: res.data.map((f) => PixelfedAPI.Converter.filter(f))
})
})
}
async getFilter(id) {
return this.client.get(`/api/v1/filters/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.filter(res.data)
})
})
}
async createFilter(phrase, context, options) {
let params = {
phrase: phrase,
context: context
}
if (options) {
if (options.irreversible !== undefined) {
params = Object.assign(params, {
irreversible: options.irreversible
})
}
if (options.whole_word !== undefined) {
params = Object.assign(params, {
whole_word: options.whole_word
})
}
if (options.expires_in) {
params = Object.assign(params, {
expires_in: options.expires_in
})
}
}
return this.client.post('/api/v1/filters', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.filter(res.data)
})
})
}
async updateFilter(id, phrase, context, options) {
let params = {
phrase: phrase,
context: context
}
if (options) {
if (options.irreversible !== undefined) {
params = Object.assign(params, {
irreversible: options.irreversible
})
}
if (options.whole_word !== undefined) {
params = Object.assign(params, {
whole_word: options.whole_word
})
}
if (options.expires_in) {
params = Object.assign(params, {
expires_in: options.expires_in
})
}
}
return this.client.put(`/api/v1/filters/${id}`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.filter(res.data)
})
})
}
async deleteFilter(id) {
return this.client.del(`/api/v1/filters/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.filter(res.data)
})
})
}
async report(account_id, options) {
let params = {
account_id: account_id
}
if (options) {
if (options.status_ids) {
params = Object.assign(params, {
status_ids: options.status_ids
})
}
if (options.comment) {
params = Object.assign(params, {
comment: options.comment
})
}
if (options.forward !== undefined) {
params = Object.assign(params, {
forward: options.forward
})
}
if (options.category) {
params = Object.assign(params, {
category: options.category
})
}
if (options.rule_ids) {
params = Object.assign(params, {
rule_ids: options.rule_ids
})
}
}
return this.client.post('/api/v1/reports', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.report(res.data)
})
})
}
async getFollowRequests(limit) {
if (limit) {
return this.client
.get('/api/v1/follow_requests', {
limit: limit
})
.then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
} else {
return this.client.get('/api/v1/follow_requests').then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
}
async acceptFollowRequest(id) {
return this.client.post(`/api/v1/follow_requests/${id}/authorize`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async rejectFollowRequest(id) {
return this.client.post(`/api/v1/follow_requests/${id}/reject`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.relationship(res.data)
})
})
}
async getEndorsements(options) {
let params = {}
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
}
return this.client.get('/api/v1/endorsements', params).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async getFeaturedTags() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async createFeaturedTag(_name) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
deleteFeaturedTag(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getSuggestedTags() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getPreferences() {
return this.client.get('/api/v1/preferences').then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.preferences(res.data)
})
})
}
async getFollowedTags() {
return this.client.get('/api/v1/followed_tags').then((res) => {
return Object.assign(res, {
data: res.data.map((tag) => PixelfedAPI.Converter.tag(tag))
})
})
}
async getSuggestions(_limit) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getTag(id) {
return this.client.get(`/api/v1/tags/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.tag(res.data)
})
})
}
async followTag(id) {
return this.client.post(`/api/v1/tags/${id}/follow`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.tag(res.data)
})
})
}
async unfollowTag(id) {
return this.client.post(`/api/v1/tags/${id}/unfollow`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.tag(res.data)
})
})
}
async postStatus(status, options) {
let params = {
status: status
}
let scheduled = false
if (options) {
if (options.media_ids) {
params = Object.assign(params, {
media_ids: options.media_ids
})
}
if (options.poll) {
let pollParam = {
options: options.poll.options,
expires_in: options.poll.expires_in
}
if (options.poll.multiple !== undefined) {
pollParam = Object.assign(pollParam, {
multiple: options.poll.multiple
})
}
if (options.poll.hide_totals !== undefined) {
pollParam = Object.assign(pollParam, {
hide_totals: options.poll.hide_totals
})
}
params = Object.assign(params, {
poll: pollParam
})
}
if (options.in_reply_to_id) {
params = Object.assign(params, {
in_reply_to_id: options.in_reply_to_id
})
}
if (options.sensitive !== undefined) {
params = Object.assign(params, {
sensitive: options.sensitive
})
}
if (options.spoiler_text) {
params = Object.assign(params, {
spoiler_text: options.spoiler_text
})
}
if (options.visibility) {
params = Object.assign(params, {
visibility: PixelfedAPI.Converter.encodeVisibility(options.visibility)
})
}
if (options.scheduled_at && dayjs(options.scheduled_at).diff(dayjs(), 'seconds') > 300) {
scheduled = true
params = Object.assign(params, {
scheduled_at: options.scheduled_at
})
}
if (options.language) {
params = Object.assign(params, {
language: options.language
})
}
if (options.quote_id) {
params = Object.assign(params, {
quote_id: options.quote_id
})
}
}
if (scheduled) {
return this.client.post('/api/v1/statuses', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.scheduled_status(res.data)
})
})
}
return this.client.post('/api/v1/statuses', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async getStatus(id) {
return this.client.get(`/api/v1/statuses/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async editStatus(id, options) {
let params = {}
if (options.status) {
params = Object.assign(params, {
status: options.status
})
}
if (options.spoiler_text) {
params = Object.assign(params, {
spoiler_text: options.spoiler_text
})
}
if (options.sensitive) {
params = Object.assign(params, {
sensitive: options.sensitive
})
}
if (options.media_ids) {
params = Object.assign(params, {
media_ids: options.media_ids
})
}
if (options.poll) {
let pollParam = {}
if (options.poll.options !== undefined) {
pollParam = Object.assign(pollParam, {
options: options.poll.options
})
}
if (options.poll.expires_in !== undefined) {
pollParam = Object.assign(pollParam, {
expires_in: options.poll.expires_in
})
}
if (options.poll.multiple !== undefined) {
pollParam = Object.assign(pollParam, {
multiple: options.poll.multiple
})
}
if (options.poll.hide_totals !== undefined) {
pollParam = Object.assign(pollParam, {
hide_totals: options.poll.hide_totals
})
}
params = Object.assign(params, {
poll: pollParam
})
}
return this.client.put(`/api/v1/statuses/${id}`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async deleteStatus(id) {
return this.client.del(`/api/v1/statuses/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async getStatusContext(id, options) {
let params = {}
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
}
return this.client.get(`/api/v1/statuses/${id}/context`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.context(res.data)
})
})
}
async getStatusSource(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getStatusRebloggedBy(id) {
return this.client.get(`/api/v1/statuses/${id}/reblogged_by`).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async getStatusFavouritedBy(id) {
return this.client.get(`/api/v1/statuses/${id}/favourited_by`).then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.account(a))
})
})
}
async favouriteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/favourite`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async unfavouriteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unfavourite`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async reblogStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/reblog`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async unreblogStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unreblog`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async bookmarkStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/bookmark`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async unbookmarkStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unbookmark`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.status(res.data)
})
})
}
async muteStatus(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async unmuteStatus(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async pinStatus(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async unpinStatus(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async uploadMedia(file, options) {
const formData = new FormData()
formData.append('file', file)
if (options) {
if (options.description) {
formData.append('description', options.description)
}
if (options.focus) {
formData.append('focus', options.focus)
}
}
return this.client.postForm('/api/v2/media', formData).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.async_attachment(res.data)
})
})
}
async getMedia(id) {
const res = await this.client.get(`/api/v1/media/${id}`)
return Object.assign(res, {
data: PixelfedAPI.Converter.attachment(res.data)
})
}
async updateMedia(id, options) {
const formData = new FormData()
if (options) {
if (options.file) {
formData.append('file', options.file)
}
if (options.description) {
formData.append('description', options.description)
}
if (options.focus) {
formData.append('focus', options.focus)
}
}
return this.client.putForm(`/api/v1/media/${id}`, formData).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.attachment(res.data)
})
})
}
async getPoll(id) {
return this.client.get(`/api/v1/polls/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.poll(res.data)
})
})
}
async votePoll(id, choices) {
return this.client
.post(`/api/v1/polls/${id}/votes`, {
choices: choices
})
.then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.poll(res.data)
})
})
}
async getScheduledStatuses(options) {
let params = {}
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
}
return this.client.get('/api/v1/scheduled_statuses', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.scheduled_status(s))
})
})
}
async getScheduledStatus(id) {
return this.client.get(`/api/v1/scheduled_statuses/${id}`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.scheduled_status(res.data)
})
})
}
async scheduleStatus(id, scheduled_at) {
let params = {}
if (scheduled_at) {
params = Object.assign(params, {
scheduled_at: scheduled_at
})
}
return this.client.put(`/api/v1/scheduled_statuses/${id}`, params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.scheduled_status(res.data)
})
})
}
cancelScheduledStatus(id) {
return this.client.del(`/api/v1/scheduled_statuses/${id}`)
}
async getPublicTimeline(options) {
let params = {
local: false,
remote: true
}
if (options) {
if (options.only_media !== undefined) {
params = Object.assign(params, {
only_media: options.only_media
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/timelines/public', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getLocalTimeline(options) {
let params = {
local: true
}
if (options) {
if (options.only_media !== undefined) {
params = Object.assign(params, {
only_media: options.only_media
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/timelines/public', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getTagTimeline(hashtag, options) {
let params = {}
if (options) {
if (options.local !== undefined) {
params = Object.assign(params, {
local: options.local
})
}
if (options.only_media !== undefined) {
params = Object.assign(params, {
only_media: options.only_media
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get(`/api/v1/timelines/tag/${hashtag}`, params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getHomeTimeline(options) {
let params = {}
if (options) {
if (options.local !== undefined) {
params = Object.assign(params, {
local: options.local
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/timelines/home', params).then((res) => {
return Object.assign(res, {
data: res.data.map((s) => PixelfedAPI.Converter.status(s))
})
})
}
async getListTimeline(_list_id, _options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getConversationTimeline(options) {
let params = {}
if (options) {
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
}
return this.client.get('/api/v1/conversations', params).then((res) => {
return Object.assign(res, {
data: res.data.map((c) => PixelfedAPI.Converter.conversation(c))
})
})
}
deleteConversation(id) {
return this.client.del(`/api/v1/conversations/${id}`)
}
async readConversation(id) {
return this.client.post(`/api/v1/conversations/${id}/read`).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.conversation(res.data)
})
})
}
async getLists() {
return this.client.get('/api/v1/lists').then((res) => {
return Object.assign(res, {
data: []
})
})
}
async getList(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async createList(_title) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async updateList(_id, _title) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
deleteList(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getAccountsInList(_id, _options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
addAccountsToList(_id, _account_ids) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
deleteAccountsFromList(_id, _account_ids) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getMarkers(timeline) {
return this.client
.get('/api/v1/markers', {
timeline: timeline
})
.then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.marker(res.data)
})
})
}
async saveMarkers(options) {
let params = {}
if (options) {
if (options.home) {
params = Object.assign(params, {
home: options.home
})
}
if (options.notifications) {
params = Object.assign(params, {
notifications: options.notifications
})
}
}
return this.client.post('/api/v1/markers', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.marker(res.data)
})
})
}
async getNotifications(options) {
let params = {}
if (options) {
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.since_id) {
params = Object.assign(params, {
since_id: options.since_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.exclude_types) {
params = Object.assign(params, {
exclude_types: options.exclude_types.map((e) => PixelfedAPI.Converter.encodeNotificationType(e))
})
}
if (options.account_id) {
params = Object.assign(params, {
account_id: options.account_id
})
}
}
return this.client.get('/api/v1/notifications', params).then((res) => {
return Object.assign(res, {
data: res.data.flatMap((n) => {
const notify = PixelfedAPI.Converter.notification(n)
if (notify instanceof UnknownNotificationTypeError) return []
return notify
})
})
})
}
async getNotification(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
dismissNotifications() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
dismissNotification(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
readNotifications(_options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async subscribePushNotification(_subscription, _data) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getPushSubscription() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async updatePushSubscription(_data) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
deletePushSubscription() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async search(q, options) {
let params = {
q
}
if (options) {
if (options.type) {
params = Object.assign(params, {
type: options.type
})
}
if (options.limit) {
params = Object.assign(params, {
limit: options.limit
})
}
if (options.max_id) {
params = Object.assign(params, {
max_id: options.max_id
})
}
if (options.min_id) {
params = Object.assign(params, {
min_id: options.min_id
})
}
if (options.resolve !== undefined) {
params = Object.assign(params, {
resolve: options.resolve
})
}
if (options.offset) {
params = Object.assign(params, {
offset: options.offset
})
}
if (options.following !== undefined) {
params = Object.assign(params, {
following: options.following
})
}
if (options.account_id) {
params = Object.assign(params, {
account_id: options.account_id
})
}
if (options.exclude_unreviewed) {
params = Object.assign(params, {
exclude_unreviewed: options.exclude_unreviewed
})
}
}
return this.client.get('/api/v2/search', params).then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.results(res.data)
})
})
}
async getInstance() {
return this.client.get('/api/v1/instance').then((res) => {
return Object.assign(res, {
data: PixelfedAPI.Converter.instance(res.data)
})
})
}
getInstancePeers() {
return this.client.get('/api/v1/instance/peers')
}
async getInstanceActivity() {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getInstanceTrends(limit) {
let params = {}
if (limit) {
params = Object.assign(params, {
limit
})
}
return this.client.get('/api/v1/trends', params).then((res) => {
return Object.assign(res, {
data: res.data.map((t) => PixelfedAPI.Converter.tag(t))
})
})
}
async getInstanceDirectory(_options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getInstanceCustomEmojis() {
return this.client.get('/api/v1/custom_emojis').then((res) => {
return Object.assign(res, {
data: res.data.map((e) => PixelfedAPI.Converter.emoji(e))
})
})
}
async getInstanceAnnouncements() {
return this.client.get('/api/v1/announcements').then((res) => {
return Object.assign(res, {
data: res.data.map((a) => PixelfedAPI.Converter.announcement(a))
})
})
}
async dismissInstanceAnnouncement(id) {
return this.client.post(`/api/v1/announcements/${id}/dismiss`)
}
async addReactionToAnnouncement(id, name) {
return this.client.put(`/api/v1/announcements/${id}/reactions/${name}`)
}
async removeReactionFromAnnouncement(id, name) {
return this.client.del(`/api/v1/announcements/${id}/reactions/${name}`)
}
async createEmojiReaction(_id, _emoji) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async deleteEmojiReaction(_id, _emoji) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getEmojiReactions(_id) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async getEmojiReaction(_id, _emoji) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Pixelfed does not support this method')
reject(err)
})
}
async streamingURL() {
const instance = await this.getInstance()
if (instance.data.urls) {
return instance.data.urls.streaming_api
}
return this.baseUrl
}
async userStreaming() {
return this.client.socket()
}
async publicStreaming() {
return this.client.socket()
}
async localStreaming() {
return this.client.socket()
}
async tagStreaming(_tag) {
return this.client.socket()
}
async listStreaming(_list_id) {
return this.client.socket()
}
async directStreaming() {
return this.client.socket()
}
async userStreamingSubscription() {
return this.userStreaming()
}
async publicStreamingSubscription(socket) {
socket.subscribe('public', 'globalTimeline')
return socket
}
async localStreamingSubscription(socket) {
socket.subscribe('public:local', 'localTimeline')
return socket
}
async tagStreamingSubscription(socket, _tag) {
console.warn('misskey does not support tag streaming')
return socket
}
async listStreamingSubscription(socket, list_id) {
socket.subscribe('list', 'userList', { list: list_id })
return socket
}
async directStreamingSubscription(socket) {
console.warn('misskey does not support direct streaming')
return socket
}
}