megalodon
Version:
Fediverse API client for node.js and browser
1,478 lines (1,477 loc) • 63.6 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 MastodonAPI from './mastodon/api_client.js';
import { NotImplementedError } from './megalodon.js';
import { NO_REDIRECT, DEFAULT_SCOPE, DEFAULT_UA } from './default.js';
import * as MastodonOAuth from './mastodon/oauth.js';
import { UnknownNotificationTypeError } from './notification.js';
export default class Mastodon {
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 MastodonAPI.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) => MastodonOAuth.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) => MastodonOAuth.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) => MastodonOAuth.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: MastodonAPI.Converter.token(res.data)
});
});
}
async verifyAccountCredentials() {
return this.client.get('/api/v1/accounts/verify_credentials').then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.account(res.data)
});
});
}
async getAccount(id) {
return this.client.get(`/api/v1/accounts/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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 => MastodonAPI.Converter.status(s))
});
});
}
getAccountFavourites(_id, _options) {
return new Promise((_, reject) => {
const err = new NotImplementedError('Mastodon 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: MastodonAPI.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: MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.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 this.client.get(`/api/v1/accounts/${id}/lists`).then(res => {
return Object.assign(res, {
data: res.data.map(l => MastodonAPI.Converter.list(l))
});
});
}
async getIdentityProof(id) {
return this.client.get(`/api/v1/accounts/${id}/identity_proofs`).then(res => {
return Object.assign(res, {
data: res.data.map(i => MastodonAPI.Converter.identity_proof(i))
});
});
}
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: MastodonAPI.Converter.relationship(res.data)
});
});
}
async unfollowAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unfollow`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async blockAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/block`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async unblockAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unblock`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.relationship(res.data)
});
});
}
async unmuteAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unmute`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async pinAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/pin`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async unpinAccount(id) {
return this.client.post(`/api/v1/accounts/${id}/unpin`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async setAccountNote(id, note) {
let params = {};
if (note) {
params = Object.assign(params, {
comment: note
});
}
return this.client.post(`/api/v1/accounts/${id}/note`, params).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async getRelationship(id) {
return this.client
.get('/api/v1/accounts/relationships', {
id: [id]
})
.then(res => {
return Object.assign(res, {
data: MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.Converter.account(a))
});
});
}
async lookupAccount(acct) {
return this.client.get(`/api/v1/accounts/lookup?acct=${acct}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.account(res.data)
});
});
}
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 => MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.Converter.filter(f))
});
});
}
async getFilter(id) {
return this.client.get(`/api/v1/filters/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.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: MastodonAPI.Converter.filter(res.data)
});
});
}
async deleteFilter(id) {
return this.client.del(`/api/v1/filters/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.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 => MastodonAPI.Converter.account(a))
});
});
}
else {
return this.client.get('/api/v1/follow_requests').then(res => {
return Object.assign(res, {
data: res.data.map(a => MastodonAPI.Converter.account(a))
});
});
}
}
async acceptFollowRequest(id) {
return this.client.post(`/api/v1/follow_requests/${id}/authorize`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.relationship(res.data)
});
});
}
async rejectFollowRequest(id) {
return this.client.post(`/api/v1/follow_requests/${id}/reject`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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 => MastodonAPI.Converter.account(a))
});
});
}
async getFeaturedTags() {
return this.client.get('/api/v1/featured_tags').then(res => {
return Object.assign(res, {
data: res.data.map(f => MastodonAPI.Converter.featured_tag(f))
});
});
}
async createFeaturedTag(name) {
return this.client
.post('/api/v1/featured_tags', {
name: name
})
.then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.featured_tag(res.data)
});
});
}
deleteFeaturedTag(id) {
return this.client.del(`/api/v1/featured_tags/${id}`);
}
async getSuggestedTags() {
return this.client.get('/api/v1/featured_tags/suggestions').then(res => {
return Object.assign(res, {
data: res.data.map(t => MastodonAPI.Converter.tag(t))
});
});
}
async getPreferences() {
return this.client.get('/api/v1/preferences').then(res => {
return Object.assign(res, {
data: MastodonAPI.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 => MastodonAPI.Converter.tag(tag))
});
});
}
async getSuggestions(limit) {
if (limit) {
return this.client
.get('/api/v1/suggestions', {
limit: limit
})
.then(res => {
return Object.assign(res, {
data: res.data.map(a => MastodonAPI.Converter.account(a))
});
});
}
else {
return this.client.get('/api/v1/suggestions').then(res => {
return Object.assign(res, {
data: res.data.map(a => MastodonAPI.Converter.account(a))
});
});
}
}
async getTag(id) {
return this.client.get(`/api/v1/tags/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.tag(res.data)
});
});
}
async followTag(id) {
return this.client.post(`/api/v1/tags/${id}/follow`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.tag(res.data)
});
});
}
async unfollowTag(id) {
return this.client.post(`/api/v1/tags/${id}/unfollow`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.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: MastodonAPI.Converter.scheduled_status(res.data)
});
});
}
return this.client.post('/api/v1/statuses', params).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async getStatus(id) {
return this.client.get(`/api/v1/statuses/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.status(res.data)
});
});
}
async deleteStatus(id) {
return this.client.del(`/api/v1/statuses/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.context(res.data)
});
});
}
async getStatusSource(id) {
return this.client.get(`/api/v1/statuses/${id}/source`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status_source(res.data)
});
});
}
async getStatusRebloggedBy(id) {
return this.client.get(`/api/v1/statuses/${id}/reblogged_by`).then(res => {
return Object.assign(res, {
data: res.data.map(a => MastodonAPI.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 => MastodonAPI.Converter.account(a))
});
});
}
async favouriteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/favourite`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async unfavouriteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unfavourite`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async reblogStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/reblog`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async unreblogStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unreblog`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async bookmarkStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/bookmark`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async unbookmarkStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unbookmark`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async muteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/mute`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async unmuteStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unmute`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async pinStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/pin`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
async unpinStatus(id) {
return this.client.post(`/api/v1/statuses/${id}/unpin`).then(res => {
return Object.assign(res, {
data: MastodonAPI.Converter.status(res.data)
});
});
}
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: MastodonAPI.Converter.async_attachment(res.data)
});
});
}
async getMedia(id) {
const res = await this.client.get(`/api/v1/media/${id}`);
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.attachment(res.data)
});
});
}
async getPoll(id) {
return this.client.get(`/api/v1/polls/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.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 => MastodonAPI.Converter.scheduled_status(s))
});
});
}
async getScheduledStatus(id) {
return this.client.get(`/api/v1/scheduled_statuses/${id}`).then(res => {
return Object.assign(res, {
data: MastodonAPI.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: MastodonAPI.Converter.scheduled_status(res.data)
});
});
}
cancelScheduledStatus(id) {
return this.client.del(`/api/v1/scheduled_statuses/${id}`);
}
async getPublicTimeline(options) {
let params = {
local: false
};
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 => MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.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 => MastodonAPI.Converter.status(s))
});
});
}
async getListTimeline(list_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.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/list/${list_id}`, params).then(res => {
return Object.assign(res, {
data: res.data.map(s => MastodonAPI.Converter.status(s))
});
});
}
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 => MastodonAPI.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, {