UNPKG

@cutls/megalodon

Version:

Mastodon API client for node.js and browser

653 lines (652 loc) 26.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; import axios from 'axios'; import dayjs from 'dayjs'; import FormData from 'form-data'; import { DEFAULT_UA } from '../default'; import WebSocket from './web_socket'; import MisskeyNotificationType from './notification'; import NotificationType from '../notification'; import { isBrowser } from '../default'; import Autolinker from 'autolinker'; export var isEmojiArr = function (item) { return Array.isArray(item); }; function autoLinker(input, host) { return Autolinker.link(input, { hashtag: 'twitter', mention: 'twitter', email: false, stripPrefix: false, replaceFn: function (match) { switch (match.type) { case 'url': return true; case 'mention': return "<a href=\"https://".concat(host, "/@").concat(encodeURIComponent(match.getMention()), "\" target=\"_blank\">@").concat(match.getMention(), "</a>"); case 'hashtag': console.log('Hashtag: ', match.getHashtag()); return "<a href=\"https://".concat(host, "/tags/").concat(encodeURIComponent(match.getHashtag()), "\" target=\"_blank\">#").concat(match.getHashtag(), "</a>"); } return false; } }); } var MisskeyAPI; (function (MisskeyAPI) { var Converter; (function (Converter) { Converter.emoji = function (e) { return { shortcode: e.name, static_url: e.url, url: e.url, visible_in_picker: true }; }; Converter.emojiConverter = function (e) { if (!e) return []; if (isEmojiArr(e)) return e; var emojiArr = Object.entries(e).map(function (_a) { var _b = __read(_a, 2), key = _b[0], value = _b[1]; return { name: key, host: null, url: value, aliases: [] }; }); return emojiArr; }; Converter.user = function (u, host) { host = host.replace('https://', ''); var acct = u.username; var acctUrl = "https://".concat(host || u.host || 'example.com', "/@").concat(u.username); if (u.host) { acct = "".concat(u.username, "@").concat(u.host); acctUrl = "https://".concat(u.host, "/@").concat(u.username); } return { id: u.id, username: u.username, acct: acct, display_name: u.name || u.username, locked: false, created_at: new Date().toISOString(), followers_count: 0, following_count: 0, statuses_count: 0, note: '', url: acctUrl, avatar: u.avatarUrl, avatar_static: u.avatarUrl, header: u.avatarUrl, header_static: u.avatarUrl, emojis: Converter.emojiConverter(u.emojis).map(function (e) { return Converter.emoji(e); }), moved: null, fields: [], bot: false, group: false, discoverable: false, noindex: false, suspended: false, limited: false }; }; Converter.userDetail = function (u, host) { var acct = u.username; host = host.replace('https://', ''); var acctUrl = "https://".concat(host || u.host || 'example.com', "/@").concat(u.username); if (u.host) { acct = "".concat(u.username, "@").concat(u.host); acctUrl = "https://".concat(u.host, "/@").concat(u.username); } return { id: u.id, username: u.username, acct: acct, display_name: u.name || u.username, locked: !!u.isLocked, created_at: u.createdAt || new Date().toISOString(), followers_count: u.followersCount || 0, following_count: u.followingCount || 0, statuses_count: u.notesCount || 0, note: u.description || '', url: acctUrl, avatar: u.avatarUrl || 'https://http.cat/404', avatar_static: u.avatarUrl || 'https://http.cat/404', header: u.bannerUrl || u.avatarUrl || 'https://http.cat/404', header_static: u.bannerUrl || u.avatarUrl || 'https://http.cat/404', emojis: Converter.emojiConverter(u.emojis).map(function (e) { return Converter.emoji(e); }), moved: null, fields: [], bot: u.isBot || false, group: false, discoverable: false, noindex: false, suspended: false, limited: false }; }; Converter.visibility = function (v) { switch (v) { case 'public': return v; case 'home': return 'unlisted'; case 'followers': return 'private'; case 'specified': return 'direct'; } }; Converter.encodeVisibility = function (v) { switch (v) { case 'public': return v; case 'unlisted': return 'home'; case 'private': return 'followers'; case 'direct': return 'specified'; } }; Converter.fileType = function (s) { if (s === 'image/gif') { return 'gifv'; } if (s.includes('image')) { return 'image'; } if (s.includes('video')) { return 'video'; } if (s.includes('audio')) { return 'audio'; } return 'unknown'; }; Converter.file = function (f) { return { id: f.id, type: Converter.fileType(f.type), url: f.url, remote_url: f.url, preview_url: f.thumbnailUrl, text_url: f.url, meta: { width: f.properties.width, height: f.properties.height }, description: null, blurhash: null }; }; Converter.follower = function (f, host) { return Converter.user(f.follower, host); }; Converter.following = function (f, host) { return Converter.user(f.followee, host); }; Converter.relation = function (r) { return { id: r.id, following: r.isFollowing, followed_by: r.isFollowed, blocking: r.isBlocking, blocked_by: r.isBlocked, muting: r.isMuted, muting_notifications: false, requested: r.hasPendingFollowRequestFromYou, domain_blocking: false, showing_reblogs: true, endorsed: false, notifying: false, note: '' }; }; Converter.choice = function (c) { return { title: c.text, votes_count: c.votes }; }; Converter.poll = function (p) { var now = dayjs(); var expire = dayjs(p.expiresAt); var count = p.choices.reduce(function (sum, choice) { return sum + choice.votes; }, 0); return { id: '', expires_at: p.expiresAt, expired: now.isAfter(expire), multiple: p.multiple, votes_count: count, options: p.choices.map(function (c) { return Converter.choice(c); }), voted: p.choices.some(function (c) { return c.isVoted; }) }; }; Converter.note = function (n, host) { host = host.replace('https://', ''); var text = n.text ? n.text .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;') .replace(/`/g, '&#x60;') .replace(/\r?\n/g, '<br>') : ''; var html = autoLinker(text, host); return { id: n.id, uri: n.uri ? n.uri : "https://".concat(host, "/notes/").concat(n.id), url: n.uri ? n.uri : "https://".concat(host, "/notes/").concat(n.id), account: Converter.user(n.user, host), in_reply_to_id: n.replyId, in_reply_to_account_id: null, reblog: n.renote ? Converter.note(n.renote, host) : null, content: html, plain_content: n.text ? n.text : null, created_at: n.createdAt, edited_at: null, emojis: Converter.emojiConverter(n.emojis).map(function (e) { return Converter.emoji(e); }), replies_count: n.repliesCount, reblogs_count: n.renoteCount, favourites_count: 0, reblogged: false, favourited: !!n.myReaction, muted: false, sensitive: n.files ? n.files.some(function (f) { return f.isSensitive; }) : false, spoiler_text: n.cw ? n.cw : '', visibility: Converter.visibility(n.visibility), media_attachments: n.files ? n.files.map(function (f) { return Converter.file(f); }) : [], mentions: [], tags: [], card: null, poll: n.poll ? Converter.poll(n.poll) : null, application: null, language: null, pinned: null, emoji_reactions: Converter.mapReactions(host, n.reactions, n.myReaction || '', n.reactionEmojis || {}), bookmarked: false, quote: !!(n.renote && n.text), quote_status_misskey: n.renote && n.text ? Converter.note(n.renote, host) : null }; }; Converter.mapReactions = function (host, r, myReaction, emojiData) { if (isEmojiArr(emojiData)) { return emojiData.map(function (e) { return { count: 0, me: false, name: e.name, url: e.url, static_url: e.url }; }); } return Object.keys(r).map(function (key) { var keyObj = key.replace(/:/g, ''); var shortcode = key.replace(/[:@.]/g, ''); var isCustomEmoji = shortcode !== key; if (myReaction && key === myReaction) { return { count: r[key], me: true, name: shortcode, url: isCustomEmoji ? emojiData[keyObj] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined, static_url: isCustomEmoji ? emojiData[keyObj] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined }; } return { count: r[key], me: false, name: shortcode, url: isCustomEmoji ? emojiData[keyObj] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined, static_url: isCustomEmoji ? emojiData[keyObj] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined }; }); }; Converter.reactions = function (r, host, emojiData) { var e_1, _a; var result = []; if (isEmojiArr(emojiData)) { return emojiData.map(function (e) { return { count: 0, me: false, name: e.name, url: e.url, static_url: e.url }; }); } var _loop_1 = function (e) { var shortcode = e.type.replace(/[:@.]/g, ''); var isCustomEmoji = shortcode !== e.type; var i = result.findIndex(function (res) { return res.name === e.type; }); if (i >= 0) { result[i].count++; } else { result.push({ count: 1, me: false, name: shortcode, url: isCustomEmoji ? emojiData[shortcode] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined, static_url: isCustomEmoji ? emojiData[shortcode] || "https://".concat(host, "/emoji/").concat(shortcode, ".webp") : undefined }); } }; try { for (var r_1 = __values(r), r_1_1 = r_1.next(); !r_1_1.done; r_1_1 = r_1.next()) { var e = r_1_1.value; _loop_1(e); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (r_1_1 && !r_1_1.done && (_a = r_1.return)) _a.call(r_1); } finally { if (e_1) throw e_1.error; } } return result; }; Converter.noteToConversation = function (n, host) { var accounts = [Converter.user(n.user, host)]; if (n.reply) { accounts.push(Converter.user(n.reply.user, host)); } return { id: n.id, accounts: accounts, last_status: Converter.note(n, host), unread: false }; }; Converter.list = function (l) { return ({ id: l.id, title: l.name, replies_policy: null }); }; Converter.encodeNotificationType = function (e) { switch (e) { case NotificationType.Follow: return MisskeyNotificationType.Follow; case NotificationType.Mention: return MisskeyNotificationType.Reply; case NotificationType.Favourite: case NotificationType.Reaction: return MisskeyNotificationType.Reaction; case NotificationType.Reblog: return MisskeyNotificationType.Renote; case NotificationType.PollVote: return MisskeyNotificationType.PollVote; case NotificationType.FollowRequest: return MisskeyNotificationType.ReceiveFollowRequest; default: return e; } }; Converter.decodeNotificationType = function (e) { switch (e) { case MisskeyNotificationType.Follow: return NotificationType.Follow; case MisskeyNotificationType.Mention: case MisskeyNotificationType.Reply: return NotificationType.Mention; case MisskeyNotificationType.Renote: case MisskeyNotificationType.Quote: return NotificationType.Reblog; case MisskeyNotificationType.Reaction: return NotificationType.Reaction; case MisskeyNotificationType.PollVote: return NotificationType.PollVote; case MisskeyNotificationType.ReceiveFollowRequest: return NotificationType.FollowRequest; case MisskeyNotificationType.FollowRequestAccepted: return NotificationType.Follow; default: return e; } }; var modelOfAcct = { id: '1', username: 'none', acct: 'none', display_name: 'none', locked: true, bot: true, discoverable: false, group: false, created_at: '1971-01-01T00:00:00.000Z', note: '', url: 'https://http.cat/404', avatar: 'https://http.cat/404', avatar_static: 'https://http.cat/404', header: 'https://http.cat/404', header_static: 'https://http.cat/404', followers_count: -1, following_count: 0, statuses_count: 0, noindex: true, emojis: [], fields: [], moved: null, suspended: false, limited: false }; Converter.notification = function (n, host) { var notification = { id: n.id, account: n.user ? Converter.user(n.user, host) : modelOfAcct, created_at: n.createdAt, type: Converter.decodeNotificationType(n.type) }; if (n.note) { notification = Object.assign(notification, { status: Converter.note(n.note, host) }); } if (n.reaction) { notification = Object.assign(notification, { emoji: n.reaction }); } return notification; }; Converter.stats = function (s) { return { user_count: s.usersCount, status_count: s.notesCount, domain_count: s.instances }; }; Converter.meta = function (m, s) { var wss = m.uri.replace(/^https:\/\//, 'wss://'); return { uri: m.uri, title: m.name, description: m.description, email: m.maintainerEmail, version: m.version, thumbnail: m.bannerUrl, urls: { streaming_api: "".concat(wss, "/streaming") }, stats: Converter.stats(s), languages: m.langs, contact_account: undefined, registrations: !m.disableRegistration, approval_required: false, configuration: { statuses: { max_characters: m.maxNoteTextLength } } }; }; Converter.hashtag = function (h) { return { name: h.tag, url: h.tag, history: [], following: false }; }; })(Converter = MisskeyAPI.Converter || (MisskeyAPI.Converter = {})); MisskeyAPI.DEFAULT_SCOPE = [ 'read:account', 'write:account', 'read:blocks', 'write:blocks', 'read:drive', 'write:drive', 'read:favorites', 'write:favorites', 'read:following', 'write:following', 'read:mutes', 'write:mutes', 'write:notes', 'read:notifications', 'write:notifications', 'read:reactions', 'write:reactions', 'write:votes' ]; var Client = (function () { function Client(baseUrl, accessToken, userAgent) { if (userAgent === void 0) { userAgent = DEFAULT_UA; } this.accessToken = accessToken; this.baseUrl = baseUrl; this.userAgent = userAgent; this.abortController = new AbortController(); axios.defaults.signal = this.abortController.signal; } Client.prototype.post = function (path_1) { return __awaiter(this, arguments, void 0, function (path, params, headers) { var options, bodyParams; if (params === void 0) { params = {}; } if (headers === void 0) { headers = {}; } return __generator(this, function (_a) { options = { headers: headers, maxContentLength: Infinity, maxBodyLength: Infinity }; bodyParams = params; if (this.accessToken) { if (params instanceof FormData) { bodyParams.set('limit', parseInt(bodyParams.get('limit'), 10)); bodyParams.append('i', this.accessToken); } else { params.limit = parseInt(params.limit, 10); bodyParams = Object.assign(params, { i: this.accessToken }); } } return [2, axios.post(this.baseUrl + path, bodyParams, options).then(function (resp) { var res = { data: resp.data, status: resp.status, statusText: resp.statusText, headers: resp.headers }; return res; })]; }); }); }; Client.prototype.cancel = function () { return this.abortController.abort(); }; Client.prototype.socket = function (channel, listId) { if (!this.accessToken) { throw new Error('accessToken is required'); } var url = this.baseUrl.replace('https://', 'wss://') + '/streaming'; var streaming = new WebSocket(url, channel, this.accessToken, listId, this.userAgent); if (!isBrowser()) { process.nextTick(function () { streaming.start(); }); } else { setTimeout(function () { streaming.start(); }, 0); } return streaming; }; return Client; }()); MisskeyAPI.Client = Client; })(MisskeyAPI || (MisskeyAPI = {})); export default MisskeyAPI;