diff --git a/package.json b/package.json index db96ae1ca..ec899739f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "seedrandom": "^3.0.5" }, "devDependencies": { + "@types/node": "18.11.18", "@types/gulp": "4.0.10", "@types/gulp-rename": "2.0.1", "chalk": "4.1.2", diff --git a/packages/backend/package.json b/packages/backend/package.json index 6f6344102..203749092 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -28,7 +28,7 @@ "@bull-board/api": "5.2.0", "@bull-board/koa": "5.2.0", "@bull-board/ui": "5.2.0", - "@calckey/megalodon": "5.2.0", + "@calckey/megalodon": "workspace:*", "@discordapp/twemoji": "14.1.2", "@elastic/elasticsearch": "7.17.0", "@koa/cors": "3.4.3", diff --git a/packages/megalodon/.idea/.gitignore b/packages/megalodon/.idea/.gitignore new file mode 100644 index 000000000..b58b603fe --- /dev/null +++ b/packages/megalodon/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/packages/megalodon/.idea/compiler.xml b/packages/megalodon/.idea/compiler.xml new file mode 100644 index 000000000..1a2fb332e --- /dev/null +++ b/packages/megalodon/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/megalodon/.idea/inspectionProfiles/Project_Default.xml b/packages/megalodon/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..03d9549ea --- /dev/null +++ b/packages/megalodon/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/packages/megalodon/.idea/jsLibraryMappings.xml b/packages/megalodon/.idea/jsLibraryMappings.xml new file mode 100644 index 000000000..d23208fbb --- /dev/null +++ b/packages/megalodon/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/megalodon/.idea/megalodon.iml b/packages/megalodon/.idea/megalodon.iml new file mode 100644 index 000000000..24643cc37 --- /dev/null +++ b/packages/megalodon/.idea/megalodon.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/megalodon/.idea/modules.xml b/packages/megalodon/.idea/modules.xml new file mode 100644 index 000000000..2ae34ba95 --- /dev/null +++ b/packages/megalodon/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/megalodon/.idea/vcs.xml b/packages/megalodon/.idea/vcs.xml new file mode 100644 index 000000000..6c0b86358 --- /dev/null +++ b/packages/megalodon/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/megalodon/.npmignore b/packages/megalodon/.npmignore new file mode 100644 index 000000000..fd54d1deb --- /dev/null +++ b/packages/megalodon/.npmignore @@ -0,0 +1,3 @@ +node_modules +./src +tsconfig.json diff --git a/packages/megalodon/.vscode/settings.json b/packages/megalodon/.vscode/settings.json new file mode 100644 index 000000000..5af1e3ee1 --- /dev/null +++ b/packages/megalodon/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.tabCompletion": "on", + "diffEditor.codeLens": true +} \ No newline at end of file diff --git a/packages/megalodon/lib/src/cancel.d.ts b/packages/megalodon/lib/src/cancel.d.ts new file mode 100644 index 000000000..63cb98db1 --- /dev/null +++ b/packages/megalodon/lib/src/cancel.d.ts @@ -0,0 +1,5 @@ +export declare class RequestCanceledError extends Error { + isCancel: boolean; + constructor(msg: string); +} +export declare const isCancel: (value: any) => boolean; diff --git a/packages/megalodon/lib/src/cancel.js b/packages/megalodon/lib/src/cancel.js new file mode 100644 index 000000000..98620146f --- /dev/null +++ b/packages/megalodon/lib/src/cancel.js @@ -0,0 +1,33 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isCancel = exports.RequestCanceledError = void 0; +var RequestCanceledError = (function (_super) { + __extends(RequestCanceledError, _super); + function RequestCanceledError(msg) { + var _this = _super.call(this, msg) || this; + _this.isCancel = true; + Object.setPrototypeOf(_this, RequestCanceledError); + return _this; + } + return RequestCanceledError; +}(Error)); +exports.RequestCanceledError = RequestCanceledError; +var isCancel = function (value) { + return value && value.isCancel; +}; +exports.isCancel = isCancel; diff --git a/packages/megalodon/lib/src/converter.d.ts b/packages/megalodon/lib/src/converter.d.ts new file mode 100644 index 000000000..a708890bf --- /dev/null +++ b/packages/megalodon/lib/src/converter.d.ts @@ -0,0 +1,3 @@ +import MisskeyAPI from "./misskey/api_client"; +declare const _default: typeof MisskeyAPI.Converter; +export default _default; diff --git a/packages/megalodon/lib/src/converter.js b/packages/megalodon/lib/src/converter.js new file mode 100644 index 000000000..3ee998454 --- /dev/null +++ b/packages/megalodon/lib/src/converter.js @@ -0,0 +1,7 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("./misskey/api_client")); +exports.default = api_client_1.default.Converter; diff --git a/packages/megalodon/lib/src/default.d.ts b/packages/megalodon/lib/src/default.d.ts new file mode 100644 index 000000000..65c6afa45 --- /dev/null +++ b/packages/megalodon/lib/src/default.d.ts @@ -0,0 +1,3 @@ +export declare const NO_REDIRECT = "urn:ietf:wg:oauth:2.0:oob"; +export declare const DEFAULT_SCOPE: string[]; +export declare const DEFAULT_UA = "megalodon"; diff --git a/packages/megalodon/lib/src/default.js b/packages/megalodon/lib/src/default.js new file mode 100644 index 000000000..926730ab4 --- /dev/null +++ b/packages/megalodon/lib/src/default.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_UA = exports.DEFAULT_SCOPE = exports.NO_REDIRECT = void 0; +exports.NO_REDIRECT = 'urn:ietf:wg:oauth:2.0:oob'; +exports.DEFAULT_SCOPE = ['read', 'write', 'follow']; +exports.DEFAULT_UA = 'megalodon'; diff --git a/packages/megalodon/lib/src/entities/account.d.ts b/packages/megalodon/lib/src/entities/account.d.ts new file mode 100644 index 000000000..66a4d87d2 --- /dev/null +++ b/packages/megalodon/lib/src/entities/account.d.ts @@ -0,0 +1,27 @@ +/// +/// +/// +declare namespace Entity { + type Account = { + id: string; + username: string; + acct: string; + display_name: string; + locked: boolean; + created_at: string; + followers_count: number; + following_count: number; + statuses_count: number; + note: string; + url: string; + avatar: string; + avatar_static: string; + header: string; + header_static: string; + emojis: Array; + moved: Account | null; + fields: Array; + bot: boolean | null; + source?: Source; + }; +} diff --git a/packages/megalodon/lib/src/entities/account.js b/packages/megalodon/lib/src/entities/account.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/account.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/activity.d.ts b/packages/megalodon/lib/src/entities/activity.d.ts new file mode 100644 index 000000000..ccfa72e8c --- /dev/null +++ b/packages/megalodon/lib/src/entities/activity.d.ts @@ -0,0 +1,8 @@ +declare namespace Entity { + type Activity = { + week: string; + statuses: string; + logins: string; + registrations: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/activity.js b/packages/megalodon/lib/src/entities/activity.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/activity.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/announcement.d.ts b/packages/megalodon/lib/src/entities/announcement.d.ts new file mode 100644 index 000000000..8438dd9aa --- /dev/null +++ b/packages/megalodon/lib/src/entities/announcement.d.ts @@ -0,0 +1,31 @@ +/// +/// +/// +declare namespace Entity { + type Announcement = { + id: string; + content: string; + starts_at: string | null; + ends_at: string | null; + published: boolean; + all_day: boolean; + published_at: string; + updated_at: string; + read?: boolean; + mentions: Array; + statuses: Array; + tags: Array; + emojis: Array; + reactions: Array; + }; + type AnnouncementAccount = { + id: string; + username: string; + url: string; + acct: string; + }; + type AnnouncementStatus = { + id: string; + url: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/announcement.js b/packages/megalodon/lib/src/entities/announcement.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/announcement.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/application.d.ts b/packages/megalodon/lib/src/entities/application.d.ts new file mode 100644 index 000000000..910f86737 --- /dev/null +++ b/packages/megalodon/lib/src/entities/application.d.ts @@ -0,0 +1,7 @@ +declare namespace Entity { + type Application = { + name: string; + website?: string | null; + vapid_key?: string | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/application.js b/packages/megalodon/lib/src/entities/application.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/application.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/async_attachment.d.ts b/packages/megalodon/lib/src/entities/async_attachment.d.ts new file mode 100644 index 000000000..911083f96 --- /dev/null +++ b/packages/megalodon/lib/src/entities/async_attachment.d.ts @@ -0,0 +1,14 @@ +/// +declare namespace Entity { + type AsyncAttachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string | null; + remote_url: string | null; + preview_url: string; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/async_attachment.js b/packages/megalodon/lib/src/entities/async_attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/async_attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/attachment.d.ts b/packages/megalodon/lib/src/entities/attachment.d.ts new file mode 100644 index 000000000..bbb94f3cd --- /dev/null +++ b/packages/megalodon/lib/src/entities/attachment.d.ts @@ -0,0 +1,41 @@ +declare namespace Entity { + type Sub = { + width?: number; + height?: number; + size?: string; + aspect?: number; + frame_rate?: string; + duration?: number; + bitrate?: number; + }; + type Focus = { + x: number; + y: number; + }; + type Meta = { + original?: Sub; + small?: Sub; + focus?: Focus; + length?: string; + duration?: number; + fps?: number; + size?: string; + width?: number; + height?: number; + aspect?: number; + audio_encode?: string; + audio_bitrate?: string; + audio_channel?: string; + }; + type Attachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string; + remote_url: string | null; + preview_url: string | null; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/attachment.js b/packages/megalodon/lib/src/entities/attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/card.d.ts b/packages/megalodon/lib/src/entities/card.d.ts new file mode 100644 index 000000000..6e319e7ba --- /dev/null +++ b/packages/megalodon/lib/src/entities/card.d.ts @@ -0,0 +1,16 @@ +declare namespace Entity { + type Card = { + url: string; + title: string; + description: string; + type: 'link' | 'photo' | 'video' | 'rich'; + image?: string; + author_name?: string; + author_url?: string; + provider_name?: string; + provider_url?: string; + html?: string; + width?: number; + height?: number; + }; +} diff --git a/packages/megalodon/lib/src/entities/card.js b/packages/megalodon/lib/src/entities/card.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/card.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/context.d.ts b/packages/megalodon/lib/src/entities/context.d.ts new file mode 100644 index 000000000..4c3397654 --- /dev/null +++ b/packages/megalodon/lib/src/entities/context.d.ts @@ -0,0 +1,7 @@ +/// +declare namespace Entity { + type Context = { + ancestors: Array; + descendants: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/context.js b/packages/megalodon/lib/src/entities/context.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/context.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/conversation.d.ts b/packages/megalodon/lib/src/entities/conversation.d.ts new file mode 100644 index 000000000..dd5a1b143 --- /dev/null +++ b/packages/megalodon/lib/src/entities/conversation.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace Entity { + type Conversation = { + id: string; + accounts: Array; + last_status: Status | null; + unread: boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/conversation.js b/packages/megalodon/lib/src/entities/conversation.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/conversation.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/emoji.d.ts b/packages/megalodon/lib/src/entities/emoji.d.ts new file mode 100644 index 000000000..ca3c19506 --- /dev/null +++ b/packages/megalodon/lib/src/entities/emoji.d.ts @@ -0,0 +1,9 @@ +declare namespace Entity { + type Emoji = { + shortcode: string; + static_url: string; + url: string; + visible_in_picker: boolean; + category: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/emoji.js b/packages/megalodon/lib/src/entities/emoji.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/emoji.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/featured_tag.d.ts b/packages/megalodon/lib/src/entities/featured_tag.d.ts new file mode 100644 index 000000000..5a8b36ff6 --- /dev/null +++ b/packages/megalodon/lib/src/entities/featured_tag.d.ts @@ -0,0 +1,8 @@ +declare namespace Entity { + type FeaturedTag = { + id: string; + name: string; + statuses_count: number; + last_status_at: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/featured_tag.js b/packages/megalodon/lib/src/entities/featured_tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/featured_tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/field.d.ts b/packages/megalodon/lib/src/entities/field.d.ts new file mode 100644 index 000000000..efa9f0aec --- /dev/null +++ b/packages/megalodon/lib/src/entities/field.d.ts @@ -0,0 +1,7 @@ +declare namespace Entity { + type Field = { + name: string; + value: string; + verified_at: string | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/field.js b/packages/megalodon/lib/src/entities/field.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/field.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/filter.d.ts b/packages/megalodon/lib/src/entities/filter.d.ts new file mode 100644 index 000000000..48d0477cb --- /dev/null +++ b/packages/megalodon/lib/src/entities/filter.d.ts @@ -0,0 +1,11 @@ +declare namespace Entity { + type Filter = { + id: string; + phrase: string; + context: Array; + expires_at: string | null; + irreversible: boolean; + whole_word: boolean; + }; + type FilterContext = string; +} diff --git a/packages/megalodon/lib/src/entities/filter.js b/packages/megalodon/lib/src/entities/filter.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/filter.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/history.d.ts b/packages/megalodon/lib/src/entities/history.d.ts new file mode 100644 index 000000000..6b238a1d9 --- /dev/null +++ b/packages/megalodon/lib/src/entities/history.d.ts @@ -0,0 +1,7 @@ +declare namespace Entity { + type History = { + day: string; + uses: number; + accounts: number; + }; +} diff --git a/packages/megalodon/lib/src/entities/history.js b/packages/megalodon/lib/src/entities/history.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/history.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/identity_proof.d.ts b/packages/megalodon/lib/src/entities/identity_proof.d.ts new file mode 100644 index 000000000..7d4a4fbf0 --- /dev/null +++ b/packages/megalodon/lib/src/entities/identity_proof.d.ts @@ -0,0 +1,9 @@ +declare namespace Entity { + type IdentityProof = { + provider: string; + provider_username: string; + updated_at: string; + proof_url: string; + profile_url: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/identity_proof.js b/packages/megalodon/lib/src/entities/identity_proof.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/identity_proof.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/instance.d.ts b/packages/megalodon/lib/src/entities/instance.d.ts new file mode 100644 index 000000000..a869f7e6d --- /dev/null +++ b/packages/megalodon/lib/src/entities/instance.d.ts @@ -0,0 +1,40 @@ +/// +/// +/// +declare namespace Entity { + type Instance = { + uri: string; + title: string; + description: string; + email: string; + version: string; + thumbnail: string | null; + urls: URLs; + stats: Stats; + languages: Array; + contact_account: Account | null; + max_toot_chars?: number; + registrations?: boolean; + configuration?: { + statuses: { + max_characters: number; + max_media_attachments: number; + characters_reserved_per_url: number; + }; + media_attachments: { + supported_mime_types: Array; + image_size_limit: number; + image_matrix_limit: number; + video_size_limit: number; + video_frame_limit: number; + video_matrix_limit: number; + }; + polls: { + max_options: number; + max_characters_per_option: number; + min_expiration: number; + max_expiration: number; + }; + }; + }; +} diff --git a/packages/megalodon/lib/src/entities/instance.js b/packages/megalodon/lib/src/entities/instance.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/instance.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/list.d.ts b/packages/megalodon/lib/src/entities/list.d.ts new file mode 100644 index 000000000..ab7c6416d --- /dev/null +++ b/packages/megalodon/lib/src/entities/list.d.ts @@ -0,0 +1,6 @@ +declare namespace Entity { + type List = { + id: string; + title: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/list.js b/packages/megalodon/lib/src/entities/list.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/list.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/marker.d.ts b/packages/megalodon/lib/src/entities/marker.d.ts new file mode 100644 index 000000000..d23e1b5ef --- /dev/null +++ b/packages/megalodon/lib/src/entities/marker.d.ts @@ -0,0 +1,15 @@ +declare namespace Entity { + type Marker = { + home?: { + last_read_id: string; + version: number; + updated_at: string; + }; + notifications?: { + last_read_id: string; + version: number; + updated_at: string; + unread_count?: number; + }; + }; +} diff --git a/packages/megalodon/lib/src/entities/marker.js b/packages/megalodon/lib/src/entities/marker.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/marker.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/mention.d.ts b/packages/megalodon/lib/src/entities/mention.d.ts new file mode 100644 index 000000000..986105454 --- /dev/null +++ b/packages/megalodon/lib/src/entities/mention.d.ts @@ -0,0 +1,8 @@ +declare namespace Entity { + type Mention = { + id: string; + username: string; + url: string; + acct: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/mention.js b/packages/megalodon/lib/src/entities/mention.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/mention.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/notification.d.ts b/packages/megalodon/lib/src/entities/notification.d.ts new file mode 100644 index 000000000..2aed75789 --- /dev/null +++ b/packages/megalodon/lib/src/entities/notification.d.ts @@ -0,0 +1,13 @@ +/// +/// +declare namespace Entity { + type Notification = { + account: Account; + created_at: string; + id: string; + status?: Status; + emoji?: string; + type: NotificationType; + }; + type NotificationType = string; +} diff --git a/packages/megalodon/lib/src/entities/notification.js b/packages/megalodon/lib/src/entities/notification.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/notification.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/poll.d.ts b/packages/megalodon/lib/src/entities/poll.d.ts new file mode 100644 index 000000000..bd5fb5c48 --- /dev/null +++ b/packages/megalodon/lib/src/entities/poll.d.ts @@ -0,0 +1,12 @@ +/// +declare namespace Entity { + type Poll = { + id: string; + expires_at: string | null; + expired: boolean; + multiple: boolean; + votes_count: number; + options: Array; + voted: boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/poll.js b/packages/megalodon/lib/src/entities/poll.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/poll.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/poll_option.d.ts b/packages/megalodon/lib/src/entities/poll_option.d.ts new file mode 100644 index 000000000..968aff9a4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/poll_option.d.ts @@ -0,0 +1,6 @@ +declare namespace Entity { + type PollOption = { + title: string; + votes_count: number | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/poll_option.js b/packages/megalodon/lib/src/entities/poll_option.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/poll_option.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/preferences.d.ts b/packages/megalodon/lib/src/entities/preferences.d.ts new file mode 100644 index 000000000..79e62955d --- /dev/null +++ b/packages/megalodon/lib/src/entities/preferences.d.ts @@ -0,0 +1,9 @@ +declare namespace Entity { + type Preferences = { + 'posting:default:visibility': 'public' | 'unlisted' | 'private' | 'direct'; + 'posting:default:sensitive': boolean; + 'posting:default:language': string | null; + 'reading:expand:media': 'default' | 'show_all' | 'hide_all'; + 'reading:expand:spoilers': boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/preferences.js b/packages/megalodon/lib/src/entities/preferences.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/preferences.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/push_subscription.d.ts b/packages/megalodon/lib/src/entities/push_subscription.d.ts new file mode 100644 index 000000000..92fa7a39f --- /dev/null +++ b/packages/megalodon/lib/src/entities/push_subscription.d.ts @@ -0,0 +1,15 @@ +declare namespace Entity { + type Alerts = { + follow: boolean; + favourite: boolean; + mention: boolean; + reblog: boolean; + poll: boolean; + }; + type PushSubscription = { + id: string; + endpoint: string; + server_key: string; + alerts: Alerts; + }; +} diff --git a/packages/megalodon/lib/src/entities/push_subscription.js b/packages/megalodon/lib/src/entities/push_subscription.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/push_subscription.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/reaction.d.ts b/packages/megalodon/lib/src/entities/reaction.d.ts new file mode 100644 index 000000000..eb4cfb780 --- /dev/null +++ b/packages/megalodon/lib/src/entities/reaction.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace Entity { + type Reaction = { + count: number; + me: boolean; + name: string; + url?: string; + accounts?: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/reaction.js b/packages/megalodon/lib/src/entities/reaction.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/reaction.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/relationship.d.ts b/packages/megalodon/lib/src/entities/relationship.d.ts new file mode 100644 index 000000000..56c520131 --- /dev/null +++ b/packages/megalodon/lib/src/entities/relationship.d.ts @@ -0,0 +1,17 @@ +declare namespace Entity { + type Relationship = { + id: string; + following: boolean; + followed_by: boolean; + delivery_following?: boolean; + blocking: boolean; + blocked_by: boolean; + muting: boolean; + muting_notifications: boolean; + requested: boolean; + domain_blocking: boolean; + showing_reblogs: boolean; + endorsed: boolean; + notifying: boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/relationship.js b/packages/megalodon/lib/src/entities/relationship.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/relationship.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/report.d.ts b/packages/megalodon/lib/src/entities/report.d.ts new file mode 100644 index 000000000..6d42cbf46 --- /dev/null +++ b/packages/megalodon/lib/src/entities/report.d.ts @@ -0,0 +1,9 @@ +declare namespace Entity { + type Report = { + id: string; + action_taken: string; + comment: string; + account_id: string; + status_ids: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/report.js b/packages/megalodon/lib/src/entities/report.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/report.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/results.d.ts b/packages/megalodon/lib/src/entities/results.d.ts new file mode 100644 index 000000000..639b2fc13 --- /dev/null +++ b/packages/megalodon/lib/src/entities/results.d.ts @@ -0,0 +1,10 @@ +/// +/// +/// +declare namespace Entity { + type Results = { + accounts: Array; + statuses: Array; + hashtags: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/results.js b/packages/megalodon/lib/src/entities/results.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/results.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/scheduled_status.d.ts b/packages/megalodon/lib/src/entities/scheduled_status.d.ts new file mode 100644 index 000000000..b6842dad3 --- /dev/null +++ b/packages/megalodon/lib/src/entities/scheduled_status.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace Entity { + type ScheduledStatus = { + id: string; + scheduled_at: string; + params: StatusParams; + media_attachments: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/scheduled_status.js b/packages/megalodon/lib/src/entities/scheduled_status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/scheduled_status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/source.d.ts b/packages/megalodon/lib/src/entities/source.d.ts new file mode 100644 index 000000000..13a0cf9b6 --- /dev/null +++ b/packages/megalodon/lib/src/entities/source.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace Entity { + type Source = { + privacy: string | null; + sensitive: boolean | null; + language: string | null; + note: string; + fields: Array; + }; +} diff --git a/packages/megalodon/lib/src/entities/source.js b/packages/megalodon/lib/src/entities/source.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/source.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/stats.d.ts b/packages/megalodon/lib/src/entities/stats.d.ts new file mode 100644 index 000000000..d23ae51cb --- /dev/null +++ b/packages/megalodon/lib/src/entities/stats.d.ts @@ -0,0 +1,7 @@ +declare namespace Entity { + type Stats = { + user_count: number; + status_count: number; + domain_count: number; + }; +} diff --git a/packages/megalodon/lib/src/entities/stats.js b/packages/megalodon/lib/src/entities/stats.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/stats.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/status.d.ts b/packages/megalodon/lib/src/entities/status.d.ts new file mode 100644 index 000000000..5fdab67e0 --- /dev/null +++ b/packages/megalodon/lib/src/entities/status.d.ts @@ -0,0 +1,44 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +declare namespace Entity { + type Status = { + id: string; + uri: string; + url: string; + account: Account; + in_reply_to_id: string | null; + in_reply_to_account_id: string | null; + reblog: Status | null; + content: string; + plain_content: string | null; + created_at: string; + emojis: Emoji[]; + replies_count: number; + reblogs_count: number; + favourites_count: number; + reblogged: boolean | null; + favourited: boolean | null; + muted: boolean | null; + sensitive: boolean; + spoiler_text: string; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + media_attachments: Array; + mentions: Array; + tags: Array; + card: Card | null; + poll: Poll | null; + application: Application | null; + language: string | null; + pinned: boolean | null; + emoji_reactions: Array; + quote: Status | null; + bookmarked: boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/status.js b/packages/megalodon/lib/src/entities/status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/status_edit.d.ts b/packages/megalodon/lib/src/entities/status_edit.d.ts new file mode 100644 index 000000000..638d33b89 --- /dev/null +++ b/packages/megalodon/lib/src/entities/status_edit.d.ts @@ -0,0 +1,22 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +declare namespace Entity { + type StatusEdit = { + account: Account; + content: string; + plain_content: string | null; + created_at: string; + emojis: Emoji[]; + sensitive: boolean; + spoiler_text: string; + media_attachments: Array; + poll: Poll | null; + }; +} diff --git a/packages/megalodon/lib/src/entities/status_edit.js b/packages/megalodon/lib/src/entities/status_edit.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/status_edit.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/status_params.d.ts b/packages/megalodon/lib/src/entities/status_params.d.ts new file mode 100644 index 000000000..872be786b --- /dev/null +++ b/packages/megalodon/lib/src/entities/status_params.d.ts @@ -0,0 +1,12 @@ +declare namespace Entity { + type StatusParams = { + text: string; + in_reply_to_id: string | null; + media_ids: Array | null; + sensitive: boolean | null; + spoiler_text: string | null; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at: string | null; + application_id: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/status_params.js b/packages/megalodon/lib/src/entities/status_params.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/status_params.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/tag.d.ts b/packages/megalodon/lib/src/entities/tag.d.ts new file mode 100644 index 000000000..29130004e --- /dev/null +++ b/packages/megalodon/lib/src/entities/tag.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace Entity { + type Tag = { + name: string; + url: string; + history: Array | null; + following?: boolean; + }; +} diff --git a/packages/megalodon/lib/src/entities/tag.js b/packages/megalodon/lib/src/entities/tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/token.d.ts b/packages/megalodon/lib/src/entities/token.d.ts new file mode 100644 index 000000000..feae2d08c --- /dev/null +++ b/packages/megalodon/lib/src/entities/token.d.ts @@ -0,0 +1,8 @@ +declare namespace Entity { + type Token = { + access_token: string; + token_type: string; + scope: string; + created_at: number; + }; +} diff --git a/packages/megalodon/lib/src/entities/token.js b/packages/megalodon/lib/src/entities/token.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/token.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entities/urls.d.ts b/packages/megalodon/lib/src/entities/urls.d.ts new file mode 100644 index 000000000..3a6052851 --- /dev/null +++ b/packages/megalodon/lib/src/entities/urls.d.ts @@ -0,0 +1,5 @@ +declare namespace Entity { + type URLs = { + streaming_api: string; + }; +} diff --git a/packages/megalodon/lib/src/entities/urls.js b/packages/megalodon/lib/src/entities/urls.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/entities/urls.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/entity.d.ts b/packages/megalodon/lib/src/entity.d.ts new file mode 100644 index 000000000..6d6d3261f --- /dev/null +++ b/packages/megalodon/lib/src/entity.d.ts @@ -0,0 +1,37 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +export default Entity; diff --git a/packages/megalodon/lib/src/entity.js b/packages/megalodon/lib/src/entity.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/entity.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/src/filter_context.d.ts b/packages/megalodon/lib/src/filter_context.d.ts new file mode 100644 index 000000000..f996a3227 --- /dev/null +++ b/packages/megalodon/lib/src/filter_context.d.ts @@ -0,0 +1,9 @@ +import Entity from './entity'; +declare namespace FilterContext { + const Home: Entity.FilterContext; + const Notifications: Entity.FilterContext; + const Public: Entity.FilterContext; + const Thread: Entity.FilterContext; + const Account: Entity.FilterContext; +} +export default FilterContext; diff --git a/packages/megalodon/lib/src/filter_context.js b/packages/megalodon/lib/src/filter_context.js new file mode 100644 index 000000000..743568f6e --- /dev/null +++ b/packages/megalodon/lib/src/filter_context.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var FilterContext; +(function (FilterContext) { + FilterContext.Home = 'home'; + FilterContext.Notifications = 'notifications'; + FilterContext.Public = 'public'; + FilterContext.Thread = 'thread'; + FilterContext.Account = 'account'; +})(FilterContext || (FilterContext = {})); +exports.default = FilterContext; diff --git a/packages/megalodon/lib/src/index.d.ts b/packages/megalodon/lib/src/index.d.ts new file mode 100644 index 000000000..5a7d8776e --- /dev/null +++ b/packages/megalodon/lib/src/index.d.ts @@ -0,0 +1,12 @@ +import Response from './response'; +import OAuth from './oauth'; +import { isCancel, RequestCanceledError } from './cancel'; +import { ProxyConfig } from './proxy_config'; +import generator, { detector, MegalodonInterface, WebSocketInterface } from './megalodon'; +import Misskey from './misskey'; +import Entity from './entity'; +import NotificationType from './notification'; +import FilterContext from './filter_context'; +import Converter from './converter'; +export { Response, OAuth, RequestCanceledError, isCancel, ProxyConfig, detector, MegalodonInterface, WebSocketInterface, NotificationType, FilterContext, Misskey, Entity, Converter }; +export default generator; diff --git a/packages/megalodon/lib/src/index.js b/packages/megalodon/lib/src/index.js new file mode 100644 index 000000000..6c0f108ce --- /dev/null +++ b/packages/megalodon/lib/src/index.js @@ -0,0 +1,45 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Converter = exports.Misskey = exports.FilterContext = exports.NotificationType = exports.detector = exports.isCancel = exports.RequestCanceledError = exports.OAuth = void 0; +var oauth_1 = __importDefault(require("./oauth")); +exports.OAuth = oauth_1.default; +var cancel_1 = require("./cancel"); +Object.defineProperty(exports, "isCancel", { enumerable: true, get: function () { return cancel_1.isCancel; } }); +Object.defineProperty(exports, "RequestCanceledError", { enumerable: true, get: function () { return cancel_1.RequestCanceledError; } }); +var megalodon_1 = __importStar(require("./megalodon")); +Object.defineProperty(exports, "detector", { enumerable: true, get: function () { return megalodon_1.detector; } }); +var misskey_1 = __importDefault(require("./misskey")); +exports.Misskey = misskey_1.default; +var notification_1 = __importDefault(require("./notification")); +exports.NotificationType = notification_1.default; +var filter_context_1 = __importDefault(require("./filter_context")); +exports.FilterContext = filter_context_1.default; +var converter_1 = __importDefault(require("./converter")); +exports.Converter = converter_1.default; +exports.default = megalodon_1.default; diff --git a/packages/megalodon/lib/src/mastodon.d.ts b/packages/megalodon/lib/src/mastodon.d.ts new file mode 100644 index 000000000..9191f0add --- /dev/null +++ b/packages/megalodon/lib/src/mastodon.d.ts @@ -0,0 +1,374 @@ +import MastodonAPI from './mastodon/api_client'; +import WebSocket from './mastodon/web_socket'; +import { MegalodonInterface } from './megalodon'; +import Response from './response'; +import Entity from './entity'; +import { ProxyConfig } from './proxy_config'; +import OAuth from './oauth'; +export default class Mastodon implements MegalodonInterface { + client: MastodonAPI.Interface; + baseUrl: string; + constructor(baseUrl: string, accessToken?: string | null, userAgent?: string | null, proxyConfig?: ProxyConfig | false); + cancel(): void; + registerApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + createApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + generateAuthUrl(clientId: string, clientSecret: string, options: Partial<{ + scope: Array; + redirect_uri: string; + }>): Promise; + verifyAppCredentials(): Promise>; + fetchAccessToken(client_id: string | null, client_secret: string, code: string, redirect_uri?: string): Promise; + refreshToken(client_id: string, client_secret: string, refresh_token: string): Promise; + revokeToken(client_id: string, client_secret: string, token: string): Promise>; + registerAccount(username: string, email: string, password: string, agreement: boolean, locale: string, reason?: string | null): Promise>; + verifyAccountCredentials(): Promise>; + updateCredentials(options?: { + discoverable?: boolean; + bot?: boolean; + display_name?: string; + note?: string; + avatar?: string; + header?: string; + locked?: boolean; + source?: { + privacy?: string; + sensitive?: boolean; + language?: string; + }; + fields_attributes?: Array<{ + name: string; + value: string; + }>; + }): Promise>; + getAccount(id: string): Promise>; + getAccountStatuses(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + pinned?: boolean; + exclude_replies?: boolean; + exclude_reblogs?: boolean; + only_media: boolean; + }): Promise>>; + subscribeAccount(id: string): Promise>; + unsubscribeAccount(id: string): Promise>; + getAccountFavourites(_id: string, _options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountFollowers(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + get_all?: boolean; + sleep_ms?: number; + }): Promise>>; + getAccountFollowing(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + get_all?: boolean; + sleep_ms?: number; + }): Promise>>; + private urlToAccounts; + getAccountLists(id: string): Promise>>; + getIdentityProof(id: string): Promise>>; + followAccount(id: string, options?: { + reblog?: boolean; + }): Promise>; + unfollowAccount(id: string): Promise>; + blockAccount(id: string): Promise>; + unblockAccount(id: string): Promise>; + muteAccount(id: string, notifications?: boolean): Promise>; + unmuteAccount(id: string): Promise>; + pinAccount(id: string): Promise>; + unpinAccount(id: string): Promise>; + getRelationship(id: string): Promise>; + getRelationships(ids: Array): Promise>>; + searchAccount(q: string, options?: { + following?: boolean; + resolve?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getBookmarks(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getFavourites(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getMutes(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getDomainBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + blockDomain(domain: string): Promise>; + unblockDomain(domain: string): Promise>; + getFilters(): Promise>>; + getFilter(id: string): Promise>; + createFilter(phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + updateFilter(id: string, phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + deleteFilter(id: string): Promise>; + report(account_id: string, comment: string, options?: { + status_ids?: Array; + forward?: boolean; + }): Promise>; + getFollowRequests(limit?: number): Promise>>; + acceptFollowRequest(id: string): Promise>; + rejectFollowRequest(id: string): Promise>; + getEndorsements(options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getFeaturedTags(): Promise>>; + getAccountFeaturedTags(id: string): Promise>>; + createFeaturedTag(name: string): Promise>; + deleteFeaturedTag(id: string): Promise>; + getSuggestedTags(): Promise>>; + getPreferences(): Promise>; + getSuggestions(limit?: number): Promise>>; + getTag(id: string): Promise>; + followTag(id: string): Promise>; + unfollowTag(id: string): Promise>; + postStatus(status: string, options: { + media_ids?: Array; + poll?: { + options: Array; + expires_in: number; + multiple?: boolean; + hide_totals?: boolean; + }; + in_reply_to_id?: string; + sensitive?: boolean; + spoiler_text?: string; + visibility?: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at?: string; + language?: string; + quote_id?: string; + }): Promise>; + getStatus(id: string): Promise>; + editStatus(id: string, options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array; + poll?: { + options?: Array; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }): Promise>; + deleteStatus(id: string): Promise>; + getStatusContext(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>; + getStatusRebloggedBy(id: string): Promise>>; + getStatusFavouritedBy(id: string): Promise>>; + favouriteStatus(id: string): Promise>; + unfavouriteStatus(id: string): Promise>; + reblogStatus(id: string): Promise>; + unreblogStatus(id: string): Promise>; + bookmarkStatus(id: string): Promise>; + unbookmarkStatus(id: string): Promise>; + muteStatus(id: string): Promise>; + unmuteStatus(id: string): Promise>; + pinStatus(id: string): Promise>; + unpinStatus(id: string): Promise>; + uploadMedia(file: any, options?: { + description?: string; + focus?: string; + }): Promise>; + getMedia(id: string): Promise>; + updateMedia(id: string, options?: { + file?: any; + description?: string; + focus?: string; + }): Promise>; + getPoll(id: string): Promise>; + votePoll(id: string, choices: Array): Promise>; + getScheduledStatuses(options?: { + limit?: number | null; + max_id?: string | null; + since_id?: string | null; + min_id?: string | null; + }): Promise>>; + getScheduledStatus(id: string): Promise>; + scheduleStatus(id: string, scheduled_at?: string | null): Promise>; + cancelScheduledStatus(id: string): Promise>; + getPublicTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getLocalTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getTagTimeline(hashtag: string, options?: { + local?: boolean; + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getHomeTimeline(options?: { + local?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getListTimeline(list_id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getConversationTimeline(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + deleteConversation(id: string): Promise>; + readConversation(id: string): Promise>; + getLists(): Promise>>; + getList(id: string): Promise>; + createList(title: string): Promise>; + updateList(id: string, title: string): Promise>; + deleteList(id: string): Promise>; + getAccountsInList(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + addAccountsToList(id: string, account_ids: Array): Promise>; + deleteAccountsFromList(id: string, account_ids: Array): Promise>; + getMarkers(timeline: Array): Promise>; + saveMarkers(options?: { + home?: { + last_read_id: string; + }; + notifications?: { + last_read_id: string; + }; + }): Promise>; + getNotifications(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + exclude_types?: Array; + account_id?: string; + }): Promise>>; + getNotification(id: string): Promise>; + dismissNotifications(): Promise>; + dismissNotification(id: string): Promise>; + readNotifications(_options: { + id?: string; + max_id?: string; + }): Promise>>; + subscribePushNotification(subscription: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }, data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + getPushSubscription(): Promise>; + updatePushSubscription(data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + deletePushSubscription(): Promise>; + search(q: string, type: 'accounts' | 'hashtags' | 'statuses', options?: { + limit?: number; + max_id?: string; + min_id?: string; + resolve?: boolean; + offset?: number; + following?: boolean; + account_id?: string; + exclude_unreviewed?: boolean; + }): Promise>; + getInstance(): Promise>; + getInstancePeers(): Promise>>; + getInstanceActivity(): Promise>>; + getInstanceTrends(limit?: number | null): Promise>>; + getInstanceDirectory(options?: { + limit?: number; + offset?: number; + order?: 'active' | 'new'; + local?: boolean; + }): Promise>>; + getInstanceCustomEmojis(): Promise>>; + getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>>; + dismissInstanceAnnouncement(id: string): Promise>; + createEmojiReaction(_id: string, _emoji: string): Promise>; + deleteEmojiReaction(_id: string, _emoji: string): Promise>; + getEmojiReactions(_id: string): Promise>>; + getEmojiReaction(_id: string, _emoji: string): Promise>; + userSocket(): WebSocket; + publicSocket(): WebSocket; + localSocket(): WebSocket; + tagSocket(tag: string): WebSocket; + listSocket(list_id: string): WebSocket; + directSocket(): WebSocket; +} diff --git a/packages/megalodon/lib/src/mastodon.js b/packages/megalodon/lib/src/mastodon.js new file mode 100644 index 000000000..6ae7ed51c --- /dev/null +++ b/packages/megalodon/lib/src/mastodon.js @@ -0,0 +1,2367 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var oauth_1 = require("oauth"); +var form_data_1 = __importDefault(require("form-data")); +var parse_link_header_1 = __importDefault(require("parse-link-header")); +var api_client_1 = __importDefault(require("./mastodon/api_client")); +var megalodon_1 = require("./megalodon"); +var default_1 = require("./default"); +var oauth_2 = __importDefault(require("./oauth")); +var Mastodon = (function () { + function Mastodon(baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + var token = ''; + if (accessToken) { + token = accessToken; + } + var agent = default_1.DEFAULT_UA; + if (userAgent) { + agent = userAgent; + } + this.client = new api_client_1.default.Client(baseUrl, token, agent, proxyConfig); + this.baseUrl = baseUrl; + } + Mastodon.prototype.cancel = function () { + return this.client.cancel(); + }; + Mastodon.prototype.registerApp = function (client_name, options) { + return __awaiter(this, void 0, void 0, function () { + var scopes; + var _this = this; + return __generator(this, function (_a) { + scopes = options.scopes || default_1.DEFAULT_SCOPE; + return [2, this.createApp(client_name, options).then(function (appData) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.generateAuthUrl(appData.client_id, appData.client_secret, { + scope: scopes, + redirect_uri: appData.redirect_uri + }).then(function (url) { + appData.url = url; + return appData; + })]; + }); + }); })]; + }); + }); + }; + Mastodon.prototype.createApp = function (client_name, options) { + return __awaiter(this, void 0, void 0, function () { + var scopes, redirect_uris, params; + return __generator(this, function (_a) { + scopes = options.scopes || default_1.DEFAULT_SCOPE; + redirect_uris = options.redirect_uris || default_1.NO_REDIRECT; + params = { + client_name: client_name, + redirect_uris: redirect_uris, + scopes: scopes.join(' ') + }; + if (options.website) + params.website = options.website; + return [2, this.client + .post('/api/v1/apps', params) + .then(function (res) { return oauth_2.default.AppData.from(res.data); })]; + }); + }); + }; + Mastodon.prototype.generateAuthUrl = function (clientId, clientSecret, options) { + var _this = this; + var scope = options.scope || default_1.DEFAULT_SCOPE; + var redirect_uri = options.redirect_uri || default_1.NO_REDIRECT; + return new Promise(function (resolve) { + var oauth = new oauth_1.OAuth2(clientId, clientSecret, _this.baseUrl, undefined, '/oauth/token'); + var url = oauth.getAuthorizeUrl({ + redirect_uri: redirect_uri, + response_type: 'code', + client_id: clientId, + scope: scope.join(' ') + }); + resolve(url); + }); + }; + Mastodon.prototype.verifyAppCredentials = function () { + return this.client.get('/api/v1/apps/verify_credentials'); + }; + Mastodon.prototype.fetchAccessToken = function (client_id, client_secret, code, redirect_uri) { + if (redirect_uri === void 0) { redirect_uri = default_1.NO_REDIRECT; } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (!client_id) { + throw new Error('client_id is required'); + } + return [2, this.client + .post('/oauth/token', { + client_id: client_id, + client_secret: client_secret, + code: code, + redirect_uri: redirect_uri, + grant_type: 'authorization_code' + }) + .then(function (res) { return oauth_2.default.TokenData.from(res.data); })]; + }); + }); + }; + Mastodon.prototype.refreshToken = function (client_id, client_secret, refresh_token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/oauth/token', { + client_id: client_id, + client_secret: client_secret, + refresh_token: refresh_token, + grant_type: 'refresh_token' + }) + .then(function (res) { return oauth_2.default.TokenData.from(res.data); })]; + }); + }); + }; + Mastodon.prototype.revokeToken = function (client_id, client_secret, token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/oauth/revoke', { + client_id: client_id, + client_secret: client_secret, + token: token + })]; + }); + }); + }; + Mastodon.prototype.registerAccount = function (username, email, password, agreement, locale, reason) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + username: username, + email: email, + password: password, + agreement: agreement, + locale: locale + }; + if (reason) { + params = Object.assign(params, { + reason: reason + }); + } + return [2, this.client.post('/api/v1/accounts', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.token(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.verifyAccountCredentials = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/accounts/verify_credentials').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.updateCredentials = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.patch('/api/v1/accounts/update_credentials', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getAccountStatuses = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/accounts/".concat(id, "/statuses"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.subscribeAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + notify: true + }; + return [2, this.client.post("/api/v1/accounts/".concat(id, "/follow"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unsubscribeAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + notify: false + }; + return [2, this.client.post("/api/v1/accounts/".concat(id, "/follow"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getAccountFavourites = function (_id, _options) { + return new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('mastodon does not support'); + reject(err); + }); + }; + Mastodon.prototype.getAccountFollowers = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.urlToAccounts("/api/v1/accounts/".concat(id, "/followers"), params, (options === null || options === void 0 ? void 0 : options.get_all) || false, (options === null || options === void 0 ? void 0 : options.sleep_ms) || 0)]; + }); + }); + }; + Mastodon.prototype.getAccountFollowing = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.urlToAccounts("/api/v1/accounts/".concat(id, "/following"), params, (options === null || options === void 0 ? void 0 : options.get_all) || false, (options === null || options === void 0 ? void 0 : options.sleep_ms) || 0)]; + }); + }); + }; + Mastodon.prototype.urlToAccounts = function (url, params, get_all, sleep_ms) { + return __awaiter(this, void 0, void 0, function () { + var res, parsed, nextRes; + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4, this.client.get(url, params)]; + case 1: + res = _b.sent(); + res.data = res.data.map(function (a) { return api_client_1.default.Converter.account(a); }); + if (!(get_all && res.headers.link)) return [3, 6]; + parsed = (0, parse_link_header_1.default)(res.headers.link); + _b.label = 2; + case 2: + if (!(parsed === null || parsed === void 0 ? void 0 : parsed.next)) return [3, 6]; + return [4, this.client.get(parsed === null || parsed === void 0 ? void 0 : parsed.next.url, undefined, undefined, true)]; + case 3: + nextRes = _b.sent(); + (_a = res.data).push.apply(_a, __spreadArray([], __read(nextRes.data.map(function (a) { return api_client_1.default.Converter.account(a); })), false)); + parsed = (0, parse_link_header_1.default)(nextRes.headers.link); + if (!sleep_ms) return [3, 5]; + return [4, new Promise(function (res) { return setTimeout(res, sleep_ms); })]; + case 4: + _b.sent(); + _b.label = 5; + case 5: return [3, 2]; + case 6: return [2, res]; + } + }); + }); + }; + Mastodon.prototype.getAccountLists = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/lists")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (l) { return api_client_1.default.Converter.list(l); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getIdentityProof = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/identity_proofs")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (i) { return api_client_1.default.Converter.identity_proof(i); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.followAccount = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.reblog !== undefined) { + params = Object.assign(params, { + reblog: options.reblog + }); + } + } + return [2, this.client.post("/api/v1/accounts/".concat(id, "/follow"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unfollowAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unfollow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.blockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/block")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unblockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unblock")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.muteAccount = function (id, notifications) { + if (notifications === void 0) { notifications = true; } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post("/api/v1/accounts/".concat(id, "/mute"), { + notifications: notifications + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unmuteAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unmute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.pinAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/pin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unpinAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unpin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getRelationship = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .get('/api/v1/accounts/relationships', { + id: [id] + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data[0]) + }); + })]; + }); + }); + }; + Mastodon.prototype.getRelationships = function (ids) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .get('/api/v1/accounts/relationships', { + id: ids + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (r) { return api_client_1.default.Converter.relationship(r); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.searchAccount = function (q, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/accounts/search', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getBookmarks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/bookmarks', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getFavourites = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/favourites', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getMutes = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/mutes', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getBlocks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/blocks', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getDomainBlocks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/domain_blocks', params)]; + }); + }); + }; + Mastodon.prototype.blockDomain = function (domain) { + return this.client.post('/api/v1/domain_blocks', { + domain: domain + }); + }; + Mastodon.prototype.unblockDomain = function (domain) { + return this.client.del('/api/v1/domain_blocks', { + domain: domain + }); + }; + Mastodon.prototype.getFilters = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/filters').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.filter(f); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getFilter = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/filters/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.createFilter = function (phrase, context, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.post('/api/v1/filters', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.updateFilter = function (id, phrase, context, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.put("/api/v1/filters/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.deleteFilter = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.del("/api/v1/filters/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.report = function (account_id, comment, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + account_id: account_id, + comment: comment + }; + if (options) { + if (options.status_ids) { + params = Object.assign(params, { + status_ids: options.status_ids + }); + } + if (options.forward !== undefined) { + params = Object.assign(params, { + forward: options.forward + }); + } + } + return [2, this.client.post('/api/v1/reports', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.report(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getFollowRequests = function (limit) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (limit) { + return [2, this.client + .get('/api/v1/follow_requests', { + limit: limit + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + else { + return [2, this.client.get('/api/v1/follow_requests').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + return [2]; + }); + }); + }; + Mastodon.prototype.acceptFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/follow_requests/".concat(id, "/authorize")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.rejectFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/follow_requests/".concat(id, "/reject")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getEndorsements = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/endorsements', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getFeaturedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/featured_tags').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.featured_tag(f); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getAccountFeaturedTags = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/featured_tags")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.featured_tag(f); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.createFeaturedTag = function (name) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/v1/featured_tags', { + name: name + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.featured_tag(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.deleteFeaturedTag = function (id) { + return this.client.del("/api/v1/featured_tags/".concat(id)); + }; + Mastodon.prototype.getSuggestedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/featured_tags/suggestions').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (t) { return api_client_1.default.Converter.tag(t); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getPreferences = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/preferences').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.preferences(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getSuggestions = function (limit) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (limit) { + return [2, this.client + .get('/api/v1/suggestions', { + limit: limit + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + else { + return [2, this.client.get('/api/v1/suggestions').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + return [2]; + }); + }); + }; + Mastodon.prototype.getTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/tags/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.followTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/tags/".concat(id, "/follow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unfollowTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/tags/".concat(id, "/unfollow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.postStatus = function (status, options) { + return __awaiter(this, void 0, void 0, function () { + var params, pollParam; + return __generator(this, function (_a) { + params = { + status: status + }; + if (options) { + if (options.media_ids) { + params = Object.assign(params, { + media_ids: options.media_ids + }); + } + if (options.poll) { + 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: options.visibility + }); + } + if (options.scheduled_at) { + 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 + }); + } + } + return [2, this.client.post('/api/v1/statuses', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.editStatus = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params, pollParam; + return __generator(this, function (_a) { + 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) { + 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 [2, this.client.put("/api/v1/statuses/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.deleteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.del("/api/v1/statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getStatusContext = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/statuses/".concat(id, "/context"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.context(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getStatusRebloggedBy = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id, "/reblogged_by")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getStatusFavouritedBy = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id, "/favourited_by")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.favouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/favourite")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unfavouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unfavourite")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.reblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/reblog")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unreblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unreblog")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.bookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/bookmark")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unbookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unbookmark")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.muteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/mute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unmuteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unmute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.pinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/pin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.unpinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unpin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.uploadMedia = function (file, options) { + return __awaiter(this, void 0, void 0, function () { + var formData; + return __generator(this, function (_a) { + formData = new form_data_1.default(); + formData.append('file', file); + if (options) { + if (options.description) { + formData.append('description', options.description); + } + if (options.focus) { + formData.append('focus', options.focus); + } + } + return [2, this.client.postForm('/api/v2/media', formData).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.async_attachment(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getMedia = function (id) { + return __awaiter(this, void 0, void 0, function () { + var res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.get("/api/v1/media/".concat(id))]; + case 1: + res = _a.sent(); + return [2, Object.assign(res, { + data: api_client_1.default.Converter.attachment(res.data) + })]; + } + }); + }); + }; + Mastodon.prototype.updateMedia = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var formData; + return __generator(this, function (_a) { + formData = new form_data_1.default(); + 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 [2, this.client.putForm("/api/v1/media/".concat(id), formData).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.attachment(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getPoll = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/polls/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.poll(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.votePoll = function (id, choices) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post("/api/v1/polls/".concat(id, "/votes"), { + choices: choices + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.poll(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getScheduledStatuses = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/scheduled_statuses', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.scheduled_status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getScheduledStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/scheduled_statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.scheduled_status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.scheduleStatus = function (id, scheduled_at) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (scheduled_at) { + params = Object.assign(params, { + scheduled_at: scheduled_at + }); + } + return [2, this.client.put("/api/v1/scheduled_statuses/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.scheduled_status(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.cancelScheduledStatus = function (id) { + return this.client.del("/api/v1/scheduled_statuses/".concat(id)); + }; + Mastodon.prototype.getPublicTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/public', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getLocalTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/public', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getTagTimeline = function (hashtag, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/timelines/tag/".concat(hashtag), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getHomeTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/home', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getListTimeline = function (list_id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/timelines/list/".concat(list_id), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getConversationTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/conversations', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (c) { return api_client_1.default.Converter.conversation(c); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.deleteConversation = function (id) { + return this.client.del("/api/v1/conversations/".concat(id)); + }; + Mastodon.prototype.readConversation = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/conversations/".concat(id, "/read")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.conversation(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getLists = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/lists').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (l) { return api_client_1.default.Converter.list(l); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getList = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/lists/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.createList = function (title) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/v1/lists', { + title: title + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.updateList = function (id, title) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .put("/api/v1/lists/".concat(id), { + title: title + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.deleteList = function (id) { + return this.client.del("/api/v1/lists/".concat(id)); + }; + Mastodon.prototype.getAccountsInList = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/lists/".concat(id, "/accounts"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.addAccountsToList = function (id, account_ids) { + return this.client.post("/api/v1/lists/".concat(id, "/accounts"), { + account_ids: account_ids + }); + }; + Mastodon.prototype.deleteAccountsFromList = function (id, account_ids) { + return this.client.del("/api/v1/lists/".concat(id, "/accounts"), { + account_ids: account_ids + }); + }; + Mastodon.prototype.getMarkers = function (timeline) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/markers', { + timeline: timeline + })]; + }); + }); + }; + Mastodon.prototype.saveMarkers = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.home) { + params = Object.assign(params, { + home: options.home + }); + } + if (options.notifications) { + params = Object.assign(params, { + notifications: options.notifications + }); + } + } + return [2, this.client.post('/api/v1/markers', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.marker(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getNotifications = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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(function (e) { return api_client_1.default.Converter.encodeNotificationType(e); }) + }); + } + if (options.account_id) { + params = Object.assign(params, { + account_id: options.account_id + }); + } + } + return [2, this.client.get('/api/v1/notifications', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (n) { return api_client_1.default.Converter.notification(n); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getNotification = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/notifications/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.notification(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.dismissNotifications = function () { + return this.client.post('/api/v1/notifications/clear'); + }; + Mastodon.prototype.dismissNotification = function (id) { + return this.client.post("/api/v1/notifications/".concat(id, "/dismiss")); + }; + Mastodon.prototype.readNotifications = function (_options) { + return new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('mastodon does not support'); + reject(err); + }); + }; + Mastodon.prototype.subscribePushNotification = function (subscription, data) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + subscription: subscription + }; + if (data) { + params = Object.assign(params, { + data: data + }); + } + return [2, this.client.post('/api/v1/push/subscription', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getPushSubscription = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/push/subscription').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.updatePushSubscription = function (data) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (data) { + params = Object.assign(params, { + data: data + }); + } + return [2, this.client.put('/api/v1/push/subscription', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.deletePushSubscription = function () { + return this.client.del('/api/v1/push/subscription'); + }; + Mastodon.prototype.search = function (q, type, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + q: q, + type: type + }; + 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.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 [2, this.client.get('/api/v2/search', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.results(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstance = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/instance').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.instance(res.data) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstancePeers = function () { + return this.client.get('/api/v1/instance/peers'); + }; + Mastodon.prototype.getInstanceActivity = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/instance/activity').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.activity(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstanceTrends = function (limit) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (limit) { + params = Object.assign(params, { + limit: limit + }); + } + return [2, this.client.get('/api/v1/trends', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (t) { return api_client_1.default.Converter.tag(t); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstanceDirectory = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }); + } + if (options.order) { + params = Object.assign(params, { + order: options.order + }); + } + if (options.local !== undefined) { + params = Object.assign(params, { + local: options.local + }); + } + } + return [2, this.client.get('/api/v1/directory', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstanceCustomEmojis = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/custom_emojis').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (e) { return api_client_1.default.Converter.emoji(e); }) + }); + })]; + }); + }); + }; + Mastodon.prototype.getInstanceAnnouncements = function (with_dismissed) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (with_dismissed) { + params = Object.assign(params, { + with_dismissed: with_dismissed + }); + } + return [2, this.client.get('/api/v1/announcements', params).then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (t) { return api_client_1.default.Converter.announcement(t); }) })); })]; + }); + }); + }; + Mastodon.prototype.dismissInstanceAnnouncement = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/announcements/".concat(id, "/dismiss"))]; + }); + }); + }; + Mastodon.prototype.createEmojiReaction = function (_id, _emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Mastodon.prototype.deleteEmojiReaction = function (_id, _emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Mastodon.prototype.getEmojiReactions = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Mastodon.prototype.getEmojiReaction = function (_id, _emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Mastodon.prototype.userSocket = function () { + return this.client.socket('/api/v1/streaming', 'user'); + }; + Mastodon.prototype.publicSocket = function () { + return this.client.socket('/api/v1/streaming', 'public'); + }; + Mastodon.prototype.localSocket = function () { + return this.client.socket('/api/v1/streaming', 'public:local'); + }; + Mastodon.prototype.tagSocket = function (tag) { + return this.client.socket('/api/v1/streaming', 'hashtag', "tag=".concat(tag)); + }; + Mastodon.prototype.listSocket = function (list_id) { + return this.client.socket('/api/v1/streaming', 'list', "list=".concat(list_id)); + }; + Mastodon.prototype.directSocket = function () { + return this.client.socket('/api/v1/streaming', 'direct'); + }; + return Mastodon; +}()); +exports.default = Mastodon; diff --git a/packages/megalodon/lib/src/mastodon/api_client.d.ts b/packages/megalodon/lib/src/mastodon/api_client.d.ts new file mode 100644 index 000000000..b5169744d --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/api_client.d.ts @@ -0,0 +1,152 @@ +import WebSocket from './web_socket'; +import Response from '../response'; +import { ProxyConfig } from '../proxy_config'; +import MastodonEntity from './entity'; +import MegalodonEntity from '../entity'; +import NotificationType from '../notification'; +declare namespace MastodonAPI { + interface Interface { + get(path: string, params?: any, headers?: { + [key: string]: string; + }, pathIsFullyQualified?: boolean): Promise>; + put(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + putForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + patch(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + patchForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + post(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + postForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + del(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(path: string, stream: string, params?: string): WebSocket; + } + class Client implements Interface { + static DEFAULT_SCOPE: string[]; + static DEFAULT_URL: string; + static NO_REDIRECT: string; + private accessToken; + private baseUrl; + private userAgent; + private abortController; + private proxyConfig; + constructor(baseUrl: string, accessToken?: string | null, userAgent?: string, proxyConfig?: ProxyConfig | false); + get(path: string, params?: {}, headers?: { + [key: string]: string; + }, pathIsFullyQualified?: boolean): Promise>; + put(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + putForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + patch(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + patchForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + post(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + postForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + del(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(path: string, stream: string, params?: string): WebSocket; + } + namespace Entity { + type Account = MastodonEntity.Account; + type Activity = MastodonEntity.Activity; + type Announcement = MastodonEntity.Announcement; + type Application = MastodonEntity.Application; + type AsyncAttachment = MegalodonEntity.AsyncAttachment; + type Attachment = MastodonEntity.Attachment; + type Card = MastodonEntity.Card; + type Context = MastodonEntity.Context; + type Conversation = MastodonEntity.Conversation; + type Emoji = MastodonEntity.Emoji; + type FeaturedTag = MastodonEntity.FeaturedTag; + type Field = MastodonEntity.Field; + type Filter = MastodonEntity.Filter; + type History = MastodonEntity.History; + type IdentityProof = MastodonEntity.IdentityProof; + type Instance = MastodonEntity.Instance; + type List = MastodonEntity.List; + type Marker = MastodonEntity.Marker; + type Mention = MastodonEntity.Mention; + type Notification = MastodonEntity.Notification; + type Poll = MastodonEntity.Poll; + type PollOption = MastodonEntity.PollOption; + type Preferences = MastodonEntity.Preferences; + type PushSubscription = MastodonEntity.PushSubscription; + type Relationship = MastodonEntity.Relationship; + type Reaction = MastodonEntity.Reaction; + type Report = MastodonEntity.Report; + type Results = MastodonEntity.Results; + type ScheduledStatus = MastodonEntity.ScheduledStatus; + type Source = MastodonEntity.Source; + type Stats = MastodonEntity.Stats; + type Status = MastodonEntity.Status; + type StatusParams = MastodonEntity.StatusParams; + type Tag = MastodonEntity.Tag; + type Token = MastodonEntity.Token; + type URLs = MastodonEntity.URLs; + } + namespace Converter { + const encodeNotificationType: (t: MegalodonEntity.NotificationType) => MastodonEntity.NotificationType; + const decodeNotificationType: (t: MastodonEntity.NotificationType) => MegalodonEntity.NotificationType; + const account: (a: Entity.Account) => MegalodonEntity.Account; + const activity: (a: Entity.Activity) => MegalodonEntity.Activity; + const announcement: (a: Entity.Announcement) => MegalodonEntity.Announcement; + const application: (a: Entity.Application) => MegalodonEntity.Application; + const attachment: (a: Entity.Attachment) => MegalodonEntity.Attachment; + const async_attachment: (a: Entity.AsyncAttachment) => MegalodonEntity.Attachment | MegalodonEntity.AsyncAttachment; + const card: (c: Entity.Card) => MegalodonEntity.Card; + const context: (c: Entity.Context) => MegalodonEntity.Context; + const conversation: (c: Entity.Conversation) => MegalodonEntity.Conversation; + const emoji: (e: Entity.Emoji) => MegalodonEntity.Emoji; + const featured_tag: (e: Entity.FeaturedTag) => MegalodonEntity.FeaturedTag; + const field: (f: Entity.Field) => MegalodonEntity.Field; + const filter: (f: Entity.Filter) => MegalodonEntity.Filter; + const history: (h: Entity.History) => MegalodonEntity.History; + const identity_proof: (i: Entity.IdentityProof) => MegalodonEntity.IdentityProof; + const instance: (i: Entity.Instance) => MegalodonEntity.Instance; + const list: (l: Entity.List) => MegalodonEntity.List; + const marker: (m: Entity.Marker) => MegalodonEntity.Marker; + const mention: (m: Entity.Mention) => MegalodonEntity.Mention; + const notification: (n: Entity.Notification) => MegalodonEntity.Notification; + const poll: (p: Entity.Poll) => MegalodonEntity.Poll; + const poll_option: (p: Entity.PollOption) => MegalodonEntity.PollOption; + const preferences: (p: Entity.Preferences) => MegalodonEntity.Preferences; + const push_subscription: (p: Entity.PushSubscription) => MegalodonEntity.PushSubscription; + const relationship: (r: Entity.Relationship) => MegalodonEntity.Relationship; + const reaction: (r: Entity.Reaction) => MegalodonEntity.Reaction; + const report: (r: Entity.Report) => MegalodonEntity.Report; + const results: (r: Entity.Results) => MegalodonEntity.Results; + const scheduled_status: (s: Entity.ScheduledStatus) => MegalodonEntity.ScheduledStatus; + const source: (s: Entity.Source) => MegalodonEntity.Source; + const stats: (s: Entity.Stats) => MegalodonEntity.Stats; + const status: (s: Entity.Status) => MegalodonEntity.Status; + const status_params: (s: Entity.StatusParams) => MegalodonEntity.StatusParams; + const tag: (t: Entity.Tag) => MegalodonEntity.Tag; + const token: (t: Entity.Token) => MegalodonEntity.Token; + const urls: (u: Entity.URLs) => MegalodonEntity.URLs; + } +} +export default MastodonAPI; diff --git a/packages/megalodon/lib/src/mastodon/api_client.js b/packages/megalodon/lib/src/mastodon/api_client.js new file mode 100644 index 000000000..8ff48c404 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/api_client.js @@ -0,0 +1,614 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var axios_1 = __importDefault(require("axios")); +var object_assign_deep_1 = __importDefault(require("object-assign-deep")); +var web_socket_1 = __importDefault(require("./web_socket")); +var cancel_1 = require("../cancel"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var default_1 = require("../default"); +var notification_1 = __importDefault(require("../notification")); +var notification_2 = __importDefault(require("./notification")); +var MastodonAPI; +(function (MastodonAPI) { + var Client = (function () { + function Client(baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + this.proxyConfig = false; + this.accessToken = accessToken; + this.baseUrl = baseUrl; + this.userAgent = userAgent; + this.proxyConfig = proxyConfig; + this.abortController = new AbortController(); + axios_1.default.defaults.signal = this.abortController.signal; + } + Client.prototype.get = function (path, params, headers, pathIsFullyQualified) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + if (pathIsFullyQualified === void 0) { pathIsFullyQualified = false; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + params: params, + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .get((pathIsFullyQualified ? '' : this.baseUrl) + path, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.put = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .put(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.putForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .putForm(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.patch = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .patch(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.patchForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .patchForm(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.post = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default.post(this.baseUrl + path, params, options).then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.postForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default.postForm(this.baseUrl + path, params, options).then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.del = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + data: params, + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .delete(this.baseUrl + path, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .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 (path, stream, params) { + if (!this.accessToken) { + throw new Error('accessToken is required'); + } + var url = this.baseUrl + path; + var streaming = new web_socket_1.default(url, stream, params, this.accessToken, this.userAgent, this.proxyConfig); + process.nextTick(function () { + streaming.start(); + }); + return streaming; + }; + Client.DEFAULT_SCOPE = default_1.DEFAULT_SCOPE; + Client.DEFAULT_URL = 'https://mastodon.social'; + Client.NO_REDIRECT = default_1.NO_REDIRECT; + return Client; + }()); + MastodonAPI.Client = Client; + var Converter; + (function (Converter) { + Converter.encodeNotificationType = function (t) { + switch (t) { + case notification_1.default.Follow: + return notification_2.default.Follow; + case notification_1.default.Favourite: + return notification_2.default.Favourite; + case notification_1.default.Reblog: + return notification_2.default.Reblog; + case notification_1.default.Mention: + return notification_2.default.Mention; + case notification_1.default.FollowRequest: + return notification_2.default.FollowRequest; + case notification_1.default.Status: + return notification_2.default.Status; + case notification_1.default.PollExpired: + return notification_2.default.Poll; + default: + return t; + } + }; + Converter.decodeNotificationType = function (t) { + switch (t) { + case notification_2.default.Follow: + return notification_1.default.Follow; + case notification_2.default.Favourite: + return notification_1.default.Favourite; + case notification_2.default.Mention: + return notification_1.default.Mention; + case notification_2.default.Reblog: + return notification_1.default.Reblog; + case notification_2.default.FollowRequest: + return notification_1.default.FollowRequest; + case notification_2.default.Status: + return notification_1.default.Status; + case notification_2.default.Poll: + return notification_1.default.PollExpired; + default: + return t; + } + }; + Converter.account = function (a) { return a; }; + Converter.activity = function (a) { return a; }; + Converter.announcement = function (a) { return (__assign(__assign({}, a), { reactions: a.reactions.map(function (r) { return Converter.reaction(r); }) })); }; + Converter.application = function (a) { return a; }; + Converter.attachment = function (a) { return a; }; + Converter.async_attachment = function (a) { + if (a.url) { + return { + id: a.id, + type: a.type, + url: a.url, + remote_url: a.remote_url, + preview_url: a.preview_url, + text_url: a.text_url, + meta: a.meta, + description: a.description, + blurhash: a.blurhash + }; + } + else { + return a; + } + }; + Converter.card = function (c) { return c; }; + Converter.context = function (c) { return ({ + ancestors: c.ancestors.map(function (a) { return Converter.status(a); }), + descendants: c.descendants.map(function (d) { return Converter.status(d); }) + }); }; + Converter.conversation = function (c) { return ({ + id: c.id, + accounts: c.accounts.map(function (a) { return Converter.account(a); }), + last_status: c.last_status ? Converter.status(c.last_status) : null, + unread: c.unread + }); }; + Converter.emoji = function (e) { return e; }; + Converter.featured_tag = function (e) { return e; }; + Converter.field = function (f) { return f; }; + Converter.filter = function (f) { return f; }; + Converter.history = function (h) { return h; }; + Converter.identity_proof = function (i) { return i; }; + Converter.instance = function (i) { return i; }; + Converter.list = function (l) { return l; }; + Converter.marker = function (m) { return m; }; + Converter.mention = function (m) { return m; }; + Converter.notification = function (n) { + if (n.status) { + return { + account: Converter.account(n.account), + created_at: n.created_at, + id: n.id, + status: Converter.status(n.status), + type: Converter.decodeNotificationType(n.type) + }; + } + else { + return { + account: Converter.account(n.account), + created_at: n.created_at, + id: n.id, + type: Converter.decodeNotificationType(n.type) + }; + } + }; + Converter.poll = function (p) { return p; }; + Converter.poll_option = function (p) { return p; }; + Converter.preferences = function (p) { return p; }; + Converter.push_subscription = function (p) { return p; }; + Converter.relationship = function (r) { return r; }; + Converter.reaction = function (r) { + var _a; + return ({ + count: r.count, + me: (_a = r.me) !== null && _a !== void 0 ? _a : false, + name: r.name, + url: r.url, + }); + }; + Converter.report = function (r) { return r; }; + Converter.results = function (r) { return ({ + accounts: r.accounts.map(function (a) { return Converter.account(a); }), + statuses: r.statuses.map(function (s) { return Converter.status(s); }), + hashtags: r.hashtags.map(function (h) { return Converter.tag(h); }) + }); }; + Converter.scheduled_status = function (s) { return s; }; + Converter.source = function (s) { return s; }; + Converter.stats = function (s) { return s; }; + Converter.status = function (s) { return ({ + id: s.id, + uri: s.uri, + url: s.url, + account: Converter.account(s.account), + in_reply_to_id: s.in_reply_to_id, + in_reply_to_account_id: s.in_reply_to_account_id, + reblog: s.reblog ? Converter.status(s.reblog) : s.quote ? Converter.status(s.quote) : null, + content: s.content, + plain_content: null, + created_at: s.created_at, + emojis: s.emojis.map(function (e) { return Converter.emoji(e); }), + replies_count: s.replies_count, + reblogs_count: s.reblogs_count, + favourites_count: s.favourites_count, + reblogged: s.reblogged, + favourited: s.favourited, + muted: s.muted, + sensitive: s.sensitive, + spoiler_text: s.spoiler_text, + visibility: s.visibility, + media_attachments: s.media_attachments.map(function (m) { return Converter.attachment(m); }), + mentions: s.mentions.map(function (m) { return Converter.mention(m); }), + tags: s.tags.map(function (t) { return Converter.tag(t); }), + card: s.card ? Converter.card(s.card) : null, + poll: s.poll ? Converter.poll(s.poll) : null, + application: s.application ? Converter.application(s.application) : null, + language: s.language, + pinned: s.pinned, + emoji_reactions: [], + bookmarked: s.bookmarked ? s.bookmarked : false, + quote: s.quote ? Converter.status(s.quote) : null + }); }; + Converter.status_params = function (s) { return s; }; + Converter.tag = function (t) { return t; }; + Converter.token = function (t) { return t; }; + Converter.urls = function (u) { return u; }; + })(Converter = MastodonAPI.Converter || (MastodonAPI.Converter = {})); +})(MastodonAPI || (MastodonAPI = {})); +exports.default = MastodonAPI; diff --git a/packages/megalodon/lib/src/mastodon/entities/account.d.ts b/packages/megalodon/lib/src/mastodon/entities/account.d.ts new file mode 100644 index 000000000..02b3d5b8c --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/account.d.ts @@ -0,0 +1,27 @@ +/// +/// +/// +declare namespace MastodonEntity { + type Account = { + id: string; + username: string; + acct: string; + display_name: string; + locked: boolean; + created_at: string; + followers_count: number; + following_count: number; + statuses_count: number; + note: string; + url: string; + avatar: string; + avatar_static: string; + header: string; + header_static: string; + emojis: Array; + moved: Account | null; + fields: Array; + bot: boolean | null; + source?: Source; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/account.js b/packages/megalodon/lib/src/mastodon/entities/account.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/account.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/activity.d.ts b/packages/megalodon/lib/src/mastodon/entities/activity.d.ts new file mode 100644 index 000000000..26d3c4338 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/activity.d.ts @@ -0,0 +1,8 @@ +declare namespace MastodonEntity { + type Activity = { + week: string; + statuses: string; + logins: string; + registrations: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/activity.js b/packages/megalodon/lib/src/mastodon/entities/activity.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/activity.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/announcement.d.ts b/packages/megalodon/lib/src/mastodon/entities/announcement.d.ts new file mode 100644 index 000000000..bd5acb750 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/announcement.d.ts @@ -0,0 +1,37 @@ +/// +/// +declare namespace MastodonEntity { + type Announcement = { + id: string; + content: string; + starts_at: string | null; + ends_at: string | null; + published: boolean; + all_day: boolean; + published_at: string; + updated_at: string; + read?: boolean; + mentions: Array; + statuses: Array; + tags: Array; + emojis: Array; + reactions: Array; + }; + type AnnouncementAccount = { + id: string; + username: string; + url: string; + acct: string; + }; + type AnnouncementStatus = { + id: string; + url: string; + }; + type Reaction = { + name: string; + count: number; + me?: boolean; + url?: string; + static_url?: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/announcement.js b/packages/megalodon/lib/src/mastodon/entities/announcement.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/announcement.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/application.d.ts b/packages/megalodon/lib/src/mastodon/entities/application.d.ts new file mode 100644 index 000000000..88943865b --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/application.d.ts @@ -0,0 +1,7 @@ +declare namespace MastodonEntity { + type Application = { + name: string; + website?: string | null; + vapid_key?: string | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/application.js b/packages/megalodon/lib/src/mastodon/entities/application.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/application.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/async_attachment.d.ts b/packages/megalodon/lib/src/mastodon/entities/async_attachment.d.ts new file mode 100644 index 000000000..59d8daff2 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/async_attachment.d.ts @@ -0,0 +1,14 @@ +/// +declare namespace MastodonEntity { + type AsyncAttachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string | null; + remote_url: string | null; + preview_url: string; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/async_attachment.js b/packages/megalodon/lib/src/mastodon/entities/async_attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/async_attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/attachment.d.ts b/packages/megalodon/lib/src/mastodon/entities/attachment.d.ts new file mode 100644 index 000000000..bb0b8d6dc --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/attachment.d.ts @@ -0,0 +1,41 @@ +declare namespace MastodonEntity { + type Sub = { + width?: number; + height?: number; + size?: string; + aspect?: number; + frame_rate?: string; + duration?: number; + bitrate?: number; + }; + type Focus = { + x: number; + y: number; + }; + type Meta = { + original?: Sub; + small?: Sub; + focus?: Focus; + length?: string; + duration?: number; + fps?: number; + size?: string; + width?: number; + height?: number; + aspect?: number; + audio_encode?: string; + audio_bitrate?: string; + audio_channel?: string; + }; + type Attachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string; + remote_url: string | null; + preview_url: string | null; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/attachment.js b/packages/megalodon/lib/src/mastodon/entities/attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/card.d.ts b/packages/megalodon/lib/src/mastodon/entities/card.d.ts new file mode 100644 index 000000000..927ed7d6c --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/card.d.ts @@ -0,0 +1,16 @@ +declare namespace MastodonEntity { + type Card = { + url: string; + title: string; + description: string; + type: 'link' | 'photo' | 'video' | 'rich'; + image?: string; + author_name?: string; + author_url?: string; + provider_name?: string; + provider_url?: string; + html?: string; + width?: number; + height?: number; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/card.js b/packages/megalodon/lib/src/mastodon/entities/card.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/card.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/context.d.ts b/packages/megalodon/lib/src/mastodon/entities/context.d.ts new file mode 100644 index 000000000..91e15feb2 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/context.d.ts @@ -0,0 +1,7 @@ +/// +declare namespace MastodonEntity { + type Context = { + ancestors: Array; + descendants: Array; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/context.js b/packages/megalodon/lib/src/mastodon/entities/context.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/context.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/conversation.d.ts b/packages/megalodon/lib/src/mastodon/entities/conversation.d.ts new file mode 100644 index 000000000..ec3253179 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/conversation.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace MastodonEntity { + type Conversation = { + id: string; + accounts: Array; + last_status: Status | null; + unread: boolean; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/conversation.js b/packages/megalodon/lib/src/mastodon/entities/conversation.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/conversation.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/emoji.d.ts b/packages/megalodon/lib/src/mastodon/entities/emoji.d.ts new file mode 100644 index 000000000..e5aedd56f --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/emoji.d.ts @@ -0,0 +1,9 @@ +declare namespace MastodonEntity { + type Emoji = { + shortcode: string; + static_url: string; + url: string; + visible_in_picker: boolean; + category: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/emoji.js b/packages/megalodon/lib/src/mastodon/entities/emoji.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/emoji.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/featured_tag.d.ts b/packages/megalodon/lib/src/mastodon/entities/featured_tag.d.ts new file mode 100644 index 000000000..1587354b9 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/featured_tag.d.ts @@ -0,0 +1,8 @@ +declare namespace MastodonEntity { + type FeaturedTag = { + id: string; + name: string; + statuses_count: number; + last_status_at: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/featured_tag.js b/packages/megalodon/lib/src/mastodon/entities/featured_tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/featured_tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/field.d.ts b/packages/megalodon/lib/src/mastodon/entities/field.d.ts new file mode 100644 index 000000000..bff55954c --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/field.d.ts @@ -0,0 +1,7 @@ +declare namespace MastodonEntity { + type Field = { + name: string; + value: string; + verified_at: string | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/field.js b/packages/megalodon/lib/src/mastodon/entities/field.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/field.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/filter.d.ts b/packages/megalodon/lib/src/mastodon/entities/filter.d.ts new file mode 100644 index 000000000..963c7c4ae --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/filter.d.ts @@ -0,0 +1,11 @@ +declare namespace MastodonEntity { + type Filter = { + id: string; + phrase: string; + context: Array; + expires_at: string | null; + irreversible: boolean; + whole_word: boolean; + }; + type FilterContext = string; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/filter.js b/packages/megalodon/lib/src/mastodon/entities/filter.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/filter.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/history.d.ts b/packages/megalodon/lib/src/mastodon/entities/history.d.ts new file mode 100644 index 000000000..3303cdd6e --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/history.d.ts @@ -0,0 +1,7 @@ +declare namespace MastodonEntity { + type History = { + day: string; + uses: number; + accounts: number; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/history.js b/packages/megalodon/lib/src/mastodon/entities/history.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/history.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/identity_proof.d.ts b/packages/megalodon/lib/src/mastodon/entities/identity_proof.d.ts new file mode 100644 index 000000000..c4c42548f --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/identity_proof.d.ts @@ -0,0 +1,9 @@ +declare namespace MastodonEntity { + type IdentityProof = { + provider: string; + provider_username: string; + updated_at: string; + proof_url: string; + profile_url: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/identity_proof.js b/packages/megalodon/lib/src/mastodon/entities/identity_proof.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/identity_proof.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/instance.d.ts b/packages/megalodon/lib/src/mastodon/entities/instance.d.ts new file mode 100644 index 000000000..c8c0dc608 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/instance.d.ts @@ -0,0 +1,40 @@ +/// +/// +/// +declare namespace MastodonEntity { + type Instance = { + uri: string; + title: string; + description: string; + email: string; + version: string; + thumbnail: string | null; + urls: URLs; + stats: Stats; + languages: Array; + contact_account: Account | null; + max_toot_chars?: number; + registrations?: boolean; + configuration?: { + statuses: { + max_characters: number; + max_media_attachments: number; + characters_reserved_per_url: number; + }; + media_attachments: { + supported_mime_types: Array; + image_size_limit: number; + image_matrix_limit: number; + video_size_limit: number; + video_frame_limit: number; + video_matrix_limit: number; + }; + polls: { + max_options: number; + max_characters_per_option: number; + min_expiration: number; + max_expiration: number; + }; + }; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/instance.js b/packages/megalodon/lib/src/mastodon/entities/instance.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/instance.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/list.d.ts b/packages/megalodon/lib/src/mastodon/entities/list.d.ts new file mode 100644 index 000000000..e72bc7993 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/list.d.ts @@ -0,0 +1,6 @@ +declare namespace MastodonEntity { + type List = { + id: string; + title: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/list.js b/packages/megalodon/lib/src/mastodon/entities/list.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/list.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/marker.d.ts b/packages/megalodon/lib/src/mastodon/entities/marker.d.ts new file mode 100644 index 000000000..c10a16586 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/marker.d.ts @@ -0,0 +1,14 @@ +declare namespace MastodonEntity { + type Marker = { + home: { + last_read_id: string; + version: number; + updated_at: string; + }; + notifications: { + last_read_id: string; + version: number; + updated_at: string; + }; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/marker.js b/packages/megalodon/lib/src/mastodon/entities/marker.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/marker.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/mention.d.ts b/packages/megalodon/lib/src/mastodon/entities/mention.d.ts new file mode 100644 index 000000000..c850ddb81 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/mention.d.ts @@ -0,0 +1,8 @@ +declare namespace MastodonEntity { + type Mention = { + id: string; + username: string; + url: string; + acct: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/mention.js b/packages/megalodon/lib/src/mastodon/entities/mention.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/mention.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/notification.d.ts b/packages/megalodon/lib/src/mastodon/entities/notification.d.ts new file mode 100644 index 000000000..22b16434d --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/notification.d.ts @@ -0,0 +1,12 @@ +/// +/// +declare namespace MastodonEntity { + type Notification = { + account: Account; + created_at: string; + id: string; + status?: Status; + type: NotificationType; + }; + type NotificationType = string; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/notification.js b/packages/megalodon/lib/src/mastodon/entities/notification.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/notification.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/poll.d.ts b/packages/megalodon/lib/src/mastodon/entities/poll.d.ts new file mode 100644 index 000000000..636b0ed93 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/poll.d.ts @@ -0,0 +1,12 @@ +/// +declare namespace MastodonEntity { + type Poll = { + id: string; + expires_at: string | null; + expired: boolean; + multiple: boolean; + votes_count: number; + options: Array; + voted: boolean; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/poll.js b/packages/megalodon/lib/src/mastodon/entities/poll.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/poll.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/poll_option.d.ts b/packages/megalodon/lib/src/mastodon/entities/poll_option.d.ts new file mode 100644 index 000000000..7ed529faa --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/poll_option.d.ts @@ -0,0 +1,6 @@ +declare namespace MastodonEntity { + type PollOption = { + title: string; + votes_count: number | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/poll_option.js b/packages/megalodon/lib/src/mastodon/entities/poll_option.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/poll_option.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/preferences.d.ts b/packages/megalodon/lib/src/mastodon/entities/preferences.d.ts new file mode 100644 index 000000000..011dc27d1 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/preferences.d.ts @@ -0,0 +1,9 @@ +declare namespace MastodonEntity { + type Preferences = { + 'posting:default:visibility': 'public' | 'unlisted' | 'private' | 'direct'; + 'posting:default:sensitive': boolean; + 'posting:default:language': string | null; + 'reading:expand:media': 'default' | 'show_all' | 'hide_all'; + 'reading:expand:spoilers': boolean; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/preferences.js b/packages/megalodon/lib/src/mastodon/entities/preferences.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/preferences.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/push_subscription.d.ts b/packages/megalodon/lib/src/mastodon/entities/push_subscription.d.ts new file mode 100644 index 000000000..dbed36e34 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/push_subscription.d.ts @@ -0,0 +1,15 @@ +declare namespace MastodonEntity { + type Alerts = { + follow: boolean; + favourite: boolean; + mention: boolean; + reblog: boolean; + poll: boolean; + }; + type PushSubscription = { + id: string; + endpoint: string; + server_key: string; + alerts: Alerts; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/push_subscription.js b/packages/megalodon/lib/src/mastodon/entities/push_subscription.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/push_subscription.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/relationship.d.ts b/packages/megalodon/lib/src/mastodon/entities/relationship.d.ts new file mode 100644 index 000000000..33b9f8d85 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/relationship.d.ts @@ -0,0 +1,18 @@ +declare namespace MastodonEntity { + type Relationship = { + id: string; + following: boolean; + followed_by: boolean; + delivery_following: boolean; + blocking: boolean; + blocked_by: boolean; + muting: boolean; + muting_notifications: boolean; + requested: boolean; + domain_blocking: boolean; + showing_reblogs: boolean; + endorsed: boolean; + notifying: boolean; + note: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/relationship.js b/packages/megalodon/lib/src/mastodon/entities/relationship.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/relationship.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/report.d.ts b/packages/megalodon/lib/src/mastodon/entities/report.d.ts new file mode 100644 index 000000000..d2118f105 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/report.d.ts @@ -0,0 +1,9 @@ +declare namespace MastodonEntity { + type Report = { + id: string; + action_taken: string; + comment: string; + account_id: string; + status_ids: Array; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/report.js b/packages/megalodon/lib/src/mastodon/entities/report.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/report.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/results.d.ts b/packages/megalodon/lib/src/mastodon/entities/results.d.ts new file mode 100644 index 000000000..2dbd766c2 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/results.d.ts @@ -0,0 +1,10 @@ +/// +/// +/// +declare namespace MastodonEntity { + type Results = { + accounts: Array; + statuses: Array; + hashtags: Array; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/results.js b/packages/megalodon/lib/src/mastodon/entities/results.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/results.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/scheduled_status.d.ts b/packages/megalodon/lib/src/mastodon/entities/scheduled_status.d.ts new file mode 100644 index 000000000..9bed69954 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/scheduled_status.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace MastodonEntity { + type ScheduledStatus = { + id: string; + scheduled_at: string; + params: StatusParams; + media_attachments: Array; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/scheduled_status.js b/packages/megalodon/lib/src/mastodon/entities/scheduled_status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/scheduled_status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/source.d.ts b/packages/megalodon/lib/src/mastodon/entities/source.d.ts new file mode 100644 index 000000000..fc7d06164 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/source.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace MastodonEntity { + type Source = { + privacy: string | null; + sensitive: boolean | null; + language: string | null; + note: string; + fields: Array; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/source.js b/packages/megalodon/lib/src/mastodon/entities/source.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/source.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/stats.d.ts b/packages/megalodon/lib/src/mastodon/entities/stats.d.ts new file mode 100644 index 000000000..86648217a --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/stats.d.ts @@ -0,0 +1,7 @@ +declare namespace MastodonEntity { + type Stats = { + user_count: number; + status_count: number; + domain_count: number; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/stats.js b/packages/megalodon/lib/src/mastodon/entities/stats.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/stats.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/status.d.ts b/packages/megalodon/lib/src/mastodon/entities/status.d.ts new file mode 100644 index 000000000..7d0778fde --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/status.d.ts @@ -0,0 +1,42 @@ +/// +/// +/// +/// +/// +/// +/// +/// +declare namespace MastodonEntity { + type Status = { + id: string; + uri: string; + url: string; + account: Account; + in_reply_to_id: string | null; + in_reply_to_account_id: string | null; + reblog: Status | null; + content: string; + created_at: string; + emojis: Emoji[]; + replies_count: number; + reblogs_count: number; + favourites_count: number; + reblogged: boolean | null; + favourited: boolean | null; + muted: boolean | null; + sensitive: boolean; + spoiler_text: string; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + media_attachments: Array; + mentions: Array; + tags: Array; + card: Card | null; + poll: Poll | null; + application: Application | null; + language: string | null; + pinned: boolean | null; + bookmarked?: boolean; + quote_id?: string; + quote?: Status | null; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/status.js b/packages/megalodon/lib/src/mastodon/entities/status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/status_params.d.ts b/packages/megalodon/lib/src/mastodon/entities/status_params.d.ts new file mode 100644 index 000000000..cf4e9bf29 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/status_params.d.ts @@ -0,0 +1,12 @@ +declare namespace MastodonEntity { + type StatusParams = { + text: string; + in_reply_to_id: string | null; + media_ids: Array | null; + sensitive: boolean | null; + spoiler_text: string | null; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at: string | null; + application_id: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/status_params.js b/packages/megalodon/lib/src/mastodon/entities/status_params.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/status_params.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/tag.d.ts b/packages/megalodon/lib/src/mastodon/entities/tag.d.ts new file mode 100644 index 000000000..418b527a9 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/tag.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace MastodonEntity { + type Tag = { + name: string; + url: string; + history: Array | null; + following?: boolean; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/tag.js b/packages/megalodon/lib/src/mastodon/entities/tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/token.d.ts b/packages/megalodon/lib/src/mastodon/entities/token.d.ts new file mode 100644 index 000000000..d7d2e192a --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/token.d.ts @@ -0,0 +1,8 @@ +declare namespace MastodonEntity { + type Token = { + access_token: string; + token_type: string; + scope: string; + created_at: number; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/token.js b/packages/megalodon/lib/src/mastodon/entities/token.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/token.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entities/urls.d.ts b/packages/megalodon/lib/src/mastodon/entities/urls.d.ts new file mode 100644 index 000000000..fd56c2b32 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/urls.d.ts @@ -0,0 +1,5 @@ +declare namespace MastodonEntity { + type URLs = { + streaming_api: string; + }; +} diff --git a/packages/megalodon/lib/src/mastodon/entities/urls.js b/packages/megalodon/lib/src/mastodon/entities/urls.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entities/urls.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/mastodon/entity.d.ts b/packages/megalodon/lib/src/mastodon/entity.d.ts new file mode 100644 index 000000000..e93268d6f --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entity.d.ts @@ -0,0 +1,36 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +export default MastodonEntity; diff --git a/packages/megalodon/lib/src/mastodon/entity.js b/packages/megalodon/lib/src/mastodon/entity.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/entity.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/src/mastodon/notification.d.ts b/packages/megalodon/lib/src/mastodon/notification.d.ts new file mode 100644 index 000000000..d05e32790 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/notification.d.ts @@ -0,0 +1,11 @@ +import MastodonEntity from './entity'; +declare namespace MastodonNotificationType { + const Mention: MastodonEntity.NotificationType; + const Reblog: MastodonEntity.NotificationType; + const Favourite: MastodonEntity.NotificationType; + const Follow: MastodonEntity.NotificationType; + const Poll: MastodonEntity.NotificationType; + const FollowRequest: MastodonEntity.NotificationType; + const Status: MastodonEntity.NotificationType; +} +export default MastodonNotificationType; diff --git a/packages/megalodon/lib/src/mastodon/notification.js b/packages/megalodon/lib/src/mastodon/notification.js new file mode 100644 index 000000000..790ca9d84 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/notification.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MastodonNotificationType; +(function (MastodonNotificationType) { + MastodonNotificationType.Mention = 'mention'; + MastodonNotificationType.Reblog = 'reblog'; + MastodonNotificationType.Favourite = 'favourite'; + MastodonNotificationType.Follow = 'follow'; + MastodonNotificationType.Poll = 'poll'; + MastodonNotificationType.FollowRequest = 'follow_request'; + MastodonNotificationType.Status = 'status'; +})(MastodonNotificationType || (MastodonNotificationType = {})); +exports.default = MastodonNotificationType; diff --git a/packages/megalodon/lib/src/mastodon/web_socket.d.ts b/packages/megalodon/lib/src/mastodon/web_socket.d.ts new file mode 100644 index 000000000..639afab43 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/web_socket.d.ts @@ -0,0 +1,39 @@ +/// +import WS from 'ws'; +import { EventEmitter } from 'events'; +import { ProxyConfig } from '../proxy_config'; +import { WebSocketInterface } from '../megalodon'; +export default class WebSocket extends EventEmitter implements WebSocketInterface { + url: string; + stream: string; + params: string | null; + parser: Parser; + headers: { + [key: string]: string; + }; + proxyConfig: ProxyConfig | false; + private _accessToken; + private _reconnectInterval; + private _reconnectMaxAttempts; + private _reconnectCurrentAttempts; + private _connectionClosed; + private _client; + private _pongReceivedTimestamp; + private _heartbeatInterval; + private _pongWaiting; + constructor(url: string, stream: string, params: string | undefined, accessToken: string, userAgent: string, proxyConfig?: ProxyConfig | false); + start(): void; + private _startWebSocketConnection; + stop(): void; + private _resetConnection; + private _resetRetryParams; + private _reconnect; + private _connect; + private _clearBinding; + private _bindSocket; + private _setupParser; + private _checkAlive; +} +export declare class Parser extends EventEmitter { + parse(data: WS.Data, isBinary: boolean): void; +} diff --git a/packages/megalodon/lib/src/mastodon/web_socket.js b/packages/megalodon/lib/src/mastodon/web_socket.js new file mode 100644 index 000000000..f37876729 --- /dev/null +++ b/packages/megalodon/lib/src/mastodon/web_socket.js @@ -0,0 +1,260 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Parser = void 0; +var ws_1 = __importDefault(require("ws")); +var dayjs_1 = __importDefault(require("dayjs")); +var events_1 = require("events"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var api_client_1 = __importDefault(require("./api_client")); +var WebSocket = (function (_super) { + __extends(WebSocket, _super); + function WebSocket(url, stream, params, accessToken, userAgent, proxyConfig) { + if (proxyConfig === void 0) { proxyConfig = false; } + var _this = _super.call(this) || this; + _this.proxyConfig = false; + _this._heartbeatInterval = 60000; + _this._pongWaiting = false; + _this.url = url; + _this.stream = stream; + if (params === undefined) { + _this.params = null; + } + else { + _this.params = params; + } + _this.parser = new Parser(); + _this.headers = { + 'User-Agent': userAgent + }; + _this.proxyConfig = proxyConfig; + _this._accessToken = accessToken; + _this._reconnectInterval = 10000; + _this._reconnectMaxAttempts = Infinity; + _this._reconnectCurrentAttempts = 0; + _this._connectionClosed = false; + _this._client = null; + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + return _this; + } + WebSocket.prototype.start = function () { + this._connectionClosed = false; + this._resetRetryParams(); + this._startWebSocketConnection(); + }; + WebSocket.prototype._startWebSocketConnection = function () { + this._resetConnection(); + this._setupParser(); + this._client = this._connect(this.url, this.stream, this.params, this._accessToken, this.headers, this.proxyConfig); + this._bindSocket(this._client); + }; + WebSocket.prototype.stop = function () { + this._connectionClosed = true; + this._resetConnection(); + this._resetRetryParams(); + }; + WebSocket.prototype._resetConnection = function () { + if (this._client) { + this._client.close(1000); + this._client.removeAllListeners(); + this._client = null; + } + if (this.parser) { + this.parser.removeAllListeners(); + } + }; + WebSocket.prototype._resetRetryParams = function () { + this._reconnectCurrentAttempts = 0; + }; + WebSocket.prototype._reconnect = function () { + var _this = this; + setTimeout(function () { + if (_this._client && _this._client.readyState === ws_1.default.CONNECTING) { + return; + } + if (_this._reconnectCurrentAttempts < _this._reconnectMaxAttempts) { + _this._reconnectCurrentAttempts++; + _this._clearBinding(); + if (_this._client) { + _this._client.terminate(); + } + console.log('Reconnecting'); + _this._client = _this._connect(_this.url, _this.stream, _this.params, _this._accessToken, _this.headers, _this.proxyConfig); + _this._bindSocket(_this._client); + } + }, this._reconnectInterval); + }; + WebSocket.prototype._connect = function (url, stream, params, accessToken, headers, proxyConfig) { + var parameter = ["stream=".concat(stream)]; + if (params) { + parameter.push(params); + } + if (accessToken !== null) { + parameter.push("access_token=".concat(accessToken)); + } + var requestURL = "".concat(url, "/?").concat(parameter.join('&')); + var options = { + headers: headers + }; + if (proxyConfig) { + options = Object.assign(options, { + agent: (0, proxy_config_1.default)(proxyConfig) + }); + } + var cli = new ws_1.default(requestURL, options); + return cli; + }; + WebSocket.prototype._clearBinding = function () { + if (this._client) { + this._client.removeAllListeners('close'); + this._client.removeAllListeners('pong'); + this._client.removeAllListeners('open'); + this._client.removeAllListeners('message'); + this._client.removeAllListeners('error'); + } + }; + WebSocket.prototype._bindSocket = function (client) { + var _this = this; + client.on('close', function (code, _reason) { + if (code === 1000) { + _this.emit('close', {}); + } + else { + console.log("Closed connection with ".concat(code)); + if (!_this._connectionClosed) { + _this._reconnect(); + } + } + }); + client.on('pong', function () { + _this._pongWaiting = false; + _this.emit('pong', {}); + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + setTimeout(function () { return _this._checkAlive(_this._pongReceivedTimestamp); }, _this._heartbeatInterval); + }); + client.on('open', function () { + _this.emit('connect', {}); + setTimeout(function () { + client.ping(''); + }, 10000); + }); + client.on('message', function (data, isBinary) { + _this.parser.parse(data, isBinary); + }); + client.on('error', function (err) { + _this.emit('error', err); + }); + }; + WebSocket.prototype._setupParser = function () { + var _this = this; + this.parser.on('update', function (status) { + _this.emit('update', api_client_1.default.Converter.status(status)); + }); + this.parser.on('notification', function (notification) { + _this.emit('notification', api_client_1.default.Converter.notification(notification)); + }); + this.parser.on('delete', function (id) { + _this.emit('delete', id); + }); + this.parser.on('conversation', function (conversation) { + _this.emit('conversation', api_client_1.default.Converter.conversation(conversation)); + }); + this.parser.on('status_update', function (status) { + _this.emit('status_update', api_client_1.default.Converter.status(status)); + }); + this.parser.on('error', function (err) { + _this.emit('parser-error', err); + }); + this.parser.on('heartbeat', function (_) { + _this.emit('heartbeat', 'heartbeat'); + }); + }; + WebSocket.prototype._checkAlive = function (timestamp) { + var _this = this; + var now = (0, dayjs_1.default)(); + if (now.diff(timestamp) > this._heartbeatInterval - 1000 && !this._connectionClosed) { + if (this._client && this._client.readyState !== ws_1.default.CONNECTING) { + this._pongWaiting = true; + this._client.ping(''); + setTimeout(function () { + if (_this._pongWaiting) { + _this._pongWaiting = false; + _this._reconnect(); + } + }, 10000); + } + } + }; + return WebSocket; +}(events_1.EventEmitter)); +exports.default = WebSocket; +var Parser = (function (_super) { + __extends(Parser, _super); + function Parser() { + return _super !== null && _super.apply(this, arguments) || this; + } + Parser.prototype.parse = function (data, isBinary) { + var message = isBinary ? data : data.toString(); + if (typeof message !== 'string') { + this.emit('heartbeat', {}); + return; + } + if (message === '') { + this.emit('heartbeat', {}); + return; + } + var event = ''; + var payload = ''; + var mes = {}; + try { + var obj = JSON.parse(message); + event = obj.event; + payload = obj.payload; + mes = JSON.parse(payload); + } + catch (err) { + if (event !== 'delete') { + this.emit('error', new Error("Error parsing websocket reply: ".concat(message, ", error message: ").concat(err))); + return; + } + } + switch (event) { + case 'update': + this.emit('update', mes); + break; + case 'notification': + this.emit('notification', mes); + break; + case 'conversation': + this.emit('conversation', mes); + break; + case 'delete': + this.emit('delete', payload); + break; + case 'status.update': + this.emit('status_update', mes); + break; + default: + this.emit('error', new Error("Unknown event has received: ".concat(message))); + } + }; + return Parser; +}(events_1.EventEmitter)); +exports.Parser = Parser; diff --git a/packages/megalodon/lib/src/megalodon.d.ts b/packages/megalodon/lib/src/megalodon.d.ts new file mode 100644 index 000000000..1128dd0a5 --- /dev/null +++ b/packages/megalodon/lib/src/megalodon.d.ts @@ -0,0 +1,386 @@ +import Response from './response'; +import OAuth from './oauth'; +import { ProxyConfig } from './proxy_config'; +import Entity from './entity'; +export interface WebSocketInterface { + start(): void; + stop(): void; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + removeAllListeners(event?: string | symbol): this; +} +export interface MegalodonInterface { + cancel(): void; + registerApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + createApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + verifyAppCredentials(): Promise>; + fetchAccessToken(client_id: string | null, client_secret: string, code: string, redirect_uri?: string): Promise; + refreshToken(client_id: string, client_secret: string, refresh_token: string): Promise; + revokeToken(client_id: string, client_secret: string, token: string): Promise>; + registerAccount(username: string, email: string, password: string, agreement: boolean, locale: string, reason?: string | null): Promise>; + verifyAccountCredentials(): Promise>; + updateCredentials(options?: { + discoverable?: boolean; + bot?: boolean; + display_name?: string; + note?: string; + avatar?: string; + header?: string; + locked?: boolean; + source?: { + privacy?: string; + sensitive?: boolean; + language?: string; + }; + fields_attributes?: Array<{ + name: string; + value: string; + }>; + }): Promise>; + getAccount(id: string): Promise>; + getAccountStatuses(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + pinned?: boolean; + exclude_replies?: boolean; + exclude_reblogs?: boolean; + only_media?: boolean; + }): Promise>>; + getAccountFavourites(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + subscribeAccount(id: string): Promise>; + unsubscribeAccount(id: string): Promise>; + getAccountFollowers(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + get_all?: boolean; + sleep_ms?: number; + }): Promise>>; + getAccountFeaturedTags(id: string): Promise>>; + getAccountFollowing(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + get_all?: boolean; + sleep_ms?: number; + }): Promise>>; + getAccountLists(id: string): Promise>>; + getIdentityProof(id: string): Promise>>; + followAccount(id: string, options?: { + reblog?: boolean; + }): Promise>; + unfollowAccount(id: string): Promise>; + blockAccount(id: string): Promise>; + unblockAccount(id: string): Promise>; + muteAccount(id: string, notifications: boolean): Promise>; + unmuteAccount(id: string): Promise>; + pinAccount(id: string): Promise>; + unpinAccount(id: string): Promise>; + getRelationship(id: string): Promise>; + getRelationships(ids: Array): Promise>>; + searchAccount(q: string, options?: { + following?: boolean; + resolve?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getBookmarks(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getFavourites(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getMutes(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getDomainBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + blockDomain(domain: string): Promise>; + unblockDomain(domain: string): Promise>; + getFilters(): Promise>>; + getFilter(id: string): Promise>; + createFilter(phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + updateFilter(id: string, phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + deleteFilter(id: string): Promise>; + report(account_id: string, comment: string, options?: { + status_ids?: Array; + forward?: boolean; + }): Promise>; + getFollowRequests(limit?: number): Promise>>; + acceptFollowRequest(id: string): Promise>; + rejectFollowRequest(id: string): Promise>; + getEndorsements(options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getFeaturedTags(): Promise>>; + createFeaturedTag(name: string): Promise>; + deleteFeaturedTag(id: string): Promise>; + getSuggestedTags(): Promise>>; + getPreferences(): Promise>; + getSuggestions(limit?: number): Promise>>; + getFollowedTags(): Promise>>; + getTag(id: string): Promise>; + followTag(id: string): Promise>; + unfollowTag(id: string): Promise>; + postStatus(status: string, options?: { + media_ids?: Array; + poll?: { + options: Array; + expires_in: number; + multiple?: boolean; + hide_totals?: boolean; + }; + in_reply_to_id?: string; + sensitive?: boolean; + spoiler_text?: string; + visibility?: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at?: string; + language?: string; + quote_id?: string; + }): Promise>; + getStatus(id: string): Promise>; + editStatus(id: string, options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array; + poll?: { + options?: Array; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }): Promise>; + deleteStatus(id: string): Promise>; + getStatusContext(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>; + getStatusHistory(id: string): Promise>>; + getStatusRebloggedBy(id: string): Promise>>; + getStatusFavouritedBy(id: string): Promise>>; + favouriteStatus(id: string): Promise>; + unfavouriteStatus(id: string): Promise>; + reblogStatus(id: string): Promise>; + unreblogStatus(id: string): Promise>; + bookmarkStatus(id: string): Promise>; + unbookmarkStatus(id: string): Promise>; + muteStatus(id: string): Promise>; + unmuteStatus(id: string): Promise>; + pinStatus(id: string): Promise>; + unpinStatus(id: string): Promise>; + uploadMedia(file: any, options?: { + description?: string; + focus?: string; + }): Promise>; + getMedia(id: string): Promise>; + updateMedia(id: string, options?: { + file?: any; + description?: string; + focus?: string; + is_sensitive?: boolean; + }): Promise>; + getPoll(id: string): Promise>; + votePoll(id: string, choices: Array, status_id?: string | null): Promise>; + getScheduledStatuses(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getScheduledStatus(id: string): Promise>; + scheduleStatus(id: string, scheduled_at?: string | null): Promise>; + cancelScheduledStatus(id: string): Promise>; + getPublicTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getLocalTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getTagTimeline(hashtag: string, options?: { + local?: boolean; + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getHomeTimeline(options?: { + local?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getListTimeline(list_id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getConversationTimeline(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + deleteConversation(id: string): Promise>; + readConversation(id: string): Promise>; + getLists(): Promise>>; + getList(id: string): Promise>; + createList(title: string): Promise>; + updateList(id: string, title: string): Promise>; + deleteList(id: string): Promise>; + getAccountsInList(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + addAccountsToList(id: string, account_ids: Array): Promise>; + deleteAccountsFromList(id: string, account_ids: Array): Promise>; + getMarkers(timeline: Array): Promise>; + saveMarkers(options?: { + home?: { + last_read_id: string; + }; + notifications?: { + last_read_id: string; + }; + }): Promise>; + getNotifications(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + exclude_types?: Array; + account_id?: string; + }): Promise>>; + getNotification(id: string): Promise>; + dismissNotifications(): Promise>; + dismissNotification(id: string): Promise>; + readNotifications(options: { + id?: string; + max_id?: string; + }): Promise>>; + subscribePushNotification(subscription: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }, data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + getPushSubscription(): Promise>; + updatePushSubscription(data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + deletePushSubscription(): Promise>; + search(q: string, type: 'accounts' | 'hashtags' | 'statuses', options?: { + limit?: number; + max_id?: string; + min_id?: string; + resolve?: boolean; + offset?: number; + following?: boolean; + account_id?: string; + exclude_unreviewed?: boolean; + }): Promise>; + getInstance(): Promise>; + getInstancePeers(): Promise>>; + getInstanceActivity(): Promise>>; + getInstanceTrends(limit?: number | null): Promise>>; + getInstanceDirectory(options?: { + limit?: number; + offset?: number; + order?: 'active' | 'new'; + local?: boolean; + }): Promise>>; + getInstanceCustomEmojis(): Promise>>; + getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>>; + dismissInstanceAnnouncement(id: string): Promise>; + createEmojiReaction(id: string, emoji: string): Promise>; + deleteEmojiReaction(id: string, emoji: string): Promise>; + getEmojiReactions(id: string): Promise>>; + getEmojiReaction(id: string, emoji: string): Promise>; + userSocket(): WebSocketInterface; + publicSocket(): WebSocketInterface; + localSocket(): WebSocketInterface; + tagSocket(tag: string): WebSocketInterface; + listSocket(list_id: string): WebSocketInterface; + directSocket(): WebSocketInterface; +} +export declare class NoImplementedError extends Error { + constructor(err?: string); +} +export declare class ArgumentError extends Error { + constructor(err?: string); +} +export declare class UnexpectedError extends Error { + constructor(err?: string); +} +export declare const detector: (url: string, proxyConfig?: ProxyConfig | false) => Promise<'mastodon' | 'pleroma' | 'misskey'>; +declare const generator: (baseUrl: string, accessToken?: string | null, userAgent?: string | null, proxyConfig?: ProxyConfig | false) => MegalodonInterface; +export default generator; diff --git a/packages/megalodon/lib/src/megalodon.js b/packages/megalodon/lib/src/megalodon.js new file mode 100644 index 000000000..8071e7f82 --- /dev/null +++ b/packages/megalodon/lib/src/megalodon.js @@ -0,0 +1,146 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.detector = exports.UnexpectedError = exports.ArgumentError = exports.NoImplementedError = void 0; +var proxy_config_1 = __importDefault(require("./proxy_config")); +var axios_1 = __importDefault(require("axios")); +var misskey_1 = __importDefault(require("./misskey")); +var default_1 = require("./default"); +var NoImplementedError = (function (_super) { + __extends(NoImplementedError, _super); + function NoImplementedError(err) { + var _newTarget = this.constructor; + var _this = _super.call(this, err) || this; + _this.name = _newTarget.name; + Object.setPrototypeOf(_this, _newTarget.prototype); + return _this; + } + return NoImplementedError; +}(Error)); +exports.NoImplementedError = NoImplementedError; +var ArgumentError = (function (_super) { + __extends(ArgumentError, _super); + function ArgumentError(err) { + var _newTarget = this.constructor; + var _this = _super.call(this, err) || this; + _this.name = _newTarget.name; + Object.setPrototypeOf(_this, _newTarget.prototype); + return _this; + } + return ArgumentError; +}(Error)); +exports.ArgumentError = ArgumentError; +var UnexpectedError = (function (_super) { + __extends(UnexpectedError, _super); + function UnexpectedError(err) { + var _newTarget = this.constructor; + var _this = _super.call(this, err) || this; + _this.name = _newTarget.name; + Object.setPrototypeOf(_this, _newTarget.prototype); + return _this; + } + return UnexpectedError; +}(Error)); +exports.UnexpectedError = UnexpectedError; +var detector = function (url, proxyConfig) { + if (proxyConfig === void 0) { proxyConfig = false; } + return __awaiter(void 0, void 0, void 0, function () { + var options, res, err_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + options = { + headers: { + 'User-Agent': default_1.DEFAULT_UA + } + }; + if (proxyConfig) { + options = Object.assign(options, { + httpsAgent: (0, proxy_config_1.default)(proxyConfig) + }); + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 5]); + return [4, axios_1.default.get(url + '/api/v1/instance', options)]; + case 2: + res = _a.sent(); + if (res.data.version.includes('Pleroma')) { + return [2, 'pleroma']; + } + else { + return [2, 'mastodon']; + } + return [3, 5]; + case 3: + err_1 = _a.sent(); + return [4, axios_1.default.post(url + '/api/meta', {}, options)]; + case 4: + _a.sent(); + return [2, 'misskey']; + case 5: return [2]; + } + }); + }); +}; +exports.detector = detector; +var generator = function (baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = null; } + if (proxyConfig === void 0) { proxyConfig = false; } + return new misskey_1.default(baseUrl, accessToken, userAgent, proxyConfig); +}; +exports.default = generator; diff --git a/packages/megalodon/lib/src/misskey.d.ts b/packages/megalodon/lib/src/misskey.d.ts new file mode 100644 index 000000000..f31544218 --- /dev/null +++ b/packages/megalodon/lib/src/misskey.d.ts @@ -0,0 +1,385 @@ +import AsyncLock from 'async-lock'; +import MisskeyAPI from './misskey/api_client'; +import { ProxyConfig } from './proxy_config'; +import OAuth from './oauth'; +import Response from './response'; +import Entity from './entity'; +import { MegalodonInterface, WebSocketInterface } from './megalodon'; +import MegalodonEntity from "@/entity"; +type AccountCache = { + locks: AsyncLock; + accounts: Entity.Account[]; +}; +export default class Misskey implements MegalodonInterface { + client: MisskeyAPI.Interface; + converter: MisskeyAPI.Converter; + baseUrl: string; + proxyConfig: ProxyConfig | false; + constructor(baseUrl: string, accessToken?: string | null, userAgent?: string | null, proxyConfig?: ProxyConfig | false); + private baseUrlToHost; + cancel(): void; + registerApp(client_name: string, options?: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + createApp(client_name: string, options?: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + generateAuthUrlAndToken(clientSecret: string): Promise; + verifyAppCredentials(): Promise>; + fetchAccessToken(_client_id: string | null, client_secret: string, session_token: string, _redirect_uri?: string): Promise; + refreshToken(_client_id: string, _client_secret: string, _refresh_token: string): Promise; + revokeToken(_client_id: string, _client_secret: string, _token: string): Promise>; + registerAccount(_username: string, _email: string, _password: string, _agreement: boolean, _locale: string, _reason?: string | null): Promise>; + verifyAccountCredentials(): Promise>; + updateCredentials(options?: { + discoverable?: boolean; + bot?: boolean; + display_name?: string; + note?: string; + avatar?: string; + header?: string; + locked?: boolean; + source?: { + privacy?: string; + sensitive?: boolean; + language?: string; + } | null; + fields_attributes?: Array<{ + name: string; + value: string; + }>; + }): Promise>; + getAccount(id: string): Promise>; + getAccountByName(user: string, host: string | null): Promise>; + getAccountStatuses(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + pinned?: boolean; + exclude_replies: boolean; + exclude_reblogs: boolean; + only_media?: boolean; + }): Promise>>; + getAccountFavourites(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + subscribeAccount(_id: string): Promise>; + unsubscribeAccount(_id: string): Promise>; + getAccountFollowers(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountFollowing(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountLists(_id: string): Promise>>; + getIdentityProof(_id: string): Promise>>; + followAccount(id: string, _options?: { + reblog?: boolean; + }): Promise>; + unfollowAccount(id: string): Promise>; + blockAccount(id: string): Promise>; + unblockAccount(id: string): Promise>; + muteAccount(id: string, _notifications: boolean): Promise>; + unmuteAccount(id: string): Promise>; + pinAccount(_id: string): Promise>; + unpinAccount(_id: string): Promise>; + getRelationship(id: string): Promise>; + getRelationships(ids: Array): Promise>>; + searchAccount(q: string, options?: { + following?: boolean; + resolve?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getBookmarks(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getFavourites(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getMutes(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getDomainBlocks(_options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + blockDomain(_domain: string): Promise>; + unblockDomain(_domain: string): Promise>; + getFilters(): Promise>>; + getFilter(_id: string): Promise>; + createFilter(_phrase: string, _context: Array, _options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + updateFilter(_id: string, _phrase: string, _context: Array, _options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + deleteFilter(_id: string): Promise>; + report(account_id: string, comment: string, _options?: { + status_ids?: Array; + forward?: boolean; + }): Promise>; + getFollowRequests(_limit?: number): Promise>>; + acceptFollowRequest(id: string): Promise>; + rejectFollowRequest(id: string): Promise>; + getEndorsements(_options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getFeaturedTags(): Promise>>; + getAccountFeaturedTags(): Promise>>; + createFeaturedTag(_name: string): Promise>; + deleteFeaturedTag(_id: string): Promise>; + getSuggestedTags(): Promise>>; + getPreferences(): Promise>; + getSuggestions(limit?: number): Promise>>; + getFollowedTags(): Promise>>; + getTag(_id: string): Promise>; + followTag(_id: string): Promise>; + unfollowTag(_id: string): Promise>; + postStatus(status: string, options?: { + media_ids?: Array; + poll?: { + options: Array; + expires_in: number; + multiple?: boolean; + hide_totals?: boolean; + }; + in_reply_to_id?: string; + sensitive?: boolean; + spoiler_text?: string; + visibility?: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at?: string; + language?: string; + quote_id?: string; + }): Promise>; + getStatus(id: string): Promise>; + private getFreshAccountCache; + noteWithMentions(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise; + addMentionsToStatus(status: Entity.Status, cache: AccountCache): Promise; + getMentions(text: string, cache: AccountCache): Promise; + getAccountByNameCached(user: string, host: string | null, cache: AccountCache): Promise; + editStatus(_id: string, _options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array; + poll?: { + options?: Array; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }): Promise>; + deleteStatus(id: string): Promise>; + getStatusContext(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>; + private dfs; + getStatusHistory(): Promise>>; + getStatusRebloggedBy(id: string): Promise>>; + getStatusFavouritedBy(_id: string): Promise>>; + favouriteStatus(id: string): Promise>; + private getDefaultFavoriteEmoji; + unfavouriteStatus(id: string): Promise>; + reblogStatus(id: string): Promise>; + unreblogStatus(id: string): Promise>; + bookmarkStatus(id: string): Promise>; + unbookmarkStatus(id: string): Promise>; + muteStatus(_id: string): Promise>; + unmuteStatus(_id: string): Promise>; + pinStatus(id: string): Promise>; + unpinStatus(id: string): Promise>; + uploadMedia(file: any, _options?: { + description?: string; + focus?: string; + }): Promise>; + getMedia(id: string): Promise>; + updateMedia(id: string, options?: { + file?: any; + description?: string; + focus?: string; + is_sensitive?: boolean; + }): Promise>; + getPoll(_id: string): Promise>; + votePoll(_id: string, choices: Array, status_id?: string | null): Promise>; + getScheduledStatuses(_options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getScheduledStatus(_id: string): Promise>; + scheduleStatus(_id: string, _scheduled_at?: string | null): Promise>; + cancelScheduledStatus(_id: string): Promise>; + getPublicTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getLocalTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getTagTimeline(hashtag: string, options?: { + local?: boolean; + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getHomeTimeline(options?: { + local?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getListTimeline(list_id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getConversationTimeline(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + deleteConversation(_id: string): Promise>; + readConversation(_id: string): Promise>; + getLists(): Promise>>; + getList(id: string): Promise>; + createList(title: string): Promise>; + updateList(id: string, title: string): Promise>; + deleteList(id: string): Promise>; + getAccountsInList(id: string, _options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + addAccountsToList(id: string, account_ids: Array): Promise>; + deleteAccountsFromList(id: string, account_ids: Array): Promise>; + getMarkers(_timeline: Array): Promise>; + saveMarkers(_options?: { + home?: { + last_read_id: string; + }; + notifications?: { + last_read_id: string; + }; + }): Promise>; + getNotifications(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + exclude_type?: Array; + account_id?: string; + }): Promise>>; + getNotification(_id: string): Promise>; + dismissNotifications(): Promise>; + dismissNotification(_id: string): Promise>; + readNotifications(_options: { + id?: string; + max_id?: string; + }): Promise>>; + subscribePushNotification(_subscription: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }, _data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + getPushSubscription(): Promise>; + updatePushSubscription(_data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + deletePushSubscription(): Promise>; + search(q: string, type: 'accounts' | 'hashtags' | 'statuses', options?: { + limit?: number; + max_id?: string; + min_id?: string; + resolve?: boolean; + offset?: number; + following?: boolean; + account_id?: string; + exclude_unreviewed?: boolean; + }): Promise>; + getInstance(): Promise>; + getInstancePeers(): Promise>>; + getInstanceActivity(): Promise>>; + getInstanceTrends(_limit?: number | null): Promise>>; + getInstanceDirectory(_options?: { + limit?: number; + offset?: number; + order?: 'active' | 'new'; + local?: boolean; + }): Promise>>; + getInstanceCustomEmojis(): Promise>>; + getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>>; + dismissInstanceAnnouncement(id: string): Promise>; + createEmojiReaction(id: string, emoji: string): Promise>; + deleteEmojiReaction(id: string, _emoji: string): Promise>; + getEmojiReactions(id: string): Promise>>; + getEmojiReaction(_id: string, _emoji: string): Promise>; + userSocket(): WebSocketInterface; + publicSocket(): WebSocketInterface; + localSocket(): WebSocketInterface; + tagSocket(_tag: string): WebSocketInterface; + listSocket(list_id: string): WebSocketInterface; + directSocket(): WebSocketInterface; +} +export {}; diff --git a/packages/megalodon/lib/src/misskey.js b/packages/megalodon/lib/src/misskey.js new file mode 100644 index 000000000..1730283e5 --- /dev/null +++ b/packages/megalodon/lib/src/misskey.js @@ -0,0 +1,2965 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +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 __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."); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var form_data_1 = __importDefault(require("form-data")); +var async_lock_1 = __importDefault(require("async-lock")); +var api_client_1 = __importDefault(require("./misskey/api_client")); +var default_1 = require("./default"); +var oauth_1 = __importDefault(require("./oauth")); +var megalodon_1 = require("./megalodon"); +var node_fs_1 = __importDefault(require("node:fs")); +var Misskey = (function () { + function Misskey(baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + var token = ''; + if (accessToken) { + token = accessToken; + } + var agent = default_1.DEFAULT_UA; + if (userAgent) { + agent = userAgent; + } + this.converter = new api_client_1.default.Converter(baseUrl); + this.client = new api_client_1.default.Client(baseUrl, token, agent, proxyConfig, this.converter); + this.baseUrl = baseUrl; + this.proxyConfig = proxyConfig; + } + Misskey.prototype.baseUrlToHost = function (baseUrl) { + return baseUrl.replace('https://', ''); + }; + Misskey.prototype.cancel = function () { + return this.client.cancel(); + }; + Misskey.prototype.registerApp = function (client_name, options) { + if (options === void 0) { options = { + scopes: api_client_1.default.DEFAULT_SCOPE, + redirect_uris: this.baseUrl + }; } + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.createApp(client_name, options).then(function (appData) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.generateAuthUrlAndToken(appData.client_secret).then(function (session) { + appData.url = session.url; + appData.session_token = session.token; + return appData; + })]; + }); + }); })]; + }); + }); + }; + Misskey.prototype.createApp = function (client_name, options) { + if (options === void 0) { options = { + scopes: api_client_1.default.DEFAULT_SCOPE, + redirect_uris: this.baseUrl + }; } + return __awaiter(this, void 0, void 0, function () { + var redirect_uris, scopes, params; + return __generator(this, function (_a) { + redirect_uris = options.redirect_uris || this.baseUrl; + scopes = options.scopes || api_client_1.default.DEFAULT_SCOPE; + params = { + name: client_name, + description: '', + permission: scopes, + callbackUrl: redirect_uris + }; + return [2, this.client.post('/api/app/create', params).then(function (res) { + var appData = { + id: res.data.id, + name: res.data.name, + website: null, + redirect_uri: res.data.callbackUrl, + client_id: '', + client_secret: res.data.secret + }; + return oauth_1.default.AppData.from(appData); + })]; + }); + }); + }; + Misskey.prototype.generateAuthUrlAndToken = function (clientSecret) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/auth/session/generate', { + appSecret: clientSecret + }) + .then(function (res) { return res.data; })]; + }); + }); + }; + Misskey.prototype.verifyAppCredentials = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.fetchAccessToken = function (_client_id, client_secret, session_token, _redirect_uri) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/auth/session/userkey', { + appSecret: client_secret, + token: session_token + }) + .then(function (res) { + var token = new oauth_1.default.TokenData(res.data.accessToken, 'misskey', '', 0, null, null); + return token; + })]; + }); + }); + }; + Misskey.prototype.refreshToken = function (_client_id, _client_secret, _refresh_token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.revokeToken = function (_client_id, _client_secret, _token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.registerAccount = function (_username, _email, _password, _agreement, _locale, _reason) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.verifyAccountCredentials = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client.post('/api/i').then(function (res) { + return Object.assign(res, { + data: _this.converter.userDetail(res.data, _this.baseUrlToHost(_this.baseUrl)) + }); + })]; + }); + }); + }; + Misskey.prototype.updateCredentials = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.bot !== undefined) { + params = Object.assign(params, { + isBot: options.bot + }); + } + if (options.display_name) { + params = Object.assign(params, { + name: options.display_name + }); + } + if (options.note) { + params = Object.assign(params, { + description: options.note + }); + } + if (options.locked !== undefined) { + params = Object.assign(params, { + isLocked: options.locked + }); + } + if (options.source) { + if (options.source.language) { + params = Object.assign(params, { + lang: options.source.language + }); + } + if (options.source.sensitive) { + params = Object.assign(params, { + alwaysMarkNsfw: options.source.sensitive + }); + } + } + } + return [2, this.client.post('/api/i', params).then(function (res) { + return Object.assign(res, { + data: _this.converter.userDetail(res.data, _this.baseUrlToHost(_this.baseUrl)) + }); + })]; + }); + }); + }; + Misskey.prototype.getAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/show', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.userDetail(res.data, _this.baseUrlToHost(_this.baseUrl)) + }); + })]; + }); + }); + }; + Misskey.prototype.getAccountByName = function (user, host) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/show', { + username: user, + host: host !== null && host !== void 0 ? host : null + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.userDetail(res.data, _this.baseUrlToHost(_this.baseUrl)) + }); + })]; + }); + }); + }; + Misskey.prototype.getAccountStatuses = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + if (options === null || options === void 0 ? void 0 : options.pinned) { + return [2, this.client + .post('/api/users/show', { + userId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (!res.data.pinnedNotes) return [3, 2]; + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.pinnedNotes.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, __assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)]))]; + case 2: return [2, __assign(__assign({}, res), { data: [] })]; + } + }); + }); })]; + } + params = { + userId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.exclude_replies) { + params = Object.assign(params, { + includeReplies: false + }); + } + if (options.exclude_reblogs) { + params = Object.assign(params, { + includeMyRenotes: false + }); + } + if (options.only_media) { + params = Object.assign(params, { + withFiles: options.only_media + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client.post('/api/users/notes', params).then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var statuses; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, Promise.all(res.data.map(function (note) { return _this.noteWithMentions(note, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: + statuses = _a.sent(); + return [2, Object.assign(res, { + data: statuses + })]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getAccountFavourites = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = { + userId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + } + return [2, this.client.post('/api/users/reactions', params).then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a, _b, _c; + var _d; + var _this = this; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + _b = (_a = Object).assign; + _c = [res]; + _d = {}; + return [4, Promise.all(res.data.map(function (fav) { return _this.noteWithMentions(fav.note, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, _b.apply(_a, _c.concat([(_d.data = _e.sent(), + _d)]))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.subscribeAccount = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.unsubscribeAccount = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getAccountFollowers = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + userId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + return [2, this.client.post('/api/users/followers', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return _this.converter.follower(f); }) + }); + })]; + }); + }); + }; + Misskey.prototype.getAccountFollowing = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + userId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + } + return [2, this.client.post('/api/users/following', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return _this.converter.following(f); }) + }); + })]; + }); + }); + }; + Misskey.prototype.getAccountLists = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getIdentityProof = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.followAccount = function (id, _options) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/following/create', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.unfollowAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/following/delete', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.blockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/blocking/create', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.unblockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/blocking/delete', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.muteAccount = function (id, _notifications) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/mute/create', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.unmuteAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/mute/delete', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.pinAccount = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.unpinAccount = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getRelationship = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + }); + }); + }; + Misskey.prototype.getRelationships = function (ids) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, Promise.all(ids.map(function (id) { return _this.getRelationship(id); })).then(function (results) { return (__assign(__assign({}, results[0]), { data: results.map(function (r) { return r.data; }) })); })]; + }); + }); + }; + Misskey.prototype.searchAccount = function (q, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + query: q, + detail: true + }; + if (options) { + if (options.resolve !== undefined) { + params = Object.assign(params, { + localOnly: options.resolve + }); + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + return [2, this.client.post('/api/users/search', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (u) { return _this.converter.userDetail(u, _this.baseUrlToHost(_this.baseUrl)); }) + }); + })]; + }); + }); + }; + Misskey.prototype.getBookmarks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + return [2, this.client.post('/api/i/favorites', params).then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a, _b, _c; + var _d; + var _this = this; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + _b = (_a = Object).assign; + _c = [res]; + _d = {}; + return [4, Promise.all(res.data.map(function (s) { return _this.noteWithMentions(s.note, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, _b.apply(_a, _c.concat([(_d.data = _e.sent(), + _d)]))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getFavourites = function (options) { + return __awaiter(this, void 0, void 0, function () { + var userId; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/i').then(function (res) { return res.data.id; })]; + case 1: + userId = _a.sent(); + return [2, this.getAccountFavourites(userId, options)]; + } + }); + }); + }; + Misskey.prototype.getMutes = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + return [2, this.client.post('/api/mute/list', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (mute) { return _this.converter.userDetail(mute.mutee, _this.baseUrlToHost(_this.baseUrl)); }) + }); + })]; + }); + }); + }; + Misskey.prototype.getBlocks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 40 + }); + } + return [2, this.client.post('/api/blocking/list', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (blocking) { return _this.converter.userDetail(blocking.blockee, _this.baseUrlToHost(_this.baseUrl)); }) + }); + })]; + }); + }); + }; + Misskey.prototype.getDomainBlocks = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.blockDomain = function (_domain) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.unblockDomain = function (_domain) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getFilters = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getFilter = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.createFilter = function (_phrase, _context, _options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.updateFilter = function (_id, _phrase, _context, _options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.deleteFilter = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.report = function (account_id, comment, _options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/report-abuse', { + userId: account_id, + comment: comment + }) + .then(function (res) { + return Object.assign(res, { + data: { + id: '', + action_taken: '', + comment: comment, + account_id: account_id, + status_ids: [] + } + }); + })]; + }); + }); + }; + Misskey.prototype.getFollowRequests = function (_limit) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client.post('/api/following/requests/list').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (r) { return _this.converter.user(r.follower); }) + }); + })]; + }); + }); + }; + Misskey.prototype.acceptFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/following/requests/accept', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.rejectFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/following/requests/reject', { + userId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/users/relation', { + userId: id + }) + .then(function (res) { + return Object.assign(res, { + data: _this.converter.relation(res.data) + }); + })]; + } + }); + }); + }; + Misskey.prototype.getEndorsements = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getFeaturedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.getAccountFeaturedTags()]; + }); + }); + }; + Misskey.prototype.getAccountFeaturedTags = function () { + return __awaiter(this, void 0, void 0, function () { + var tags, res; + return __generator(this, function (_a) { + tags = []; + res = { + headers: undefined, + statusText: "", + status: 200, + data: tags + }; + return [2, new Promise(function (resolve) { return resolve(res); })]; + }); + }); + }; + Misskey.prototype.createFeaturedTag = function (_name) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.deleteFeaturedTag = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getSuggestedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getPreferences = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client.post('/api/i').then(function (res) { + return Object.assign(res, { + data: _this.converter.userPreferences(res.data, { defaultNoteVisibility: "followers", tutorial: -1 }) + }); + })]; + }); + }); + }; + Misskey.prototype.getSuggestions = function (limit) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (limit) { + params = Object.assign(params, { + limit: limit + }); + } + return [2, this.client + .post('/api/users/recommendation', params) + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (u) { return _this.converter.userDetail(u, _this.baseUrlToHost(_this.baseUrl)); }) })); })]; + }); + }); + }; + Misskey.prototype.getFollowedTags = function () { + return __awaiter(this, void 0, void 0, function () { + var tags, res; + return __generator(this, function (_a) { + tags = []; + res = { + headers: undefined, + statusText: "", + status: 200, + data: tags + }; + return [2, new Promise(function (resolve) { return resolve(res); })]; + }); + }); + }; + Misskey.prototype.getTag = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.followTag = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.unfollowTag = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.postStatus = function (status, options) { + return __awaiter(this, void 0, void 0, function () { + var params, pollParam; + var _this = this; + return __generator(this, function (_a) { + params = { + text: status + }; + if (options) { + if (options.media_ids) { + params = Object.assign(params, { + fileIds: options.media_ids + }); + } + if (options.poll) { + pollParam = { + choices: options.poll.options, + expiresAt: null, + expiredAfter: options.poll.expires_in + }; + if (options.poll.multiple !== undefined) { + pollParam = Object.assign(pollParam, { + multiple: options.poll.multiple + }); + } + params = Object.assign(params, { + poll: pollParam + }); + } + if (options.in_reply_to_id) { + params = Object.assign(params, { + replyId: options.in_reply_to_id + }); + } + if (options.sensitive) { + params = Object.assign(params, { + cw: '' + }); + } + if (options.spoiler_text) { + params = Object.assign(params, { + cw: options.spoiler_text + }); + } + if (options.visibility) { + params = Object.assign(params, { + visibility: this.converter.encodeVisibility(options.visibility) + }); + } + if (options.quote_id) { + params = Object.assign(params, { + renoteId: options.quote_id + }); + } + } + return [2, this.client + .post('/api/notes/create', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getFreshAccountCache = function () { + return { + locks: new async_lock_1.default(), + accounts: [] + }; + }; + Misskey.prototype.noteWithMentions = function (n, host, cache) { + return __awaiter(this, void 0, void 0, function () { + var status; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.converter.note(n, host)]; + case 1: + status = _a.sent(); + return [2, status.mentions.length === 0 ? this.addMentionsToStatus(status, cache) : status]; + } + }); + }); + }; + Misskey.prototype.addMentionsToStatus = function (status, cache) { + return __awaiter(this, void 0, void 0, function () { + var _a, _b, _c, m; + var e_1, _d; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + _a = status; + return [4, this.getMentions(status.plain_content, cache)]; + case 1: + _a.mentions = (_e.sent()).filter(function (p) { return p != null; }); + try { + for (_b = __values(status.mentions.filter(function (value, index, array) { return array.indexOf(value) === index; })), _c = _b.next(); !_c.done; _c = _b.next()) { + m = _c.value; + status.content = status.content.replace("@".concat(m.acct), "@").concat(m.acct, "")); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_d = _b.return)) _d.call(_b); + } + finally { if (e_1) throw e_1.error; } + } + return [2, status]; + } + }); + }); + }; + Misskey.prototype.getMentions = function (text, cache) { + return __awaiter(this, void 0, void 0, function () { + var mentions, mentionMatch, mentionMatch_1, mentionMatch_1_1, m, account, e_2_1; + var e_2, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + mentions = []; + mentionMatch = text.matchAll(/(?<=^|\s)@(?.*?)(?:@(?.*?)|)(?=\s|$)/g); + _b.label = 1; + case 1: + _b.trys.push([1, 6, 7, 8]); + mentionMatch_1 = __values(mentionMatch), mentionMatch_1_1 = mentionMatch_1.next(); + _b.label = 2; + case 2: + if (!!mentionMatch_1_1.done) return [3, 5]; + m = mentionMatch_1_1.value; + if (m.groups == null) + return [3, 4]; + return [4, this.getAccountByNameCached(m.groups.user, m.groups.host, cache)]; + case 3: + account = _b.sent(); + if (account == null) + return [3, 4]; + mentions.push({ + id: account.id, + url: account.url, + username: account.username, + acct: account.acct + }); + _b.label = 4; + case 4: + mentionMatch_1_1 = mentionMatch_1.next(); + return [3, 2]; + case 5: return [3, 8]; + case 6: + e_2_1 = _b.sent(); + e_2 = { error: e_2_1 }; + return [3, 8]; + case 7: + try { + if (mentionMatch_1_1 && !mentionMatch_1_1.done && (_a = mentionMatch_1.return)) _a.call(mentionMatch_1); + } + finally { if (e_2) throw e_2.error; } + return [7]; + case 8: return [2, mentions]; + } + }); + }); + }; + Misskey.prototype.getAccountByNameCached = function (user, host, cache) { + return __awaiter(this, void 0, void 0, function () { + var acctToFind; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + acctToFind = host == null ? user : "".concat(user, "@").concat(host); + return [4, cache.locks.acquire(acctToFind, function () { return __awaiter(_this, void 0, void 0, function () { + var cacheHit, account, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + cacheHit = cache.accounts.find(function (p) { return p.acct === acctToFind; }); + if (!(cacheHit !== null && cacheHit !== void 0)) return [3, 1]; + _a = cacheHit; + return [3, 3]; + case 1: return [4, this.getAccountByName(user, host !== null && host !== void 0 ? host : null)]; + case 2: + _a = (_b.sent()).data; + _b.label = 3; + case 3: + account = _a; + if (!account) { + return [2, null]; + } + if (cacheHit == null) { + cache.accounts.push(account); + } + return [2, account]; + } + }); + }); })]; + case 1: return [2, _a.sent()]; + } + }); + }); + }; + Misskey.prototype.editStatus = function (_id, _options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.deleteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/notes/delete', { + noteId: id + })]; + }); + }); + }; + Misskey.prototype.getStatusContext = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + noteId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit, + depth: 12 + }); + } + else { + params = Object.assign(params, { + limit: 30, + depth: 12 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + } + else { + params = Object.assign(params, { + limit: 30, + depth: 12 + }); + } + return [2, this.client.post('/api/notes/children', params).then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var accountCache, conversation, parents, context, _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + accountCache = this.getFreshAccountCache(); + return [4, this.client.post('/api/notes/conversation', params)]; + case 1: + conversation = _c.sent(); + return [4, Promise.all(conversation.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 2: + parents = _c.sent(); + _b = { + ancestors: parents.reverse() + }; + _a = this.dfs; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 3: + context = (_b.descendants = _a.apply(this, [_c.sent()]), + _b); + return [2, __assign(__assign({}, res), { data: context })]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.dfs = function (graph) { + if (graph.length <= 1) { + return graph; + } + graph = graph.sort(function (a, b) { + if (a.id < b.id) + return -1; + if (a.id > b.id) + return 1; + return 0; + }); + var initialPostId = graph[0].in_reply_to_id; + var stack = graph.filter(function (reply) { return reply.in_reply_to_id === initialPostId; }).reverse(); + var visited = new Set(); + var result = []; + var _loop_1 = function () { + var e_3, _a; + var currentPost = stack.pop(); + if (currentPost === undefined) + return { value: result }; + if (!visited.has(currentPost)) { + visited.add(currentPost); + result.push(currentPost); + try { + for (var _b = (e_3 = void 0, __values(graph.filter(function (reply) { return reply.in_reply_to_id === currentPost.id; }).reverse())), _c = _b.next(); !_c.done; _c = _b.next()) { + var reply = _c.value; + stack.push(reply); + } + } + catch (e_3_1) { e_3 = { error: e_3_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) _a.call(_b); + } + finally { if (e_3) throw e_3.error; } + } + } + }; + while (stack.length) { + var state_1 = _loop_1(); + if (typeof state_1 === "object") + return state_1.value; + } + return result; + }; + Misskey.prototype.getStatusHistory = function () { + return __awaiter(this, void 0, void 0, function () { + var history, res; + return __generator(this, function (_a) { + history = []; + res = { + headers: undefined, + statusText: "", + status: 200, + data: history + }; + return [2, new Promise(function (resolve) { return resolve(res); })]; + }); + }); + }; + Misskey.prototype.getStatusRebloggedBy = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/notes/renotes', { + noteId: id + }) + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (n) { return _this.converter.user(n.user); }) })); })]; + }); + }); + }; + Misskey.prototype.getStatusFavouritedBy = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.favouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _a, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = this.createEmojiReaction; + _b = [id]; + return [4, this.getDefaultFavoriteEmoji()]; + case 1: return [2, _a.apply(this, _b.concat([_c.sent()]))]; + } + }); + }); + }; + Misskey.prototype.getDefaultFavoriteEmoji = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client + .post('/api/i/registry/get-unsecure', { + key: 'reactions', + scope: ['client', 'base'], + }) + .then(function (res) { var _a; return (_a = res.data[0]) !== null && _a !== void 0 ? _a : '⭐'; })]; + case 1: return [2, _a.sent()]; + } + }); + }); + }; + Misskey.prototype.unfavouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.deleteEmojiReaction(id, '')]; + }); + }); + }; + Misskey.prototype.reblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/notes/create', { + renoteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.unreblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/notes/unrenote', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.bookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/notes/favorites/create', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.unbookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/notes/favorites/delete', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.muteStatus = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.unmuteStatus = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.pinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/i/pin', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.unpinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/i/unpin', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.uploadMedia = function (file, _options) { + return __awaiter(this, void 0, void 0, function () { + var formData, headers; + var _this = this; + return __generator(this, function (_a) { + formData = new form_data_1.default(); + formData.append('file', node_fs_1.default.createReadStream(file.path), { + contentType: file.mimetype, + filename: file.originalname, + }); + headers = {}; + if (typeof formData.getHeaders === 'function') { + headers = formData.getHeaders(); + } + return [2, this.client + .post('/api/drive/files/create', formData, headers) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.file(res.data) })); })]; + }); + }); + }; + Misskey.prototype.getMedia = function (id) { + return __awaiter(this, void 0, void 0, function () { + var res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/drive/files/show', { fileId: id })]; + case 1: + res = _a.sent(); + return [2, __assign(__assign({}, res), { data: this.converter.file(res.data) })]; + } + }); + }); + }; + Misskey.prototype.updateMedia = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + fileId: id + }; + if (options) { + if (options.is_sensitive !== undefined) { + params = Object.assign(params, { + isSensitive: options.is_sensitive + }); + } + } + return [2, this.client + .post('/api/drive/files/update', params) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.file(res.data) })); })]; + }); + }); + }; + Misskey.prototype.getPoll = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.votePoll = function (_id, choices, status_id) { + return __awaiter(this, void 0, void 0, function () { + var params, res; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!status_id) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.ArgumentError('status_id is required'); + reject(err); + })]; + } + params = { + noteId: status_id, + choice: choices[0] + }; + return [4, this.client.post('/api/notes/polls/vote', params)]; + case 1: + _a.sent(); + return [4, this.client + .post('/api/notes/show', { + noteId: status_id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var note; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: + note = _a.sent(); + return [2, __assign(__assign({}, res), { data: note.poll })]; + } + }); + }); })]; + case 2: + res = _a.sent(); + if (!res.data) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.UnexpectedError('poll does not exist'); + reject(err); + })]; + } + return [2, __assign(__assign({}, res), { data: res.data })]; + } + }); + }); + }; + Misskey.prototype.getScheduledStatuses = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getScheduledStatus = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.scheduleStatus = function (_id, _scheduled_at) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.cancelScheduledStatus = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getPublicTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = {}; + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }); + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/global-timeline', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getLocalTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = {}; + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }); + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/local-timeline', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getTagTimeline = function (hashtag, options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = { + tag: hashtag + }; + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }); + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/search-by-tag', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getHomeTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = { + withFiles: false + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/timeline', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getListTimeline = function (list_id, options) { + return __awaiter(this, void 0, void 0, function () { + var accountCache, params; + var _this = this; + return __generator(this, function (_a) { + accountCache = this.getFreshAccountCache(); + params = { + listId: list_id, + withFiles: false + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/user-list-timeline', params) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + }); + }); + }; + Misskey.prototype.getConversationTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = { + visibility: 'specified' + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/notes/mentions', params) + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (n) { return _this.converter.noteToConversation(n, _this.baseUrlToHost(_this.baseUrl)); }) })); })]; + }); + }); + }; + Misskey.prototype.deleteConversation = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.readConversation = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getLists = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/lists/list') + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (l) { return _this.converter.list(l); }) })); })]; + }); + }); + }; + Misskey.prototype.getList = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/lists/show', { + listId: id + }) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.list(res.data) })); })]; + }); + }); + }; + Misskey.prototype.createList = function (title) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/lists/create', { + name: title + }) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.list(res.data) })); })]; + }); + }); + }; + Misskey.prototype.updateList = function (id, title) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/users/lists/update', { + listId: id, + name: title + }) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.list(res.data) })); })]; + }); + }); + }; + Misskey.prototype.deleteList = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/users/lists/delete', { + listId: id + })]; + }); + }); + }; + Misskey.prototype.getAccountsInList = function (id, _options) { + return __awaiter(this, void 0, void 0, function () { + var res, promise, accounts; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/users/lists/show', { + listId: id + })]; + case 1: + res = _a.sent(); + promise = res.data.userIds.map(function (userId) { return _this.getAccount(userId); }); + return [4, Promise.all(promise)]; + case 2: + accounts = _a.sent(); + return [2, __assign(__assign({}, res), { data: accounts.map(function (r) { return r.data; }) })]; + } + }); + }); + }; + Misskey.prototype.addAccountsToList = function (id, account_ids) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/users/lists/push', { + listId: id, + userId: account_ids[0] + })]; + }); + }); + }; + Misskey.prototype.deleteAccountsFromList = function (id, account_ids) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/users/lists/pull', { + listId: id, + userId: account_ids[0] + })]; + }); + }); + }; + Misskey.prototype.getMarkers = function (_timeline) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.saveMarkers = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getNotifications = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + if (options.exclude_type) { + params = Object.assign(params, { + excludeType: options.exclude_type.map(function (e) { return _this.converter.encodeNotificationType(e); }) + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + return [2, this.client + .post('/api/i/notifications', params) + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (n) { return _this.converter.notification(n, _this.baseUrlToHost(_this.baseUrl)); }) })); })]; + }); + }); + }; + Misskey.prototype.getNotification = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.dismissNotifications = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/notifications/mark-all-as-read')]; + }); + }); + }; + Misskey.prototype.dismissNotification = function (_id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.readNotifications = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('mastodon does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.subscribePushNotification = function (_subscription, _data) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getPushSubscription = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.updatePushSubscription = function (_data) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.deletePushSubscription = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.search = function (q, type, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function () { + var accountCache, _c, params, match, lookupQuery, result, _d, params, params; + var _this = this; + return __generator(this, function (_e) { + switch (_e.label) { + case 0: + accountCache = this.getFreshAccountCache(); + _c = type; + switch (_c) { + case 'accounts': return [3, 1]; + case 'statuses': return [3, 7]; + case 'hashtags': return [3, 8]; + } + return [3, 9]; + case 1: + params = { + query: q + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }); + } + if (options.resolve) { + params = Object.assign(params, { + localOnly: options.resolve + }); + } + } + else { + params = Object.assign(params, { + limit: 20 + }); + } + _e.label = 2; + case 2: + _e.trys.push([2, 5, , 6]); + match = q.match(/^@(?.*?)(?:@(?.*?)|)$/); + if (!match) return [3, 4]; + lookupQuery = { + username: (_a = match.groups) === null || _a === void 0 ? void 0 : _a.user, + host: (_b = match.groups) === null || _b === void 0 ? void 0 : _b.host + }; + return [4, this.client.post('/api/users/show', lookupQuery).then(function (res) { return (__assign(__assign({}, res), { data: { + accounts: [_this.converter.userDetail(res.data, _this.baseUrlToHost(_this.baseUrl))], + statuses: [], + hashtags: [] + } })); })]; + case 3: + result = _e.sent(); + if (result.status !== 200) { + result.status = 200; + result.statusText = "OK"; + result.data = { + accounts: [], + statuses: [], + hashtags: [] + }; + } + return [2, result]; + case 4: return [3, 6]; + case 5: + _d = _e.sent(); + return [3, 6]; + case 6: return [2, this.client.post('/api/users/search', params).then(function (res) { return (__assign(__assign({}, res), { data: { + accounts: res.data.map(function (u) { return _this.converter.userDetail(u, _this.baseUrlToHost(_this.baseUrl)); }), + statuses: [], + hashtags: [] + } })); })]; + case 7: + { + params = { + query: q + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }); + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }); + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }); + } + if (options.account_id) { + params = Object.assign(params, { + userId: options.account_id + }); + } + } + return [2, this.client.post('/api/notes/search', params).then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b, _c; + var _this = this; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + _c = { + accounts: [] + }; + return [4, Promise.all(res.data.map(function (n) { return _this.noteWithMentions(n, _this.baseUrlToHost(_this.baseUrl), accountCache); }))]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = (_c.statuses = _d.sent(), + _c.hashtags = [], + _c), _b)])))]; + } + }); + }); })]; + } + _e.label = 8; + case 8: + { + params = { + query: q + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }); + } + } + return [2, this.client.post('/api/hashtags/search', params).then(function (res) { return (__assign(__assign({}, res), { data: { + accounts: [], + statuses: [], + hashtags: res.data.map(function (h) { return ({ name: h, url: h, history: null, following: false }); }) + } })); })]; + } + _e.label = 9; + case 9: return [2]; + } + }); + }); + }; + Misskey.prototype.getInstance = function () { + return __awaiter(this, void 0, void 0, function () { + var meta; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/meta').then(function (res) { return res.data; })]; + case 1: + meta = _a.sent(); + return [2, this.client + .post('/api/stats') + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.meta(meta, res.data) })); })]; + } + }); + }); + }; + Misskey.prototype.getInstancePeers = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getInstanceActivity = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getInstanceTrends = function (_limit) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/hashtags/trend') + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (h) { return _this.converter.hashtag(h); }) })); })]; + }); + }); + }; + Misskey.prototype.getInstanceDirectory = function (_options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.getInstanceCustomEmojis = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/meta') + .then(function (res) { return (__assign(__assign({}, res), { data: res.data.emojis.map(function (e) { return _this.converter.emoji(e); }) })); })]; + }); + }); + }; + Misskey.prototype.getInstanceAnnouncements = function (with_dismissed) { + return __awaiter(this, void 0, void 0, function () { + var params; + var _this = this; + return __generator(this, function (_a) { + params = {}; + if (with_dismissed) { + params = Object.assign(params, { + withUnreads: with_dismissed + }); + } + return [2, this.client.post('/api/announcements', params).then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (t) { return _this.converter.announcement(t); }) })); })]; + }); + }); + }; + Misskey.prototype.dismissInstanceAnnouncement = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/api/i/read-announcement', { announcementId: id })]; + }); + }); + }; + Misskey.prototype.createEmojiReaction = function (id, emoji) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/notes/reactions/create', { + noteId: id, + reaction: emoji + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.deleteEmojiReaction = function (id, _emoji) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.post('/api/notes/reactions/delete', { + noteId: id + })]; + case 1: + _a.sent(); + return [2, this.client + .post('/api/notes/show', { + noteId: id + }) + .then(function (res) { return __awaiter(_this, void 0, void 0, function () { + var _a; + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _a = [__assign({}, res)]; + _b = {}; + return [4, this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())]; + case 1: return [2, (__assign.apply(void 0, _a.concat([(_b.data = _c.sent(), _b)])))]; + } + }); + }); })]; + } + }); + }); + }; + Misskey.prototype.getEmojiReactions = function (id) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2, this.client + .post('/api/notes/reactions', { + noteId: id + }) + .then(function (res) { return (__assign(__assign({}, res), { data: _this.converter.reactions(res.data) })); })]; + }); + }); + }; + Misskey.prototype.getEmojiReaction = function (_id, _emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.NoImplementedError('misskey does not support'); + reject(err); + })]; + }); + }); + }; + Misskey.prototype.userSocket = function () { + return this.client.socket('user'); + }; + Misskey.prototype.publicSocket = function () { + return this.client.socket('globalTimeline'); + }; + Misskey.prototype.localSocket = function () { + return this.client.socket('localTimeline'); + }; + Misskey.prototype.tagSocket = function (_tag) { + throw new megalodon_1.NoImplementedError('TODO: implement'); + }; + Misskey.prototype.listSocket = function (list_id) { + return this.client.socket('list', list_id); + }; + Misskey.prototype.directSocket = function () { + return this.client.socket('conversation'); + }; + return Misskey; +}()); +exports.default = Misskey; diff --git a/packages/megalodon/lib/src/misskey/api_client.d.ts b/packages/megalodon/lib/src/misskey/api_client.d.ts new file mode 100644 index 000000000..71d17e23c --- /dev/null +++ b/packages/megalodon/lib/src/misskey/api_client.d.ts @@ -0,0 +1,103 @@ +import { ProxyConfig } from '../proxy_config'; +import Response from '../response'; +import MisskeyEntity from './entity'; +import MegalodonEntity from '../entity'; +import WebSocket from './web_socket'; +import NotificationType from '../notification'; +declare namespace MisskeyAPI { + namespace Entity { + type App = MisskeyEntity.App; + type Announcement = MisskeyEntity.Announcement; + type Blocking = MisskeyEntity.Blocking; + type Choice = MisskeyEntity.Choice; + type CreatedNote = MisskeyEntity.CreatedNote; + type Emoji = MisskeyEntity.Emoji; + type Favorite = MisskeyEntity.Favorite; + type Field = MisskeyEntity.Field; + type File = MisskeyEntity.File; + type Follower = MisskeyEntity.Follower; + type Following = MisskeyEntity.Following; + type FollowRequest = MisskeyEntity.FollowRequest; + type Hashtag = MisskeyEntity.Hashtag; + type List = MisskeyEntity.List; + type Meta = MisskeyEntity.Meta; + type Mute = MisskeyEntity.Mute; + type Note = MisskeyEntity.Note; + type Notification = MisskeyEntity.Notification; + type Poll = MisskeyEntity.Poll; + type Reaction = MisskeyEntity.Reaction; + type Relation = MisskeyEntity.Relation; + type User = MisskeyEntity.User; + type UserDetail = MisskeyEntity.UserDetail; + type UserDetailMe = MisskeyEntity.UserDetailMe; + type GetAll = MisskeyEntity.GetAll; + type UserKey = MisskeyEntity.UserKey; + type Session = MisskeyEntity.Session; + type Stats = MisskeyEntity.Stats; + type APIEmoji = { + emojis: Emoji[]; + }; + } + class Converter { + private baseUrl; + private instanceHost; + private plcUrl; + private modelOfAcct; + constructor(baseUrl: string); + escapeMFM: (text: string) => string; + emoji: (e: Entity.Emoji) => MegalodonEntity.Emoji; + field: (f: Entity.Field) => MegalodonEntity.Field; + user: (u: Entity.User) => MegalodonEntity.Account; + userDetail: (u: Entity.UserDetail, host: string) => MegalodonEntity.Account; + userPreferences: (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll) => MegalodonEntity.Preferences; + visibility: (v: 'public' | 'home' | 'followers' | 'specified') => 'public' | 'unlisted' | 'private' | 'direct'; + encodeVisibility: (v: 'public' | 'unlisted' | 'private' | 'direct') => 'public' | 'home' | 'followers' | 'specified'; + fileType: (s: string) => 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + file: (f: Entity.File) => MegalodonEntity.Attachment; + follower: (f: Entity.Follower) => MegalodonEntity.Account; + following: (f: Entity.Following) => MegalodonEntity.Account; + relation: (r: Entity.Relation) => MegalodonEntity.Relationship; + choice: (c: Entity.Choice) => MegalodonEntity.PollOption; + poll: (p: Entity.Poll) => MegalodonEntity.Poll; + note: (n: Entity.Note, host: string) => MegalodonEntity.Status; + mapReactions: (r: { + [key: string]: number; + }, myReaction?: string) => Array; + getTotalReactions: (r: { + [key: string]: number; + }) => number; + reactions: (r: Array) => Array; + noteToConversation: (n: Entity.Note, host: string) => MegalodonEntity.Conversation; + list: (l: Entity.List) => MegalodonEntity.List; + encodeNotificationType: (e: MegalodonEntity.NotificationType) => MisskeyEntity.NotificationType; + decodeNotificationType: (e: MisskeyEntity.NotificationType) => MegalodonEntity.NotificationType; + announcement: (a: Entity.Announcement) => MegalodonEntity.Announcement; + notification: (n: Entity.Notification, host: string) => MegalodonEntity.Notification; + stats: (s: Entity.Stats) => MegalodonEntity.Stats; + meta: (m: Entity.Meta, s: Entity.Stats) => MegalodonEntity.Instance; + hashtag: (h: Entity.Hashtag) => MegalodonEntity.Tag; + } + const DEFAULT_SCOPE: string[]; + interface Interface { + post(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', listId?: string): WebSocket; + } + class Client implements Interface { + private accessToken; + private baseUrl; + private userAgent; + private abortController; + private proxyConfig; + private converter; + constructor(baseUrl: string, accessToken: string | null, userAgent: string | undefined, proxyConfig: false | ProxyConfig | undefined, converter: Converter); + post(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', listId?: string): WebSocket; + } +} +export default MisskeyAPI; diff --git a/packages/megalodon/lib/src/misskey/api_client.js b/packages/megalodon/lib/src/misskey/api_client.js new file mode 100644 index 000000000..d08be592a --- /dev/null +++ b/packages/megalodon/lib/src/misskey/api_client.js @@ -0,0 +1,597 @@ +"use strict"; +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 __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."); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var axios_1 = __importDefault(require("axios")); +var dayjs_1 = __importDefault(require("dayjs")); +var form_data_1 = __importDefault(require("form-data")); +var default_1 = require("../default"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var web_socket_1 = __importDefault(require("./web_socket")); +var notification_1 = __importDefault(require("./notification")); +var notification_2 = __importDefault(require("../notification")); +var MisskeyAPI; +(function (MisskeyAPI) { + var Converter = (function () { + function Converter(baseUrl) { + var _this = this; + this.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: 'plc', + avatar: 'plc', + avatar_static: 'plc', + header: 'plc', + header_static: 'plc', + followers_count: -1, + following_count: 0, + statuses_count: 0, + last_status_at: '1971-01-01T00:00:00.000Z', + noindex: true, + emojis: [], + fields: [], + moved: null + }; + this.escapeMFM = function (text) { return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/`/g, '`') + .replace(/\r?\n/g, '
'); }; + this.emoji = function (e) { + return { + shortcode: e.name, + static_url: e.url, + url: e.url, + visible_in_picker: true, + category: e.category + }; + }; + this.field = function (f) { return ({ + name: f.name, + value: _this.escapeMFM(f.value), + verified_at: null + }); }; + this.user = function (u) { + var acct = u.username; + var acctUrl = "https://".concat(u.host || _this.instanceHost, "/@").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: _this.plcUrl, + header_static: _this.plcUrl, + emojis: u.emojis.map(function (e) { return _this.emoji(e); }), + moved: null, + fields: [], + bot: false + }; + }; + this.userDetail = function (u, host) { + var _a, _b; + var acct = u.username; + host = host.replace('https://', ''); + var acctUrl = "https://".concat(host || u.host || _this.instanceHost, "/@").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, + locked: u.isLocked, + created_at: u.createdAt, + followers_count: u.followersCount, + following_count: u.followingCount, + statuses_count: u.notesCount, + note: u.description, + url: acctUrl, + avatar: u.avatarUrl, + avatar_static: u.avatarUrl, + header: (_a = u.bannerUrl) !== null && _a !== void 0 ? _a : _this.plcUrl, + header_static: (_b = u.bannerUrl) !== null && _b !== void 0 ? _b : _this.plcUrl, + emojis: u.emojis.map(function (e) { return _this.emoji(e); }), + moved: null, + fields: u.fields.map(function (f) { return _this.field(f); }), + bot: u.isBot, + }; + }; + this.userPreferences = function (u, g) { + return { + "reading:expand:media": "default", + "reading:expand:spoilers": false, + "posting:default:language": u.lang, + "posting:default:sensitive": u.alwaysMarkNsfw, + "posting:default:visibility": _this.visibility(g.defaultNoteVisibility) + }; + }; + this.visibility = function (v) { + switch (v) { + case 'public': + return v; + case 'home': + return 'unlisted'; + case 'followers': + return 'private'; + case 'specified': + return 'direct'; + } + }; + this.encodeVisibility = function (v) { + switch (v) { + case 'public': + return v; + case 'unlisted': + return 'home'; + case 'private': + return 'followers'; + case 'direct': + return 'specified'; + } + }; + this.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'; + }; + this.file = function (f) { + return { + id: f.id, + type: _this.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: f.comment, + blurhash: f.blurhash + }; + }; + this.follower = function (f) { + return _this.user(f.follower); + }; + this.following = function (f) { + return _this.user(f.followee); + }; + this.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 + }; + }; + this.choice = function (c) { + return { + title: c.text, + votes_count: c.votes + }; + }; + this.poll = function (p) { + var now = (0, dayjs_1.default)(); + var expire = (0, dayjs_1.default)(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 _this.choice(c); }), + voted: p.choices.some(function (c) { return c.isVoted; }) + }; + }; + this.note = function (n, host) { + var _a, _b; + host = host.replace('https://', ''); + 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: _this.user(n.user), + in_reply_to_id: n.replyId, + in_reply_to_account_id: (_b = (_a = n.reply) === null || _a === void 0 ? void 0 : _a.userId) !== null && _b !== void 0 ? _b : null, + reblog: n.renote ? _this.note(n.renote, host) : null, + content: n.text ? _this.escapeMFM(n.text) : '', + plain_content: n.text ? n.text : null, + created_at: n.createdAt, + emojis: n.emojis.map(function (e) { return _this.emoji(e); }), + replies_count: n.repliesCount, + reblogs_count: n.renoteCount, + favourites_count: _this.getTotalReactions(n.reactions), + 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: _this.visibility(n.visibility), + media_attachments: n.files ? n.files.map(function (f) { return _this.file(f); }) : [], + mentions: [], + tags: [], + card: null, + poll: n.poll ? _this.poll(n.poll) : null, + application: null, + language: null, + pinned: null, + emoji_reactions: _this.mapReactions(n.reactions, n.myReaction), + bookmarked: false, + quote: n.renote && n.text ? _this.note(n.renote, host) : null + }; + }; + this.mapReactions = function (r, myReaction) { + return Object.keys(r).map(function (key) { + if (myReaction && key === myReaction) { + return { + count: r[key], + me: true, + name: key + }; + } + return { + count: r[key], + me: false, + name: key + }; + }); + }; + this.getTotalReactions = function (r) { + return Object.values(r).length > 0 ? Object.values(r).reduce(function (previousValue, currentValue) { return previousValue + currentValue; }) : 0; + }; + this.reactions = function (r) { + var e_1, _a; + var result = []; + var _loop_1 = function (e) { + 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: e.type + }); + } + }; + 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; + }; + this.noteToConversation = function (n, host) { + var accounts = [_this.user(n.user)]; + if (n.reply) { + accounts.push(_this.user(n.reply.user)); + } + return { + id: n.id, + accounts: accounts, + last_status: _this.note(n, host), + unread: false + }; + }; + this.list = function (l) { return ({ + id: l.id, + title: l.name + }); }; + this.encodeNotificationType = function (e) { + switch (e) { + case notification_2.default.Follow: + return notification_1.default.Follow; + case notification_2.default.Mention: + return notification_1.default.Reply; + case notification_2.default.Favourite: + case notification_2.default.EmojiReaction: + return notification_1.default.Reaction; + case notification_2.default.Reblog: + return notification_1.default.Renote; + case notification_2.default.PollVote: + return notification_1.default.PollVote; + case notification_2.default.FollowRequest: + return notification_1.default.ReceiveFollowRequest; + default: + return e; + } + }; + this.decodeNotificationType = function (e) { + switch (e) { + case notification_1.default.Follow: + return notification_2.default.Follow; + case notification_1.default.Mention: + case notification_1.default.Reply: + return notification_2.default.Mention; + case notification_1.default.Renote: + case notification_1.default.Quote: + return notification_2.default.Reblog; + case notification_1.default.Reaction: + return notification_2.default.EmojiReaction; + case notification_1.default.PollVote: + return notification_2.default.PollVote; + case notification_1.default.ReceiveFollowRequest: + return notification_2.default.FollowRequest; + case notification_1.default.FollowRequestAccepted: + return notification_2.default.Follow; + default: + return e; + } + }; + this.announcement = function (a) { return ({ + id: a.id, + content: "

".concat(_this.escapeMFM(a.title), "

").concat(_this.escapeMFM(a.text)), + starts_at: null, + ends_at: null, + published: true, + all_day: false, + published_at: a.createdAt, + updated_at: a.updatedAt, + read: a.isRead, + mentions: [], + statuses: [], + tags: [], + emojis: [], + reactions: [], + }); }; + this.notification = function (n, host) { + var notification = { + id: n.id, + account: n.user ? _this.user(n.user) : _this.modelOfAcct, + created_at: n.createdAt, + type: _this.decodeNotificationType(n.type) + }; + if (n.note) { + notification = Object.assign(notification, { + status: _this.note(n.note, host) + }); + } + if (n.reaction) { + notification = Object.assign(notification, { + emoji: n.reaction + }); + } + return notification; + }; + this.stats = function (s) { + return { + user_count: s.usersCount, + status_count: s.notesCount, + domain_count: s.instances + }; + }; + this.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: _this.stats(s), + languages: m.langs, + contact_account: null, + max_toot_chars: m.maxNoteTextLength, + registrations: !m.disableRegistration + }; + }; + this.hashtag = function (h) { + return { + name: h.tag, + url: h.tag, + history: null, + following: false + }; + }; + this.baseUrl = baseUrl; + this.instanceHost = baseUrl.substring(baseUrl.indexOf('//') + 2); + this.plcUrl = "".concat(baseUrl, "/static-assets/transparent.png"); + this.modelOfAcct.url = this.plcUrl; + this.modelOfAcct.avatar = this.plcUrl; + this.modelOfAcct.avatar_static = this.plcUrl; + this.modelOfAcct.header = this.plcUrl; + this.modelOfAcct.header_static = this.plcUrl; + } + return Converter; + }()); + MisskeyAPI.Converter = 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, proxyConfig, converter) { + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + this.proxyConfig = false; + this.accessToken = accessToken; + this.baseUrl = baseUrl; + this.userAgent = userAgent; + this.proxyConfig = proxyConfig; + this.abortController = new AbortController(); + this.converter = converter; + axios_1.default.defaults.signal = this.abortController.signal; + } + Client.prototype.post = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options, bodyParams; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + bodyParams = params; + if (this.accessToken) { + if (params instanceof form_data_1.default) { + bodyParams.append('i', this.accessToken); + } + else { + bodyParams = Object.assign(params, { + i: this.accessToken + }); + } + } + console.log("sending request to ".concat(this.baseUrl).concat(path, " with params:")); + console.log(JSON.stringify(bodyParams, null, 2)); + return [2, axios_1.default.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 = "".concat(this.baseUrl, "/streaming"); + var streaming = new web_socket_1.default(url, channel, this.accessToken, listId, this.userAgent, this.proxyConfig, this.converter); + process.nextTick(function () { + streaming.start(); + }); + return streaming; + }; + return Client; + }()); + MisskeyAPI.Client = Client; +})(MisskeyAPI || (MisskeyAPI = {})); +exports.default = MisskeyAPI; diff --git a/packages/megalodon/lib/src/misskey/entities/GetAll.d.ts b/packages/megalodon/lib/src/misskey/entities/GetAll.d.ts new file mode 100644 index 000000000..ee06de068 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/GetAll.d.ts @@ -0,0 +1,6 @@ +declare namespace MisskeyEntity { + type GetAll = { + tutorial: number; + defaultNoteVisibility: 'public' | 'home' | 'followers' | 'specified'; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/GetAll.js b/packages/megalodon/lib/src/misskey/entities/GetAll.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/GetAll.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/accountCache.d.ts b/packages/megalodon/lib/src/misskey/entities/accountCache.d.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/megalodon/lib/src/misskey/entities/accountCache.js b/packages/megalodon/lib/src/misskey/entities/accountCache.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/accountCache.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/announcement.d.ts b/packages/megalodon/lib/src/misskey/entities/announcement.d.ts new file mode 100644 index 000000000..1d922c2f0 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/announcement.d.ts @@ -0,0 +1,10 @@ +declare namespace MisskeyEntity { + type Announcement = { + id: string; + createdAt: string; + updatedAt: string; + text: string; + title: string; + isRead?: boolean; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/announcement.js b/packages/megalodon/lib/src/misskey/entities/announcement.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/announcement.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/app.d.ts b/packages/megalodon/lib/src/misskey/entities/app.d.ts new file mode 100644 index 000000000..244e2f800 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/app.d.ts @@ -0,0 +1,9 @@ +declare namespace MisskeyEntity { + type App = { + id: string; + name: string; + callbackUrl: string; + permission: Array; + secret: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/app.js b/packages/megalodon/lib/src/misskey/entities/app.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/app.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/blocking.d.ts b/packages/megalodon/lib/src/misskey/entities/blocking.d.ts new file mode 100644 index 000000000..c4ac3ca10 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/blocking.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace MisskeyEntity { + type Blocking = { + id: string; + createdAt: string; + blockeeId: string; + blockee: UserDetail; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/blocking.js b/packages/megalodon/lib/src/misskey/entities/blocking.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/blocking.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/createdNote.d.ts b/packages/megalodon/lib/src/misskey/entities/createdNote.d.ts new file mode 100644 index 000000000..42f4d26df --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/createdNote.d.ts @@ -0,0 +1,6 @@ +/// +declare namespace MisskeyEntity { + type CreatedNote = { + createdNote: Note; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/createdNote.js b/packages/megalodon/lib/src/misskey/entities/createdNote.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/createdNote.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/emoji.d.ts b/packages/megalodon/lib/src/misskey/entities/emoji.d.ts new file mode 100644 index 000000000..fd87ce5bf --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/emoji.d.ts @@ -0,0 +1,9 @@ +declare namespace MisskeyEntity { + type Emoji = { + name: string; + host: string | null; + url: string; + aliases: Array; + category: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/emoji.js b/packages/megalodon/lib/src/misskey/entities/emoji.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/emoji.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/favorite.d.ts b/packages/megalodon/lib/src/misskey/entities/favorite.d.ts new file mode 100644 index 000000000..be76f6fce --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/favorite.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace MisskeyEntity { + type Favorite = { + id: string; + createdAt: string; + noteId: string; + note: Note; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/favorite.js b/packages/megalodon/lib/src/misskey/entities/favorite.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/favorite.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/field.d.ts b/packages/megalodon/lib/src/misskey/entities/field.d.ts new file mode 100644 index 000000000..c022c1c01 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/field.d.ts @@ -0,0 +1,6 @@ +declare namespace MisskeyEntity { + type Field = { + name: string; + value: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/field.js b/packages/megalodon/lib/src/misskey/entities/field.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/field.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/file.d.ts b/packages/megalodon/lib/src/misskey/entities/file.d.ts new file mode 100644 index 000000000..f0281daaf --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/file.d.ts @@ -0,0 +1,20 @@ +declare namespace MisskeyEntity { + type File = { + id: string; + createdAt: string; + name: string; + type: string; + md5: string; + size: number; + isSensitive: boolean; + properties: { + width: number; + height: number; + avgColor: string; + }; + url: string; + thumbnailUrl: string; + comment: string; + blurhash: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/file.js b/packages/megalodon/lib/src/misskey/entities/file.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/file.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/followRequest.d.ts b/packages/megalodon/lib/src/misskey/entities/followRequest.d.ts new file mode 100644 index 000000000..f22595c92 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/followRequest.d.ts @@ -0,0 +1,8 @@ +/// +declare namespace MisskeyEntity { + type FollowRequest = { + id: string; + follower: User; + followee: User; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/followRequest.js b/packages/megalodon/lib/src/misskey/entities/followRequest.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/followRequest.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/follower.d.ts b/packages/megalodon/lib/src/misskey/entities/follower.d.ts new file mode 100644 index 000000000..50e11286a --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/follower.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace MisskeyEntity { + type Follower = { + id: string; + createdAt: string; + followeeId: string; + followerId: string; + follower: UserDetail; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/follower.js b/packages/megalodon/lib/src/misskey/entities/follower.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/follower.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/following.d.ts b/packages/megalodon/lib/src/misskey/entities/following.d.ts new file mode 100644 index 000000000..1538a5e2a --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/following.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace MisskeyEntity { + type Following = { + id: string; + createdAt: string; + followeeId: string; + followerId: string; + followee: UserDetail; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/following.js b/packages/megalodon/lib/src/misskey/entities/following.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/following.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/hashtag.d.ts b/packages/megalodon/lib/src/misskey/entities/hashtag.d.ts new file mode 100644 index 000000000..341f7fcb3 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/hashtag.d.ts @@ -0,0 +1,7 @@ +declare namespace MisskeyEntity { + type Hashtag = { + tag: string; + chart: Array; + usersCount: number; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/hashtag.js b/packages/megalodon/lib/src/misskey/entities/hashtag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/hashtag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/list.d.ts b/packages/megalodon/lib/src/misskey/entities/list.d.ts new file mode 100644 index 000000000..076ebf9f8 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/list.d.ts @@ -0,0 +1,8 @@ +declare namespace MisskeyEntity { + type List = { + id: string; + createdAt: string; + name: string; + userIds: Array; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/list.js b/packages/megalodon/lib/src/misskey/entities/list.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/list.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/meta.d.ts b/packages/megalodon/lib/src/misskey/entities/meta.d.ts new file mode 100644 index 000000000..ac1fd6fb9 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/meta.d.ts @@ -0,0 +1,17 @@ +/// +declare namespace MisskeyEntity { + type Meta = { + maintainerName: string; + maintainerEmail: string; + name: string; + version: string; + uri: string; + description: string; + langs: Array; + disableRegistration: boolean; + disableLocalTimeline: boolean; + bannerUrl: string; + maxNoteTextLength: 300; + emojis: Array; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/meta.js b/packages/megalodon/lib/src/misskey/entities/meta.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/meta.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/mute.d.ts b/packages/megalodon/lib/src/misskey/entities/mute.d.ts new file mode 100644 index 000000000..7028a03b5 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/mute.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace MisskeyEntity { + type Mute = { + id: string; + createdAt: string; + muteeId: string; + mutee: UserDetail; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/mute.js b/packages/megalodon/lib/src/misskey/entities/mute.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/mute.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/note.d.ts b/packages/megalodon/lib/src/misskey/entities/note.d.ts new file mode 100644 index 000000000..fe3df8c93 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/note.d.ts @@ -0,0 +1,33 @@ +/// +/// +/// +/// +declare namespace MisskeyEntity { + type Note = { + id: string; + createdAt: string; + userId: string; + user: User; + text: string | null; + cw: string | null; + visibility: 'public' | 'home' | 'followers' | 'specified'; + renoteCount: number; + repliesCount: number; + reactions: { + [key: string]: number; + }; + emojis: Array; + fileIds: Array; + files: Array; + replyId: string | null; + renoteId: string | null; + uri?: string; + reply?: Note; + renote?: Note; + viaMobile?: boolean; + tags?: Array; + poll?: Poll; + mentions?: Array; + myReaction?: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/note.js b/packages/megalodon/lib/src/misskey/entities/note.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/note.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/notification.d.ts b/packages/megalodon/lib/src/misskey/entities/notification.d.ts new file mode 100644 index 000000000..dbb86bff6 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/notification.d.ts @@ -0,0 +1,14 @@ +/// +/// +declare namespace MisskeyEntity { + type Notification = { + id: string; + createdAt: string; + type: NotificationType; + userId: string; + user: User; + note?: Note; + reaction?: string; + }; + type NotificationType = string; +} diff --git a/packages/megalodon/lib/src/misskey/entities/notification.js b/packages/megalodon/lib/src/misskey/entities/notification.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/notification.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/poll.d.ts b/packages/megalodon/lib/src/misskey/entities/poll.d.ts new file mode 100644 index 000000000..22236d532 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/poll.d.ts @@ -0,0 +1,12 @@ +declare namespace MisskeyEntity { + type Choice = { + text: string; + votes: number; + isVoted: boolean; + }; + type Poll = { + multiple: boolean; + expiresAt: string; + choices: Array; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/poll.js b/packages/megalodon/lib/src/misskey/entities/poll.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/poll.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/reaction.d.ts b/packages/megalodon/lib/src/misskey/entities/reaction.d.ts new file mode 100644 index 000000000..df0a10673 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/reaction.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace MisskeyEntity { + type Reaction = { + id: string; + createdAt: string; + user: User; + url?: string; + type: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/reaction.js b/packages/megalodon/lib/src/misskey/entities/reaction.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/reaction.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/relation.d.ts b/packages/megalodon/lib/src/misskey/entities/relation.d.ts new file mode 100644 index 000000000..fce7a86f0 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/relation.d.ts @@ -0,0 +1,12 @@ +declare namespace MisskeyEntity { + type Relation = { + id: string; + isFollowing: boolean; + hasPendingFollowRequestFromYou: boolean; + hasPendingFollowRequestToYou: boolean; + isFollowed: boolean; + isBlocking: boolean; + isBlocked: boolean; + isMuted: boolean; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/relation.js b/packages/megalodon/lib/src/misskey/entities/relation.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/relation.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/session.d.ts b/packages/megalodon/lib/src/misskey/entities/session.d.ts new file mode 100644 index 000000000..7aef59d25 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/session.d.ts @@ -0,0 +1,6 @@ +declare namespace MisskeyEntity { + type Session = { + token: string; + url: string; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/session.js b/packages/megalodon/lib/src/misskey/entities/session.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/session.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/stats.d.ts b/packages/megalodon/lib/src/misskey/entities/stats.d.ts new file mode 100644 index 000000000..43ca65353 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/stats.d.ts @@ -0,0 +1,9 @@ +declare namespace MisskeyEntity { + type Stats = { + notesCount: number; + originalNotesCount: number; + usersCount: number; + originalUsersCount: number; + instances: number; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/stats.js b/packages/megalodon/lib/src/misskey/entities/stats.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/stats.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/user.d.ts b/packages/megalodon/lib/src/misskey/entities/user.d.ts new file mode 100644 index 000000000..3f51d64e3 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/user.d.ts @@ -0,0 +1,12 @@ +/// +declare namespace MisskeyEntity { + type User = { + id: string; + name: string; + username: string; + host: string | null; + avatarUrl: string; + avatarColor: string; + emojis: Array; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/user.js b/packages/megalodon/lib/src/misskey/entities/user.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/user.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/userDetail.d.ts b/packages/megalodon/lib/src/misskey/entities/userDetail.d.ts new file mode 100644 index 000000000..eae2b9a3c --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userDetail.d.ts @@ -0,0 +1,33 @@ +/// +/// +/// +declare namespace MisskeyEntity { + type UserDetail = { + id: string; + name: string; + username: string; + host: string | null; + avatarUrl: string; + avatarColor: string; + isAdmin: boolean; + isModerator: boolean; + isBot: boolean; + isCat: boolean; + emojis: Array; + createdAt: string; + bannerUrl: string; + bannerColor: string; + isLocked: boolean; + isSilenced: boolean; + isSuspended: boolean; + description: string; + followersCount: number; + followingCount: number; + notesCount: number; + avatarId: string; + bannerId: string; + pinnedNoteIds?: Array; + pinnedNotes?: Array; + fields: Array; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/userDetail.js b/packages/megalodon/lib/src/misskey/entities/userDetail.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userDetail.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/userDetailMe.d.ts b/packages/megalodon/lib/src/misskey/entities/userDetailMe.d.ts new file mode 100644 index 000000000..72e9ac604 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userDetailMe.d.ts @@ -0,0 +1,35 @@ +/// +/// +/// +declare namespace MisskeyEntity { + type UserDetailMe = { + id: string; + name: string; + username: string; + host: string | null; + avatarUrl: string; + avatarColor: string; + isAdmin: boolean; + isModerator: boolean; + isBot: boolean; + isCat: boolean; + emojis: Array; + createdAt: string; + bannerUrl: string; + bannerColor: string; + isLocked: boolean; + isSilenced: boolean; + isSuspended: boolean; + description: string; + followersCount: number; + followingCount: number; + notesCount: number; + avatarId: string; + bannerId: string; + pinnedNoteIds?: Array; + pinnedNotes?: Array; + fields: Array; + alwaysMarkNsfw: boolean; + lang: string | null; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/userDetailMe.js b/packages/megalodon/lib/src/misskey/entities/userDetailMe.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userDetailMe.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entities/userkey.d.ts b/packages/megalodon/lib/src/misskey/entities/userkey.d.ts new file mode 100644 index 000000000..a7dfe75c7 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userkey.d.ts @@ -0,0 +1,7 @@ +/// +declare namespace MisskeyEntity { + type UserKey = { + accessToken: string; + user: User; + }; +} diff --git a/packages/megalodon/lib/src/misskey/entities/userkey.js b/packages/megalodon/lib/src/misskey/entities/userkey.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entities/userkey.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/misskey/entity.d.ts b/packages/megalodon/lib/src/misskey/entity.d.ts new file mode 100644 index 000000000..562970387 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entity.d.ts @@ -0,0 +1,27 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +export default MisskeyEntity; diff --git a/packages/megalodon/lib/src/misskey/entity.js b/packages/megalodon/lib/src/misskey/entity.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/entity.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/src/misskey/helpers/accountCache.d.ts b/packages/megalodon/lib/src/misskey/helpers/accountCache.d.ts new file mode 100644 index 000000000..9d35ad9fa --- /dev/null +++ b/packages/megalodon/lib/src/misskey/helpers/accountCache.d.ts @@ -0,0 +1,2 @@ +/// +export {}; diff --git a/packages/megalodon/lib/src/misskey/helpers/accountCache.js b/packages/megalodon/lib/src/misskey/helpers/accountCache.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/helpers/accountCache.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/src/misskey/notification.d.ts b/packages/megalodon/lib/src/misskey/notification.d.ts new file mode 100644 index 000000000..fe63a8bd6 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/notification.d.ts @@ -0,0 +1,14 @@ +import MisskeyEntity from './entity'; +declare namespace MisskeyNotificationType { + const Follow: MisskeyEntity.NotificationType; + const Mention: MisskeyEntity.NotificationType; + const Reply: MisskeyEntity.NotificationType; + const Renote: MisskeyEntity.NotificationType; + const Quote: MisskeyEntity.NotificationType; + const Reaction: MisskeyEntity.NotificationType; + const PollVote: MisskeyEntity.NotificationType; + const ReceiveFollowRequest: MisskeyEntity.NotificationType; + const FollowRequestAccepted: MisskeyEntity.NotificationType; + const GroupInvited: MisskeyEntity.NotificationType; +} +export default MisskeyNotificationType; diff --git a/packages/megalodon/lib/src/misskey/notification.js b/packages/megalodon/lib/src/misskey/notification.js new file mode 100644 index 000000000..24c36ed69 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/notification.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MisskeyNotificationType; +(function (MisskeyNotificationType) { + MisskeyNotificationType.Follow = 'follow'; + MisskeyNotificationType.Mention = 'mention'; + MisskeyNotificationType.Reply = 'reply'; + MisskeyNotificationType.Renote = 'renote'; + MisskeyNotificationType.Quote = 'quote'; + MisskeyNotificationType.Reaction = 'favourite'; + MisskeyNotificationType.PollVote = 'pollVote'; + MisskeyNotificationType.ReceiveFollowRequest = 'receiveFollowRequest'; + MisskeyNotificationType.FollowRequestAccepted = 'followRequestAccepted'; + MisskeyNotificationType.GroupInvited = 'groupInvited'; +})(MisskeyNotificationType || (MisskeyNotificationType = {})); +exports.default = MisskeyNotificationType; diff --git a/packages/megalodon/lib/src/misskey/web_socket.d.ts b/packages/megalodon/lib/src/misskey/web_socket.d.ts new file mode 100644 index 000000000..d513d0898 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/web_socket.d.ts @@ -0,0 +1,44 @@ +/// +import WS from 'ws'; +import { EventEmitter } from 'events'; +import { WebSocketInterface } from '../megalodon'; +import { ProxyConfig } from '../proxy_config'; +import MisskeyAPI from './api_client'; +export default class WebSocket extends EventEmitter implements WebSocketInterface { + url: string; + channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list'; + parser: any; + headers: { + [key: string]: string; + }; + proxyConfig: ProxyConfig | false; + listId: string | null; + private _converter; + private _accessToken; + private _reconnectInterval; + private _reconnectMaxAttempts; + private _reconnectCurrentAttempts; + private _connectionClosed; + private _client; + private _channelID; + private _pongReceivedTimestamp; + private _heartbeatInterval; + private _pongWaiting; + constructor(url: string, channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', accessToken: string, listId: string | undefined, userAgent: string, proxyConfig: false | ProxyConfig | undefined, converter: MisskeyAPI.Converter); + start(): void; + private baseUrlToHost; + private _startWebSocketConnection; + stop(): void; + private _resetConnection; + private _resetRetryParams; + private _connect; + private _channel; + private _reconnect; + private _clearBinding; + private _bindSocket; + private _setupParser; + private _checkAlive; +} +export declare class Parser extends EventEmitter { + parse(data: WS.Data, isBinary: boolean, channelID: string): void; +} diff --git a/packages/megalodon/lib/src/misskey/web_socket.js b/packages/megalodon/lib/src/misskey/web_socket.js new file mode 100644 index 000000000..e1ad33af6 --- /dev/null +++ b/packages/megalodon/lib/src/misskey/web_socket.js @@ -0,0 +1,318 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Parser = void 0; +var ws_1 = __importDefault(require("ws")); +var dayjs_1 = __importDefault(require("dayjs")); +var uuid_1 = require("uuid"); +var events_1 = require("events"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var WebSocket = (function (_super) { + __extends(WebSocket, _super); + function WebSocket(url, channel, accessToken, listId, userAgent, proxyConfig, converter) { + if (proxyConfig === void 0) { proxyConfig = false; } + var _this = _super.call(this) || this; + _this.proxyConfig = false; + _this.listId = null; + _this._client = null; + _this._heartbeatInterval = 60000; + _this._pongWaiting = false; + _this.url = url; + _this.parser = new Parser(); + _this.channel = channel; + _this.headers = { + 'User-Agent': userAgent + }; + if (listId === undefined) { + _this.listId = null; + } + else { + _this.listId = listId; + } + _this.proxyConfig = proxyConfig; + _this._accessToken = accessToken; + _this._reconnectInterval = 10000; + _this._reconnectMaxAttempts = Infinity; + _this._reconnectCurrentAttempts = 0; + _this._connectionClosed = false; + _this._channelID = (0, uuid_1.v4)(); + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + _this._converter = converter; + return _this; + } + WebSocket.prototype.start = function () { + this._connectionClosed = false; + this._resetRetryParams(); + this._startWebSocketConnection(); + }; + WebSocket.prototype.baseUrlToHost = function (baseUrl) { + return baseUrl.replace('https://', ''); + }; + WebSocket.prototype._startWebSocketConnection = function () { + this._resetConnection(); + this._setupParser(); + this._client = this._connect(); + this._bindSocket(this._client); + }; + WebSocket.prototype.stop = function () { + this._connectionClosed = true; + this._resetConnection(); + this._resetRetryParams(); + }; + WebSocket.prototype._resetConnection = function () { + if (this._client) { + this._client.close(1000); + this._client.removeAllListeners(); + this._client = null; + } + if (this.parser) { + this.parser.removeAllListeners(); + } + }; + WebSocket.prototype._resetRetryParams = function () { + this._reconnectCurrentAttempts = 0; + }; + WebSocket.prototype._connect = function () { + var options = { + headers: this.headers + }; + if (this.proxyConfig) { + options = Object.assign(options, { + agent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + var cli = new ws_1.default("".concat(this.url, "?i=").concat(this._accessToken), options); + return cli; + }; + WebSocket.prototype._channel = function () { + if (!this._client) { + return; + } + switch (this.channel) { + case 'conversation': + this._client.send(JSON.stringify({ + type: 'connect', + body: { + channel: 'main', + id: this._channelID + } + })); + break; + case 'user': + this._client.send(JSON.stringify({ + type: 'connect', + body: { + channel: 'main', + id: this._channelID + } + })); + this._client.send(JSON.stringify({ + type: 'connect', + body: { + channel: 'homeTimeline', + id: this._channelID + } + })); + break; + case 'list': + this._client.send(JSON.stringify({ + type: 'connect', + body: { + channel: 'userList', + id: this._channelID, + params: { + listId: this.listId + } + } + })); + break; + default: + this._client.send(JSON.stringify({ + type: 'connect', + body: { + channel: this.channel, + id: this._channelID + } + })); + break; + } + }; + WebSocket.prototype._reconnect = function () { + var _this = this; + setTimeout(function () { + if (_this._client && _this._client.readyState === ws_1.default.CONNECTING) { + return; + } + if (_this._reconnectCurrentAttempts < _this._reconnectMaxAttempts) { + _this._reconnectCurrentAttempts++; + _this._clearBinding(); + if (_this._client) { + _this._client.terminate(); + } + console.log('Reconnecting'); + _this._client = _this._connect(); + _this._bindSocket(_this._client); + } + }, this._reconnectInterval); + }; + WebSocket.prototype._clearBinding = function () { + if (this._client) { + this._client.removeAllListeners('close'); + this._client.removeAllListeners('pong'); + this._client.removeAllListeners('open'); + this._client.removeAllListeners('message'); + this._client.removeAllListeners('error'); + } + }; + WebSocket.prototype._bindSocket = function (client) { + var _this = this; + client.on('close', function (code, _reason) { + if (code === 1000) { + _this.emit('close', {}); + } + else { + console.log("Closed connection with ".concat(code)); + if (!_this._connectionClosed) { + _this._reconnect(); + } + } + }); + client.on('pong', function () { + _this._pongWaiting = false; + _this.emit('pong', {}); + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + setTimeout(function () { return _this._checkAlive(_this._pongReceivedTimestamp); }, _this._heartbeatInterval); + }); + client.on('open', function () { + _this.emit('connect', {}); + _this._channel(); + setTimeout(function () { + client.ping(''); + }, 10000); + }); + client.on('message', function (data, isBinary) { + _this.parser.parse(data, isBinary, _this._channelID); + }); + client.on('error', function (err) { + _this.emit('error', err); + }); + }; + WebSocket.prototype._setupParser = function () { + var _this = this; + this.parser.on('update', function (note) { + _this.emit('update', _this._converter.note(note, _this.baseUrlToHost(_this.url))); + }); + this.parser.on('notification', function (notification) { + _this.emit('notification', _this._converter.notification(notification, _this.baseUrlToHost(_this.url))); + }); + this.parser.on('conversation', function (note) { + _this.emit('conversation', _this._converter.noteToConversation(note, _this.baseUrlToHost(_this.url))); + }); + this.parser.on('error', function (err) { + _this.emit('parser-error', err); + }); + }; + WebSocket.prototype._checkAlive = function (timestamp) { + var _this = this; + var now = (0, dayjs_1.default)(); + if (now.diff(timestamp) > this._heartbeatInterval - 1000 && !this._connectionClosed) { + if (this._client && this._client.readyState !== ws_1.default.CONNECTING) { + this._pongWaiting = true; + this._client.ping(''); + setTimeout(function () { + if (_this._pongWaiting) { + _this._pongWaiting = false; + _this._reconnect(); + } + }, 10000); + } + } + }; + return WebSocket; +}(events_1.EventEmitter)); +exports.default = WebSocket; +var Parser = (function (_super) { + __extends(Parser, _super); + function Parser() { + return _super !== null && _super.apply(this, arguments) || this; + } + Parser.prototype.parse = function (data, isBinary, channelID) { + var message = isBinary ? data : data.toString(); + if (typeof message !== 'string') { + this.emit('heartbeat', {}); + return; + } + if (message === '') { + this.emit('heartbeat', {}); + return; + } + var obj; + var body; + try { + obj = JSON.parse(message); + if (obj.type !== 'channel') { + return; + } + if (!obj.body) { + return; + } + body = obj.body; + if (body.id !== channelID) { + return; + } + } + catch (err) { + this.emit('error', new Error("Error parsing websocket reply: ".concat(message, ", error message: ").concat(err))); + return; + } + switch (body.type) { + case 'note': + this.emit('update', body.body); + break; + case 'notification': + this.emit('notification', body.body); + break; + case 'mention': { + var note = body.body; + if (note.visibility === 'specified') { + this.emit('conversation', note); + } + break; + } + case 'renote': + case 'followed': + case 'follow': + case 'unfollow': + case 'receiveFollowRequest': + case 'meUpdated': + case 'readAllNotifications': + case 'readAllUnreadSpecifiedNotes': + case 'readAllAntennas': + case 'readAllUnreadMentions': + case 'unreadNotification': + break; + default: + this.emit('error', new Error("Unknown event has received: ".concat(JSON.stringify(body)))); + break; + } + }; + return Parser; +}(events_1.EventEmitter)); +exports.Parser = Parser; diff --git a/packages/megalodon/lib/src/notification.d.ts b/packages/megalodon/lib/src/notification.d.ts new file mode 100644 index 000000000..ad90622b7 --- /dev/null +++ b/packages/megalodon/lib/src/notification.d.ts @@ -0,0 +1,13 @@ +import Entity from './entity'; +declare namespace NotificationType { + const Follow: Entity.NotificationType; + const Favourite: Entity.NotificationType; + const Reblog: Entity.NotificationType; + const Mention: Entity.NotificationType; + const EmojiReaction: Entity.NotificationType; + const FollowRequest: Entity.NotificationType; + const Status: Entity.NotificationType; + const PollVote: Entity.NotificationType; + const PollExpired: Entity.NotificationType; +} +export default NotificationType; diff --git a/packages/megalodon/lib/src/notification.js b/packages/megalodon/lib/src/notification.js new file mode 100644 index 000000000..048a66e12 --- /dev/null +++ b/packages/megalodon/lib/src/notification.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var NotificationType; +(function (NotificationType) { + NotificationType.Follow = 'follow'; + NotificationType.Favourite = 'favourite'; + NotificationType.Reblog = 'reblog'; + NotificationType.Mention = 'mention'; + NotificationType.EmojiReaction = 'emoji_reaction'; + NotificationType.FollowRequest = 'follow_request'; + NotificationType.Status = 'status'; + NotificationType.PollVote = 'poll_vote'; + NotificationType.PollExpired = 'poll_expired'; +})(NotificationType || (NotificationType = {})); +exports.default = NotificationType; diff --git a/packages/megalodon/lib/src/oauth.d.ts b/packages/megalodon/lib/src/oauth.d.ts new file mode 100644 index 000000000..0637fd5d8 --- /dev/null +++ b/packages/megalodon/lib/src/oauth.d.ts @@ -0,0 +1,50 @@ +declare namespace OAuth { + type AppDataFromServer = { + id: string; + name: string; + website: string | null; + redirect_uri: string; + client_id: string; + client_secret: string; + }; + type TokenDataFromServer = { + access_token: string; + token_type: string; + scope: string; + created_at: number; + expires_in: number | null; + refresh_token: string | null; + }; + class AppData { + id: string; + name: string; + website: string | null; + redirect_uri: string; + client_id: string; + client_secret: string; + url: string | null; + session_token: string | null; + constructor(id: string, name: string, website: string | null, redirect_uri: string, client_id: string, client_secret: string); + static from(raw: AppDataFromServer): AppData; + get redirectUri(): string; + get clientId(): string; + get clientSecret(): string; + } + class TokenData { + access_token: string; + token_type: string; + created_at: number; + expires_in: number | null; + refresh_token: string | null; + _scope: string; + constructor(access_token: string, token_type: string, scope: string, created_at: number, expires_in?: number | null, refresh_token?: string | null); + static from(raw: TokenDataFromServer): TokenData; + get accessToken(): string; + get tokenType(): string; + get scope(): string; + get createdAt(): number; + get expiresIn(): number | null; + get refreshToken(): string | null; + } +} +export default OAuth; diff --git a/packages/megalodon/lib/src/oauth.js b/packages/megalodon/lib/src/oauth.js new file mode 100644 index 000000000..80b582159 --- /dev/null +++ b/packages/megalodon/lib/src/oauth.js @@ -0,0 +1,103 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var OAuth; +(function (OAuth) { + var AppData = (function () { + function AppData(id, name, website, redirect_uri, client_id, client_secret) { + this.id = id; + this.name = name; + this.website = website; + this.redirect_uri = redirect_uri; + this.client_id = client_id; + this.client_secret = client_secret; + this.url = null; + this.session_token = null; + } + AppData.from = function (raw) { + return new this(raw.id, raw.name, raw.website, raw.redirect_uri, raw.client_id, raw.client_secret); + }; + Object.defineProperty(AppData.prototype, "redirectUri", { + get: function () { + return this.redirect_uri; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(AppData.prototype, "clientId", { + get: function () { + return this.client_id; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(AppData.prototype, "clientSecret", { + get: function () { + return this.client_secret; + }, + enumerable: false, + configurable: true + }); + return AppData; + }()); + OAuth.AppData = AppData; + var TokenData = (function () { + function TokenData(access_token, token_type, scope, created_at, expires_in, refresh_token) { + if (expires_in === void 0) { expires_in = null; } + if (refresh_token === void 0) { refresh_token = null; } + this.access_token = access_token; + this.token_type = token_type; + this.created_at = created_at; + this.expires_in = expires_in; + this.refresh_token = refresh_token; + this._scope = scope; + } + TokenData.from = function (raw) { + return new this(raw.access_token, raw.token_type, raw.scope, raw.created_at, raw.expires_in, raw.refresh_token); + }; + Object.defineProperty(TokenData.prototype, "accessToken", { + get: function () { + return this.access_token; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenData.prototype, "tokenType", { + get: function () { + return this.token_type; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenData.prototype, "scope", { + get: function () { + return this._scope; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenData.prototype, "createdAt", { + get: function () { + return this.created_at; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenData.prototype, "expiresIn", { + get: function () { + return this.expires_in; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenData.prototype, "refreshToken", { + get: function () { + return this.refresh_token; + }, + enumerable: false, + configurable: true + }); + return TokenData; + }()); + OAuth.TokenData = TokenData; +})(OAuth || (OAuth = {})); +exports.default = OAuth; diff --git a/packages/megalodon/lib/src/parser.d.ts b/packages/megalodon/lib/src/parser.d.ts new file mode 100644 index 000000000..b07425a37 --- /dev/null +++ b/packages/megalodon/lib/src/parser.d.ts @@ -0,0 +1,7 @@ +/// +import { EventEmitter } from 'events'; +export declare class Parser extends EventEmitter { + private message; + constructor(); + parse(chunk: string): void; +} diff --git a/packages/megalodon/lib/src/parser.js b/packages/megalodon/lib/src/parser.js new file mode 100644 index 000000000..e3eba4964 --- /dev/null +++ b/packages/megalodon/lib/src/parser.js @@ -0,0 +1,87 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Parser = void 0; +var events_1 = require("events"); +var Parser = (function (_super) { + __extends(Parser, _super); + function Parser() { + var _this = _super.call(this) || this; + _this.message = ''; + return _this; + } + Parser.prototype.parse = function (chunk) { + if (chunk === ':thump\n') { + this.emit('heartbeat', {}); + return; + } + this.message += chunk; + chunk = this.message; + var size = chunk.length; + var start = 0; + var offset = 0; + var curr; + var next; + while (offset < size) { + curr = chunk[offset]; + next = chunk[offset + 1]; + if (curr === '\n' && next === '\n') { + var piece = chunk.slice(start, offset); + offset += 2; + start = offset; + if (!piece.length) + continue; + var root = piece.split('\n'); + if (root.length !== 2) + continue; + var event_1 = root[0].substr(7); + var data = root[1].substr(6); + var jsonObj = {}; + try { + jsonObj = JSON.parse(data); + } + catch (err) { + if (event_1 !== 'delete') { + this.emit('error', new Error("Error parsing API reply: '".concat(piece, "', error message: '").concat(err, "'"))); + continue; + } + } + switch (event_1) { + case 'update': + this.emit('update', jsonObj); + break; + case 'notification': + this.emit('notification', jsonObj); + break; + case 'conversation': + this.emit('conversation', jsonObj); + break; + case 'delete': + this.emit('delete', data); + break; + default: + this.emit('error', new Error("Unknown event has received: ".concat(event_1))); + continue; + } + } + offset++; + } + this.message = chunk.slice(start, size); + }; + return Parser; +}(events_1.EventEmitter)); +exports.Parser = Parser; diff --git a/packages/megalodon/lib/src/pleroma.d.ts b/packages/megalodon/lib/src/pleroma.d.ts new file mode 100644 index 000000000..cff9fc8f3 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma.d.ts @@ -0,0 +1,367 @@ +import PleromaAPI from './pleroma/api_client'; +import WebSocket from './pleroma/web_socket'; +import { MegalodonInterface } from './megalodon'; +import Response from './response'; +import Entity from './entity'; +import { ProxyConfig } from './proxy_config'; +import OAuth from './oauth'; +export default class Pleroma implements MegalodonInterface { + client: PleromaAPI.Interface; + baseUrl: string; + constructor(baseUrl: string, accessToken?: string | null, userAgent?: string | null, proxyConfig?: ProxyConfig | false); + cancel(): void; + registerApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + createApp(client_name: string, options: Partial<{ + scopes: Array; + redirect_uris: string; + website: string; + }>): Promise; + generateAuthUrl(clientId: string, clientSecret: string, options: Partial<{ + scope: Array; + redirect_uri: string; + }>): Promise; + verifyAppCredentials(): Promise>; + fetchAccessToken(client_id: string | null, client_secret: string, code: string, redirect_uri?: string): Promise; + refreshToken(client_id: string, client_secret: string, refresh_token: string): Promise; + revokeToken(client_id: string, client_secret: string, token: string): Promise>; + registerAccount(username: string, email: string, password: string, agreement: boolean, locale: string, reason?: string | null): Promise>; + verifyAccountCredentials(): Promise>; + updateCredentials(options?: { + discoverable?: boolean; + bot?: boolean; + display_name?: string; + note?: string; + avatar?: string; + header?: string; + locked?: boolean; + source?: { + privacy?: string; + sensitive?: boolean; + language?: string; + }; + fields_attributes?: Array<{ + name: string; + value: string; + }>; + }): Promise>; + getAccount(id: string): Promise>; + getAccountStatuses(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + pinned?: boolean; + exclude_replies?: boolean; + exclude_reblogs?: boolean; + only_media?: boolean; + }): Promise>>; + subscribeAccount(id: string): Promise>; + unsubscribeAccount(id: string): Promise>; + getAccountFavourites(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountFollowers(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountFollowing(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getAccountLists(id: string): Promise>>; + getIdentityProof(id: string): Promise>>; + followAccount(id: string, options?: { + reblog?: boolean; + }): Promise>; + unfollowAccount(id: string): Promise>; + blockAccount(id: string): Promise>; + unblockAccount(id: string): Promise>; + muteAccount(id: string, notifications?: boolean): Promise>; + unmuteAccount(id: string): Promise>; + pinAccount(id: string): Promise>; + unpinAccount(id: string): Promise>; + getRelationship(id: string): Promise>; + getRelationships(ids: Array): Promise>>; + searchAccount(q: string, options?: { + following?: boolean; + resolve?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getBookmarks(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getFavourites(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getMutes(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + getDomainBlocks(options?: { + limit?: number; + max_id?: string; + min_id?: string; + }): Promise>>; + blockDomain(domain: string): Promise>; + unblockDomain(domain: string): Promise>; + getFilters(): Promise>>; + getFilter(id: string): Promise>; + createFilter(phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + updateFilter(id: string, phrase: string, context: Array, options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }): Promise>; + deleteFilter(id: string): Promise>; + report(account_id: string, comment: string, options?: { + status_ids?: Array; + forward?: boolean; + }): Promise>; + getFollowRequests(limit?: number): Promise>>; + acceptFollowRequest(id: string): Promise>; + rejectFollowRequest(id: string): Promise>; + getEndorsements(options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + getFeaturedTags(): Promise>>; + getAccountFeaturedTags(id: string): Promise>>; + createFeaturedTag(name: string): Promise>; + deleteFeaturedTag(id: string): Promise>; + getSuggestedTags(): Promise>>; + getPreferences(): Promise>; + getSuggestions(limit?: number): Promise>>; + getTag(id: string): Promise>; + followTag(id: string): Promise>; + unfollowTag(id: string): Promise>; + postStatus(status: string, options: { + media_ids?: Array; + poll?: { + options: Array; + expires_in: number; + multiple?: boolean; + hide_totals?: boolean; + }; + in_reply_to_id?: string; + sensitive?: boolean; + spoiler_text?: string; + visibility?: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at?: string; + language?: string; + }): Promise>; + getStatus(id: string): Promise>; + editStatus(id: string, options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array; + poll?: { + options?: Array; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }): Promise>; + deleteStatus(id: string): Promise>; + getStatusContext(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>; + getStatusRebloggedBy(id: string): Promise>>; + getStatusFavouritedBy(id: string): Promise>>; + favouriteStatus(id: string): Promise>; + unfavouriteStatus(id: string): Promise>; + reblogStatus(id: string): Promise>; + unreblogStatus(id: string): Promise>; + bookmarkStatus(id: string): Promise>; + unbookmarkStatus(id: string): Promise>; + muteStatus(id: string): Promise>; + unmuteStatus(id: string): Promise>; + pinStatus(id: string): Promise>; + unpinStatus(id: string): Promise>; + uploadMedia(file: any, options?: { + description?: string; + focus?: string; + }): Promise>; + getMedia(id: string): Promise>; + updateMedia(id: string, options?: { + file?: any; + description?: string; + focus?: string; + }): Promise>; + getPoll(id: string): Promise>; + votePoll(id: string, choices: Array): Promise>; + getScheduledStatuses(options?: { + limit?: number | null; + max_id?: string | null; + since_id?: string | null; + min_id?: string | null; + }): Promise>>; + getScheduledStatus(id: string): Promise>; + scheduleStatus(id: string, scheduled_at?: string | null): Promise>; + cancelScheduledStatus(id: string): Promise>; + getPublicTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getLocalTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getTagTimeline(hashtag: string, options?: { + local?: boolean; + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getHomeTimeline(options?: { + local?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getListTimeline(list_id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + getConversationTimeline(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise>>; + deleteConversation(id: string): Promise>; + readConversation(id: string): Promise>; + getLists(): Promise>>; + getList(id: string): Promise>; + createList(title: string): Promise>; + updateList(id: string, title: string): Promise>; + deleteList(id: string): Promise>; + getAccountsInList(id: string, options?: { + limit?: number; + max_id?: string; + since_id?: string; + }): Promise>>; + addAccountsToList(id: string, account_ids: Array): Promise>; + deleteAccountsFromList(id: string, account_ids: Array): Promise>; + getMarkers(timeline: Array): Promise>; + saveMarkers(options?: { + home?: { + last_read_id: string; + }; + notifications?: { + last_read_id: string; + }; + }): Promise>; + getNotifications(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + exclude_types?: Array; + account_id?: string; + }): Promise>>; + getNotification(id: string): Promise>; + dismissNotifications(): Promise>; + dismissNotification(id: string): Promise>; + readNotifications(options: { + id?: string; + max_id?: string; + }): Promise>>; + subscribePushNotification(subscription: { + endpoint: string; + keys: { + p256dh: string; + auth: string; + }; + }, data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + getPushSubscription(): Promise>; + updatePushSubscription(data?: { + alerts: { + follow?: boolean; + favourite?: boolean; + reblog?: boolean; + mention?: boolean; + poll?: boolean; + }; + } | null): Promise>; + deletePushSubscription(): Promise>; + search(q: string, type: 'accounts' | 'hashtags' | 'statuses', options?: { + limit?: number; + max_id?: string; + min_id?: string; + resolve?: boolean; + offset?: number; + following?: boolean; + account_id?: string; + exclude_unreviewed?: boolean; + }): Promise>; + getInstance(): Promise>; + getInstancePeers(): Promise>>; + getInstanceActivity(): Promise>>; + getInstanceTrends(limit?: number | null): Promise>>; + getInstanceDirectory(options?: { + limit?: number; + offset?: number; + order?: 'active' | 'new'; + local?: boolean; + }): Promise>>; + getInstanceCustomEmojis(): Promise>>; + getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>>; + dismissInstanceAnnouncement(id: string): Promise>; + createEmojiReaction(id: string, emoji: string): Promise>; + deleteEmojiReaction(id: string, emoji: string): Promise>; + getEmojiReactions(id: string): Promise>>; + getEmojiReaction(id: string, emoji: string): Promise>; + userSocket(): WebSocket; + publicSocket(): WebSocket; + localSocket(): WebSocket; + tagSocket(tag: string): WebSocket; + listSocket(list_id: string): WebSocket; + directSocket(): WebSocket; +} diff --git a/packages/megalodon/lib/src/pleroma.js b/packages/megalodon/lib/src/pleroma.js new file mode 100644 index 000000000..2521800ee --- /dev/null +++ b/packages/megalodon/lib/src/pleroma.js @@ -0,0 +1,2357 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var oauth_1 = require("oauth"); +var form_data_1 = __importDefault(require("form-data")); +var api_client_1 = __importDefault(require("./pleroma/api_client")); +var megalodon_1 = require("./megalodon"); +var default_1 = require("./default"); +var oauth_2 = __importDefault(require("./oauth")); +var Pleroma = (function () { + function Pleroma(baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + var token = ''; + if (accessToken) { + token = accessToken; + } + var agent = default_1.DEFAULT_UA; + if (userAgent) { + agent = userAgent; + } + this.client = new api_client_1.default.Client(baseUrl, token, agent, proxyConfig); + this.baseUrl = baseUrl; + } + Pleroma.prototype.cancel = function () { + return this.client.cancel(); + }; + Pleroma.prototype.registerApp = function (client_name, options) { + return __awaiter(this, void 0, void 0, function () { + var scopes; + var _this = this; + return __generator(this, function (_a) { + scopes = options.scopes || default_1.DEFAULT_SCOPE; + return [2, this.createApp(client_name, options).then(function (appData) { return __awaiter(_this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.generateAuthUrl(appData.client_id, appData.client_secret, { + scope: scopes, + redirect_uri: appData.redirect_uri + }).then(function (url) { + appData.url = url; + return appData; + })]; + }); + }); })]; + }); + }); + }; + Pleroma.prototype.createApp = function (client_name, options) { + return __awaiter(this, void 0, void 0, function () { + var scopes, redirect_uris, params; + return __generator(this, function (_a) { + scopes = options.scopes || default_1.DEFAULT_SCOPE; + redirect_uris = options.redirect_uris || default_1.NO_REDIRECT; + params = { + client_name: client_name, + redirect_uris: redirect_uris, + scopes: scopes.join(' ') + }; + if (options.website) + params.website = options.website; + return [2, this.client + .post('/api/v1/apps', params) + .then(function (res) { return oauth_2.default.AppData.from(res.data); })]; + }); + }); + }; + Pleroma.prototype.generateAuthUrl = function (clientId, clientSecret, options) { + var _this = this; + var scope = options.scope || default_1.DEFAULT_SCOPE; + var redirect_uri = options.redirect_uri || default_1.NO_REDIRECT; + return new Promise(function (resolve) { + var oauth = new oauth_1.OAuth2(clientId, clientSecret, _this.baseUrl, undefined, '/oauth/token'); + var url = oauth.getAuthorizeUrl({ + redirect_uri: redirect_uri, + response_type: 'code', + client_id: clientId, + scope: scope.join(' ') + }); + resolve(url); + }); + }; + Pleroma.prototype.verifyAppCredentials = function () { + return this.client.get('/api/v1/apps/verify_credentials'); + }; + Pleroma.prototype.fetchAccessToken = function (client_id, client_secret, code, redirect_uri) { + if (redirect_uri === void 0) { redirect_uri = default_1.NO_REDIRECT; } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (!client_id) { + throw new Error('client_id is required'); + } + return [2, this.client + .post('/oauth/token', { + client_id: client_id, + client_secret: client_secret, + code: code, + redirect_uri: redirect_uri, + grant_type: 'authorization_code' + }) + .then(function (res) { return oauth_2.default.TokenData.from(res.data); })]; + }); + }); + }; + Pleroma.prototype.refreshToken = function (client_id, client_secret, refresh_token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/oauth/token', { + client_id: client_id, + client_secret: client_secret, + refresh_token: refresh_token, + grant_type: 'refresh_token' + }) + .then(function (res) { return oauth_2.default.TokenData.from(res.data); })]; + }); + }); + }; + Pleroma.prototype.revokeToken = function (client_id, client_secret, token) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post('/oauth/revoke', { + client_id: client_id, + client_secret: client_secret, + token: token + })]; + }); + }); + }; + Pleroma.prototype.registerAccount = function (username, email, password, agreement, locale, reason) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + username: username, + email: email, + password: password, + agreement: agreement, + locale: locale + }; + if (reason) { + params = Object.assign(params, { + reason: reason + }); + } + return [2, this.client.post('/api/v1/accounts', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.token(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.verifyAccountCredentials = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/accounts/verify_credentials').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.updateCredentials = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.patch('/api/v1/accounts/update_credentials', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.account(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountStatuses = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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.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 [2, this.client.get("/api/v1/accounts/".concat(id, "/statuses"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.subscribeAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/pleroma/accounts/".concat(id, "/subscribe")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unsubscribeAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/pleroma/accounts/".concat(id, "/unsubscribe")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountFavourites = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/pleroma/accounts/".concat(id, "/favourites"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountFollowers = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/accounts/".concat(id, "/followers"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountFollowing = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/accounts/".concat(id, "/following"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountLists = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/lists")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (l) { return api_client_1.default.Converter.list(l); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getIdentityProof = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/identity_proofs")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (i) { return api_client_1.default.Converter.identity_proof(i); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.followAccount = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.reblog !== undefined) { + params = Object.assign(params, { + reblog: options.reblog + }); + } + } + return [2, this.client.post("/api/v1/accounts/".concat(id, "/follow"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unfollowAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unfollow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.blockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/block")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unblockAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unblock")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.muteAccount = function (id, notifications) { + if (notifications === void 0) { notifications = true; } + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post("/api/v1/accounts/".concat(id, "/mute"), { + notifications: notifications + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unmuteAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unmute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.pinAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/pin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unpinAccount = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/accounts/".concat(id, "/unpin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getRelationship = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .get('/api/v1/accounts/relationships', { + id: [id] + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data[0]) + }); + })]; + }); + }); + }; + Pleroma.prototype.getRelationships = function (ids) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .get('/api/v1/accounts/relationships', { + id: ids + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (r) { return api_client_1.default.Converter.relationship(r); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.searchAccount = function (q, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/accounts/search', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getBookmarks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/bookmarks', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getFavourites = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/favourites', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getMutes = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/mutes', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getBlocks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/blocks', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getDomainBlocks = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/domain_blocks', params)]; + }); + }); + }; + Pleroma.prototype.blockDomain = function (domain) { + return this.client.post('/api/v1/domain_blocks', { + domain: domain + }); + }; + Pleroma.prototype.unblockDomain = function (domain) { + return this.client.del('/api/v1/domain_blocks', { + domain: domain + }); + }; + Pleroma.prototype.getFilters = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/filters').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.filter(f); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getFilter = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/filters/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.createFilter = function (phrase, context, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.post('/api/v1/filters', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.updateFilter = function (id, phrase, context, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.put("/api/v1/filters/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteFilter = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.del("/api/v1/filters/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.filter(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.report = function (account_id, comment, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + account_id: account_id, + comment: comment + }; + if (options) { + if (options.status_ids) { + params = Object.assign(params, { + status_ids: options.status_ids + }); + } + if (options.forward !== undefined) { + params = Object.assign(params, { + forward: options.forward + }); + } + } + return [2, this.client.post('/api/v1/reports', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.report(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getFollowRequests = function (limit) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (limit) { + return [2, this.client + .get('/api/v1/follow_requests', { + limit: limit + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + else { + return [2, this.client.get('/api/v1/follow_requests').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + return [2]; + }); + }); + }; + Pleroma.prototype.acceptFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/follow_requests/".concat(id, "/authorize")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.rejectFollowRequest = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/follow_requests/".concat(id, "/reject")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.relationship(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getEndorsements = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/endorsements', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getFeaturedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/featured_tags').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.featured_tag(f); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getAccountFeaturedTags = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/accounts/".concat(id, "/featured_tags")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (f) { return api_client_1.default.Converter.featured_tag(f); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.createFeaturedTag = function (name) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/v1/featured_tags', { + name: name + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.featured_tag(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteFeaturedTag = function (id) { + return this.client.del("/api/v1/featured_tags/".concat(id)); + }; + Pleroma.prototype.getSuggestedTags = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/featured_tags/suggestions').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (t) { return api_client_1.default.Converter.tag(t); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getPreferences = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/preferences').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.preferences(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getSuggestions = function (limit) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (limit) { + return [2, this.client + .get('/api/v1/suggestions', { + limit: limit + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + else { + return [2, this.client.get('/api/v1/suggestions').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + } + return [2]; + }); + }); + }; + Pleroma.prototype.getTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/tags/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.followTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/tags/".concat(id, "/follow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unfollowTag = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/tags/".concat(id, "/unfollow")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.tag(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.postStatus = function (status, options) { + return __awaiter(this, void 0, void 0, function () { + var params, pollParam; + return __generator(this, function (_a) { + params = { + status: status + }; + if (options) { + if (options.media_ids) { + params = Object.assign(params, { + media_ids: options.media_ids + }); + } + if (options.poll) { + 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: options.visibility + }); + } + if (options.scheduled_at) { + params = Object.assign(params, { + scheduled_at: options.scheduled_at + }); + } + if (options.language) { + params = Object.assign(params, { + language: options.language + }); + } + } + return [2, this.client.post('/api/v1/statuses', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.editStatus = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params, pollParam; + return __generator(this, function (_a) { + 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) { + 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 [2, this.client.put("/api/v1/statuses/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.del("/api/v1/statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getStatusContext = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/statuses/".concat(id, "/context"), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.context(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getStatusRebloggedBy = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id, "/reblogged_by")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getStatusFavouritedBy = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/statuses/".concat(id, "/favourited_by")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.favouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/favourite")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unfavouriteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unfavourite")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.reblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/reblog")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unreblogStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unreblog")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.bookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/bookmark")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unbookmarkStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unbookmark")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.muteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/mute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unmuteStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unmute")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.pinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/pin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.unpinStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/statuses/".concat(id, "/unpin")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.uploadMedia = function (file, options) { + return __awaiter(this, void 0, void 0, function () { + var formData; + return __generator(this, function (_a) { + formData = new form_data_1.default(); + formData.append('file', file); + if (options) { + if (options.description) { + formData.append('description', options.description); + } + if (options.focus) { + formData.append('focus', options.focus); + } + } + return [2, this.client.postForm('/api/v2/media', formData).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.async_attachment(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getMedia = function (id) { + return __awaiter(this, void 0, void 0, function () { + var res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, this.client.get("/api/v1/media/".concat(id))]; + case 1: + res = _a.sent(); + return [2, Object.assign(res, { + data: api_client_1.default.Converter.attachment(res.data) + })]; + } + }); + }); + }; + Pleroma.prototype.updateMedia = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var formData; + return __generator(this, function (_a) { + formData = new form_data_1.default(); + 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 [2, this.client.putForm("/api/v1/media/".concat(id), formData).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.attachment(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getPoll = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/polls/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.poll(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.votePoll = function (id, choices) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post("/api/v1/polls/".concat(id, "/votes"), { + choices: choices + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.poll(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getScheduledStatuses = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/scheduled_statuses', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.scheduled_status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getScheduledStatus = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/scheduled_statuses/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.scheduled_status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.scheduleStatus = function (id, scheduled_at) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (scheduled_at) { + params = Object.assign(params, { + scheduled_at: scheduled_at + }); + } + return [2, this.client.put("/api/v1/scheduled_statuses/".concat(id), params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.scheduled_status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.cancelScheduledStatus = function (id) { + return this.client.del("/api/v1/scheduled_statuses/".concat(id)); + }; + Pleroma.prototype.getPublicTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/public', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getLocalTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/public', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getTagTimeline = function (hashtag, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/timelines/tag/".concat(hashtag), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getHomeTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/timelines/home', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getListTimeline = function (list_id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/timelines/list/".concat(list_id), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (s) { return api_client_1.default.Converter.status(s); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getConversationTimeline = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get('/api/v1/conversations', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (c) { return api_client_1.default.Converter.conversation(c); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteConversation = function (id) { + return this.client.del("/api/v1/conversations/".concat(id)); + }; + Pleroma.prototype.readConversation = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/conversations/".concat(id, "/read")).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.conversation(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getLists = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/lists').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (l) { return api_client_1.default.Converter.list(l); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getList = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/lists/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.createList = function (title) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .post('/api/v1/lists', { + title: title + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.updateList = function (id, title) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client + .put("/api/v1/lists/".concat(id), { + title: title + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.list(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteList = function (id) { + return this.client.del("/api/v1/lists/".concat(id)); + }; + Pleroma.prototype.getAccountsInList = function (id, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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 [2, this.client.get("/api/v1/lists/".concat(id, "/accounts"), params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.addAccountsToList = function (id, account_ids) { + return this.client.post("/api/v1/lists/".concat(id, "/accounts"), { + account_ids: account_ids + }); + }; + Pleroma.prototype.deleteAccountsFromList = function (id, account_ids) { + return this.client.del("/api/v1/lists/".concat(id, "/accounts"), { + account_ids: account_ids + }); + }; + Pleroma.prototype.getMarkers = function (timeline) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/markers', { + timeline: timeline + })]; + }); + }); + }; + Pleroma.prototype.saveMarkers = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.home) { + params = Object.assign(params, { + home: options.home + }); + } + if (options.notifications) { + params = Object.assign(params, { + notifications: options.notifications + }); + } + } + return [2, this.client.post('/api/v1/markers', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.marker(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getNotifications = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + 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(function (e) { return api_client_1.default.Converter.encodeNotificationType(e); }) + }); + } + if (options.account_id) { + params = Object.assign(params, { + account_id: options.account_id + }); + } + } + return [2, this.client.get('/api/v1/notifications', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (n) { return api_client_1.default.Converter.notification(n); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getNotification = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/notifications/".concat(id)).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.notification(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.dismissNotifications = function () { + return this.client.post('/api/v1/notifications/clear'); + }; + Pleroma.prototype.dismissNotification = function (id) { + return this.client.post("/api/v1/notifications/".concat(id, "/dismiss")); + }; + Pleroma.prototype.readNotifications = function (options) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + if (options.id) { + return [2, this.client + .post('/api/v1/pleroma/notifications/read', { + id: options.id + }) + .then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.notification(res.data) + }); + })]; + } + else if (options.max_id) { + return [2, this.client + .post('/api/v1/pleroma/notifications/read', { + max_id: options.max_id + }) + .then(function (res) { + return Object.assign(res, { + data: res.data.map(function (n) { return api_client_1.default.Converter.notification(n); }) + }); + })]; + } + else { + return [2, new Promise(function (_, reject) { + var err = new megalodon_1.ArgumentError('id or max_id is required'); + reject(err); + })]; + } + return [2]; + }); + }); + }; + Pleroma.prototype.subscribePushNotification = function (subscription, data) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + subscription: subscription + }; + if (data) { + params = Object.assign(params, { + data: data + }); + } + return [2, this.client.post('/api/v1/push/subscription', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getPushSubscription = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/push/subscription').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.updatePushSubscription = function (data) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (data) { + params = Object.assign(params, { + data: data + }); + } + return [2, this.client.put('/api/v1/push/subscription', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.push_subscription(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deletePushSubscription = function () { + return this.client.del('/api/v1/push/subscription'); + }; + Pleroma.prototype.search = function (q, type, options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = { + q: q, + type: type + }; + 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.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 [2, this.client.get('/api/v2/search', params).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.results(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstance = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/instance').then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.instance(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstancePeers = function () { + return this.client.get('/api/v1/instance/peers'); + }; + Pleroma.prototype.getInstanceActivity = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/instance/activity').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.activity(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstanceTrends = function (limit) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (limit) { + params = Object.assign(params, { + limit: limit + }); + } + return [2, this.client.get('/api/v1/trends', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (t) { return api_client_1.default.Converter.tag(t); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstanceDirectory = function (options) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }); + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }); + } + if (options.order) { + params = Object.assign(params, { + order: options.order + }); + } + if (options.local !== undefined) { + params = Object.assign(params, { + local: options.local + }); + } + } + return [2, this.client.get('/api/v1/directory', params).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (a) { return api_client_1.default.Converter.account(a); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstanceCustomEmojis = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get('/api/v1/custom_emojis').then(function (res) { + return Object.assign(res, { + data: res.data.map(function (e) { return api_client_1.default.Converter.emoji(e); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getInstanceAnnouncements = function (with_dismissed) { + return __awaiter(this, void 0, void 0, function () { + var params; + return __generator(this, function (_a) { + params = {}; + if (with_dismissed) { + params = Object.assign(params, { + with_dismissed: with_dismissed + }); + } + return [2, this.client.get('/api/v1/announcements', params).then(function (res) { return (__assign(__assign({}, res), { data: res.data.map(function (t) { return api_client_1.default.Converter.announcement(t); }) })); })]; + }); + }); + }; + Pleroma.prototype.dismissInstanceAnnouncement = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.post("/api/v1/announcements/".concat(id, "/dismiss"))]; + }); + }); + }; + Pleroma.prototype.createEmojiReaction = function (id, emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.put("/api/v1/pleroma/statuses/".concat(id, "/reactions/").concat(encodeURI(emoji))).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.deleteEmojiReaction = function (id, emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.del("/api/v1/pleroma/statuses/".concat(id, "/reactions/").concat(encodeURI(emoji))).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.status(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.getEmojiReactions = function (id) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/pleroma/statuses/".concat(id, "/reactions")).then(function (res) { + return Object.assign(res, { + data: res.data.map(function (r) { return api_client_1.default.Converter.reaction(r); }) + }); + })]; + }); + }); + }; + Pleroma.prototype.getEmojiReaction = function (id, emoji) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2, this.client.get("/api/v1/pleroma/statuses/".concat(id, "/reactions/").concat(encodeURI(emoji))).then(function (res) { + return Object.assign(res, { + data: api_client_1.default.Converter.reaction(res.data) + }); + })]; + }); + }); + }; + Pleroma.prototype.userSocket = function () { + return this.client.socket('/api/v1/streaming', 'user'); + }; + Pleroma.prototype.publicSocket = function () { + return this.client.socket('/api/v1/streaming', 'public'); + }; + Pleroma.prototype.localSocket = function () { + return this.client.socket('/api/v1/streaming', 'public:local'); + }; + Pleroma.prototype.tagSocket = function (tag) { + return this.client.socket('/api/v1/streaming', 'hashtag', "tag=".concat(tag)); + }; + Pleroma.prototype.listSocket = function (list_id) { + return this.client.socket('/api/v1/streaming', 'list', "list=".concat(list_id)); + }; + Pleroma.prototype.directSocket = function () { + return this.client.socket('/api/v1/streaming', 'direct'); + }; + return Pleroma; +}()); +exports.default = Pleroma; diff --git a/packages/megalodon/lib/src/pleroma/api_client.d.ts b/packages/megalodon/lib/src/pleroma/api_client.d.ts new file mode 100644 index 000000000..7814930d7 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/api_client.d.ts @@ -0,0 +1,152 @@ +import MegalodonEntity from '../entity'; +import PleromaEntity from './entity'; +import Response from '../response'; +import { ProxyConfig } from '../proxy_config'; +import WebSocket from './web_socket'; +import NotificationType from '../notification'; +declare namespace PleromaAPI { + namespace Entity { + type Account = PleromaEntity.Account; + type Activity = PleromaEntity.Activity; + type Announcement = PleromaEntity.Announcement; + type Application = PleromaEntity.Application; + type AsyncAttachment = PleromaEntity.AsyncAttachment; + type Attachment = PleromaEntity.Attachment; + type Card = PleromaEntity.Card; + type Context = PleromaEntity.Context; + type Conversation = PleromaEntity.Conversation; + type Emoji = PleromaEntity.Emoji; + type FeaturedTag = PleromaEntity.FeaturedTag; + type Field = PleromaEntity.Field; + type Filter = PleromaEntity.Filter; + type History = PleromaEntity.History; + type IdentityProof = PleromaEntity.IdentityProof; + type Instance = PleromaEntity.Instance; + type List = PleromaEntity.List; + type Marker = PleromaEntity.Marker; + type Mention = PleromaEntity.Mention; + type Notification = PleromaEntity.Notification; + type Poll = PleromaEntity.Poll; + type PollOption = PleromaEntity.PollOption; + type Preferences = PleromaEntity.Preferences; + type PushSubscription = PleromaEntity.PushSubscription; + type Reaction = PleromaEntity.Reaction; + type Relationship = PleromaEntity.Relationship; + type Report = PleromaEntity.Report; + type Results = PleromaEntity.Results; + type ScheduledStatus = PleromaEntity.ScheduledStatus; + type Source = PleromaEntity.Source; + type Stats = PleromaEntity.Stats; + type Status = PleromaEntity.Status; + type StatusParams = PleromaEntity.StatusParams; + type Tag = PleromaEntity.Tag; + type Token = PleromaEntity.Token; + type URLs = PleromaEntity.URLs; + } + namespace Converter { + const decodeNotificationType: (t: PleromaEntity.NotificationType) => MegalodonEntity.NotificationType; + const encodeNotificationType: (t: MegalodonEntity.NotificationType) => PleromaEntity.NotificationType; + const account: (a: Entity.Account) => MegalodonEntity.Account; + const activity: (a: Entity.Activity) => MegalodonEntity.Activity; + const announcement: (a: Entity.Announcement) => MegalodonEntity.Announcement; + const application: (a: Entity.Application) => MegalodonEntity.Application; + const attachment: (a: Entity.Attachment) => MegalodonEntity.Attachment; + const async_attachment: (a: Entity.AsyncAttachment) => MegalodonEntity.Attachment | MegalodonEntity.AsyncAttachment; + const card: (c: Entity.Card) => MegalodonEntity.Card; + const context: (c: Entity.Context) => MegalodonEntity.Context; + const conversation: (c: Entity.Conversation) => MegalodonEntity.Conversation; + const emoji: (e: Entity.Emoji) => MegalodonEntity.Emoji; + const featured_tag: (f: Entity.FeaturedTag) => MegalodonEntity.FeaturedTag; + const field: (f: Entity.Field) => MegalodonEntity.Field; + const filter: (f: Entity.Filter) => MegalodonEntity.Filter; + const history: (h: Entity.History) => MegalodonEntity.History; + const identity_proof: (i: Entity.IdentityProof) => MegalodonEntity.IdentityProof; + const instance: (i: Entity.Instance) => MegalodonEntity.Instance; + const list: (l: Entity.List) => MegalodonEntity.List; + const marker: (m: Entity.Marker) => MegalodonEntity.Marker; + const mention: (m: Entity.Mention) => MegalodonEntity.Mention; + const notification: (n: Entity.Notification) => MegalodonEntity.Notification; + const poll: (p: Entity.Poll) => MegalodonEntity.Poll; + const pollOption: (p: Entity.PollOption) => MegalodonEntity.PollOption; + const preferences: (p: Entity.Preferences) => MegalodonEntity.Preferences; + const push_subscription: (p: Entity.PushSubscription) => MegalodonEntity.PushSubscription; + const reaction: (r: Entity.Reaction) => MegalodonEntity.Reaction; + const relationship: (r: Entity.Relationship) => MegalodonEntity.Relationship; + const report: (r: Entity.Report) => MegalodonEntity.Report; + const results: (r: Entity.Results) => MegalodonEntity.Results; + const scheduled_status: (s: Entity.ScheduledStatus) => MegalodonEntity.ScheduledStatus; + const source: (s: Entity.Source) => MegalodonEntity.Source; + const stats: (s: Entity.Stats) => MegalodonEntity.Stats; + const status: (s: Entity.Status) => MegalodonEntity.Status; + const status_params: (s: Entity.StatusParams) => MegalodonEntity.StatusParams; + const tag: (t: Entity.Tag) => MegalodonEntity.Tag; + const token: (t: Entity.Token) => MegalodonEntity.Token; + const urls: (u: Entity.URLs) => MegalodonEntity.URLs; + } + interface Interface { + get(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + put(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + putForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + patch(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + patchForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + post(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + postForm(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + del(path: string, params?: any, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(path: string, stream: string, params?: string): WebSocket; + } + class Client implements Interface { + static DEFAULT_SCOPE: string[]; + static DEFAULT_URL: string; + static NO_REDIRECT: string; + private accessToken; + private baseUrl; + private userAgent; + private abortController; + private proxyConfig; + constructor(baseUrl: string, accessToken?: string | null, userAgent?: string, proxyConfig?: ProxyConfig | false); + get(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + put(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + putForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + patch(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + patchForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + post(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + postForm(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + del(path: string, params?: {}, headers?: { + [key: string]: string; + }): Promise>; + cancel(): void; + socket(path: string, stream: string, params?: string): WebSocket; + } +} +export default PleromaAPI; diff --git a/packages/megalodon/lib/src/pleroma/api_client.js b/packages/megalodon/lib/src/pleroma/api_client.js new file mode 100644 index 000000000..2878735f8 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/api_client.js @@ -0,0 +1,632 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var axios_1 = __importDefault(require("axios")); +var object_assign_deep_1 = __importDefault(require("object-assign-deep")); +var cancel_1 = require("../cancel"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var default_1 = require("../default"); +var web_socket_1 = __importDefault(require("./web_socket")); +var notification_1 = __importDefault(require("../notification")); +var notification_2 = __importDefault(require("./notification")); +var PleromaAPI; +(function (PleromaAPI) { + var Converter; + (function (Converter) { + Converter.decodeNotificationType = function (t) { + switch (t) { + case notification_2.default.Mention: + return notification_1.default.Mention; + case notification_2.default.Reblog: + return notification_1.default.Reblog; + case notification_2.default.Favourite: + return notification_1.default.Favourite; + case notification_2.default.Follow: + return notification_1.default.Follow; + case notification_2.default.Poll: + return notification_1.default.PollExpired; + case notification_2.default.PleromaEmojiReaction: + return notification_1.default.EmojiReaction; + case notification_2.default.FollowRequest: + return notification_1.default.FollowRequest; + default: + return t; + } + }; + Converter.encodeNotificationType = function (t) { + switch (t) { + case notification_1.default.Follow: + return notification_2.default.Follow; + case notification_1.default.Favourite: + return notification_2.default.Favourite; + case notification_1.default.Reblog: + return notification_2.default.Reblog; + case notification_1.default.Mention: + return notification_2.default.Mention; + case notification_1.default.PollExpired: + return notification_2.default.Poll; + case notification_1.default.EmojiReaction: + return notification_2.default.PleromaEmojiReaction; + case notification_1.default.FollowRequest: + return notification_2.default.FollowRequest; + default: + return t; + } + }; + Converter.account = function (a) { return a; }; + Converter.activity = function (a) { return a; }; + Converter.announcement = function (a) { return a; }; + Converter.application = function (a) { return a; }; + Converter.attachment = function (a) { return a; }; + Converter.async_attachment = function (a) { + if (a.url) { + return { + id: a.id, + type: a.type, + url: a.url, + remote_url: a.remote_url, + preview_url: a.preview_url, + text_url: a.text_url, + meta: a.meta, + description: a.description, + blurhash: a.blurhash + }; + } + else { + return a; + } + }; + Converter.card = function (c) { return c; }; + Converter.context = function (c) { return ({ + ancestors: c.ancestors.map(function (a) { return Converter.status(a); }), + descendants: c.descendants.map(function (d) { return Converter.status(d); }) + }); }; + Converter.conversation = function (c) { return ({ + id: c.id, + accounts: c.accounts.map(function (a) { return Converter.account(a); }), + last_status: c.last_status ? Converter.status(c.last_status) : null, + unread: c.unread + }); }; + Converter.emoji = function (e) { return e; }; + Converter.featured_tag = function (f) { return f; }; + Converter.field = function (f) { return f; }; + Converter.filter = function (f) { return f; }; + Converter.history = function (h) { return h; }; + Converter.identity_proof = function (i) { return i; }; + Converter.instance = function (i) { return i; }; + Converter.list = function (l) { return l; }; + Converter.marker = function (m) { + return { + notifications: { + last_read_id: m.notifications.last_read_id, + version: m.notifications.version, + updated_at: m.notifications.updated_at, + unread_count: m.notifications.pleroma.unread_count + } + }; + }; + Converter.mention = function (m) { return m; }; + Converter.notification = function (n) { + if (n.status && n.emoji) { + return { + id: n.id, + account: n.account, + created_at: n.created_at, + status: Converter.status(n.status), + emoji: n.emoji, + type: Converter.decodeNotificationType(n.type) + }; + } + else if (n.status) { + return { + id: n.id, + account: n.account, + created_at: n.created_at, + status: Converter.status(n.status), + type: Converter.decodeNotificationType(n.type) + }; + } + else { + return { + id: n.id, + account: n.account, + created_at: n.created_at, + type: Converter.decodeNotificationType(n.type) + }; + } + }; + Converter.poll = function (p) { return p; }; + Converter.pollOption = function (p) { return p; }; + Converter.preferences = function (p) { return p; }; + Converter.push_subscription = function (p) { return p; }; + Converter.reaction = function (r) { return r; }; + Converter.relationship = function (r) { return ({ + id: r.id, + following: r.following, + followed_by: r.followed_by, + blocking: r.blocking, + blocked_by: r.blocked_by, + muting: r.muting, + muting_notifications: r.muting_notifications, + requested: r.requested, + domain_blocking: r.domain_blocking, + showing_reblogs: r.showing_reblogs, + endorsed: r.endorsed, + notifying: r.subscribing + }); }; + Converter.report = function (r) { return r; }; + Converter.results = function (r) { return ({ + accounts: r.accounts.map(function (a) { return Converter.account(a); }), + statuses: r.statuses.map(function (s) { return Converter.status(s); }), + hashtags: r.hashtags.map(function (h) { return Converter.tag(h); }) + }); }; + Converter.scheduled_status = function (s) { return ({ + id: s.id, + scheduled_at: s.scheduled_at, + params: s.params, + media_attachments: s.media_attachments.map(function (m) { return Converter.attachment(m); }) + }); }; + Converter.source = function (s) { return s; }; + Converter.stats = function (s) { return s; }; + Converter.status = function (s) { + var _a; + return ({ + id: s.id, + uri: s.uri, + url: s.url, + account: Converter.account(s.account), + in_reply_to_id: s.in_reply_to_id, + in_reply_to_account_id: s.in_reply_to_account_id, + reblog: s.reblog ? Converter.status(s.reblog) : null, + content: s.content, + plain_content: ((_a = s.pleroma.content) === null || _a === void 0 ? void 0 : _a['text/plain']) ? s.pleroma.content['text/plain'] : null, + created_at: s.created_at, + emojis: s.emojis.map(function (e) { return Converter.emoji(e); }), + replies_count: s.replies_count, + reblogs_count: s.reblogs_count, + favourites_count: s.favourites_count, + reblogged: s.reblogged, + favourited: s.favourited, + muted: s.muted, + sensitive: s.sensitive, + spoiler_text: s.spoiler_text, + visibility: s.visibility, + media_attachments: s.media_attachments.map(function (m) { return Converter.attachment(m); }), + mentions: s.mentions.map(function (m) { return Converter.mention(m); }), + tags: s.tags.map(function (t) { return Converter.tag(t); }), + card: s.card ? Converter.card(s.card) : null, + poll: s.poll ? Converter.poll(s.poll) : null, + application: s.application ? Converter.application(s.application) : null, + language: s.language, + pinned: s.pinned, + emoji_reactions: s.pleroma.emoji_reactions ? s.pleroma.emoji_reactions.map(function (r) { return Converter.reaction(r); }) : [], + bookmarked: s.bookmarked ? s.bookmarked : false, + quote: null + }); + }; + Converter.status_params = function (s) { return s; }; + Converter.tag = function (t) { return t; }; + Converter.token = function (t) { return t; }; + Converter.urls = function (u) { return u; }; + })(Converter = PleromaAPI.Converter || (PleromaAPI.Converter = {})); + var Client = (function () { + function Client(baseUrl, accessToken, userAgent, proxyConfig) { + if (accessToken === void 0) { accessToken = null; } + if (userAgent === void 0) { userAgent = default_1.DEFAULT_UA; } + if (proxyConfig === void 0) { proxyConfig = false; } + this.proxyConfig = false; + this.accessToken = accessToken; + this.baseUrl = baseUrl; + this.userAgent = userAgent; + this.proxyConfig = proxyConfig; + this.abortController = new AbortController(); + axios_1.default.defaults.signal = this.abortController.signal; + } + Client.prototype.get = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + params: params, + headers: headers + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .get(this.baseUrl + path, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.put = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .put(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.putForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .putForm(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.patch = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .patch(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.patchForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .patchForm(this.baseUrl + path, params, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.post = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default.post(this.baseUrl + path, params, options).then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.postForm = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default.postForm(this.baseUrl + path, params, options).then(function (resp) { + var res = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + }; + return res; + })]; + }); + }); + }; + Client.prototype.del = function (path, params, headers) { + if (params === void 0) { params = {}; } + if (headers === void 0) { headers = {}; } + return __awaiter(this, void 0, void 0, function () { + var options; + return __generator(this, function (_a) { + options = { + data: params, + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + }; + if (this.accessToken) { + options = (0, object_assign_deep_1.default)({}, options, { + headers: { + Authorization: "Bearer ".concat(this.accessToken) + } + }); + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: (0, proxy_config_1.default)(this.proxyConfig), + httpsAgent: (0, proxy_config_1.default)(this.proxyConfig) + }); + } + return [2, axios_1.default + .delete(this.baseUrl + path, options) + .catch(function (err) { + if (axios_1.default.isCancel(err)) { + throw new cancel_1.RequestCanceledError(err.message); + } + else { + throw err; + } + }) + .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 (path, stream, params) { + if (!this.accessToken) { + throw new Error('accessToken is required'); + } + var url = this.baseUrl + path; + var streaming = new web_socket_1.default(url, stream, params, this.accessToken, this.userAgent, this.proxyConfig); + process.nextTick(function () { + streaming.start(); + }); + return streaming; + }; + Client.DEFAULT_SCOPE = default_1.DEFAULT_SCOPE; + Client.DEFAULT_URL = 'https://pleroma.io'; + Client.NO_REDIRECT = default_1.NO_REDIRECT; + return Client; + }()); + PleromaAPI.Client = Client; +})(PleromaAPI || (PleromaAPI = {})); +exports.default = PleromaAPI; diff --git a/packages/megalodon/lib/src/pleroma/entities/account.d.ts b/packages/megalodon/lib/src/pleroma/entities/account.d.ts new file mode 100644 index 000000000..96f4f43b6 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/account.d.ts @@ -0,0 +1,27 @@ +/// +/// +/// +declare namespace PleromaEntity { + type Account = { + id: string; + username: string; + acct: string; + display_name: string; + locked: boolean; + created_at: string; + followers_count: number; + following_count: number; + statuses_count: number; + note: string; + url: string; + avatar: string; + avatar_static: string; + header: string; + header_static: string; + emojis: Array; + moved: Account | null; + fields: Array; + bot: boolean | null; + source?: Source; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/account.js b/packages/megalodon/lib/src/pleroma/entities/account.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/account.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/activity.d.ts b/packages/megalodon/lib/src/pleroma/entities/activity.d.ts new file mode 100644 index 000000000..34c5ecfb0 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/activity.d.ts @@ -0,0 +1,8 @@ +declare namespace PleromaEntity { + type Activity = { + week: string; + statuses: string; + logins: string; + registrations: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/activity.js b/packages/megalodon/lib/src/pleroma/entities/activity.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/activity.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/announcement.d.ts b/packages/megalodon/lib/src/pleroma/entities/announcement.d.ts new file mode 100644 index 000000000..624cac36a --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/announcement.d.ts @@ -0,0 +1,31 @@ +/// +/// +/// +declare namespace PleromaEntity { + type Announcement = { + id: string; + content: string; + starts_at: string | null; + ends_at: string | null; + published: boolean; + all_day: boolean; + published_at: string; + updated_at: string; + read?: boolean; + mentions: Array; + statuses: Array; + tags: Array; + emojis: Array; + reactions: Array; + }; + type AnnouncementAccount = { + id: string; + username: string; + url: string; + acct: string; + }; + type AnnouncementStatus = { + id: string; + url: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/announcement.js b/packages/megalodon/lib/src/pleroma/entities/announcement.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/announcement.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/application.d.ts b/packages/megalodon/lib/src/pleroma/entities/application.d.ts new file mode 100644 index 000000000..d6c91c695 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/application.d.ts @@ -0,0 +1,7 @@ +declare namespace PleromaEntity { + type Application = { + name: string; + website?: string | null; + vapid_key?: string | null; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/application.js b/packages/megalodon/lib/src/pleroma/entities/application.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/application.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/async_attachment.d.ts b/packages/megalodon/lib/src/pleroma/entities/async_attachment.d.ts new file mode 100644 index 000000000..65ea109bd --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/async_attachment.d.ts @@ -0,0 +1,14 @@ +/// +declare namespace PleromaEntity { + type AsyncAttachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string | null; + remote_url: string | null; + preview_url: string; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/async_attachment.js b/packages/megalodon/lib/src/pleroma/entities/async_attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/async_attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/attachment.d.ts b/packages/megalodon/lib/src/pleroma/entities/attachment.d.ts new file mode 100644 index 000000000..5ed99d343 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/attachment.d.ts @@ -0,0 +1,41 @@ +declare namespace PleromaEntity { + type Sub = { + width?: number; + height?: number; + size?: string; + aspect?: number; + frame_rate?: string; + duration?: number; + bitrate?: number; + }; + type Focus = { + x: number; + y: number; + }; + type Meta = { + original?: Sub; + small?: Sub; + focus?: Focus; + length?: string; + duration?: number; + fps?: number; + size?: string; + width?: number; + height?: number; + aspect?: number; + audio_encode?: string; + audio_bitrate?: string; + audio_channel?: string; + }; + type Attachment = { + id: string; + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio'; + url: string; + remote_url: string | null; + preview_url: string | null; + text_url: string | null; + meta: Meta | null; + description: string | null; + blurhash: string | null; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/attachment.js b/packages/megalodon/lib/src/pleroma/entities/attachment.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/attachment.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/card.d.ts b/packages/megalodon/lib/src/pleroma/entities/card.d.ts new file mode 100644 index 000000000..eb2415303 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/card.d.ts @@ -0,0 +1,17 @@ +declare namespace PleromaEntity { + type Card = { + url: string; + title: string; + description: string; + type: 'link' | 'photo' | 'video' | 'rich'; + image?: string; + author_name?: string; + author_url?: string; + provider_name?: string; + provider_url?: string; + html?: string; + width?: number; + height?: number; + pleroma?: Object; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/card.js b/packages/megalodon/lib/src/pleroma/entities/card.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/card.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/context.d.ts b/packages/megalodon/lib/src/pleroma/entities/context.d.ts new file mode 100644 index 000000000..888d2ce77 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/context.d.ts @@ -0,0 +1,7 @@ +/// +declare namespace PleromaEntity { + type Context = { + ancestors: Array; + descendants: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/context.js b/packages/megalodon/lib/src/pleroma/entities/context.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/context.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/conversation.d.ts b/packages/megalodon/lib/src/pleroma/entities/conversation.d.ts new file mode 100644 index 000000000..f65b57974 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/conversation.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace PleromaEntity { + type Conversation = { + id: string; + accounts: Array; + last_status: Status | null; + unread: boolean; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/conversation.js b/packages/megalodon/lib/src/pleroma/entities/conversation.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/conversation.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/emoji.d.ts b/packages/megalodon/lib/src/pleroma/entities/emoji.d.ts new file mode 100644 index 000000000..a97d5c9dd --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/emoji.d.ts @@ -0,0 +1,9 @@ +declare namespace PleromaEntity { + type Emoji = { + shortcode: string; + static_url: string; + url: string; + visible_in_picker: boolean; + category: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/emoji.js b/packages/megalodon/lib/src/pleroma/entities/emoji.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/emoji.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/featured_tag.d.ts b/packages/megalodon/lib/src/pleroma/entities/featured_tag.d.ts new file mode 100644 index 000000000..a783d0da3 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/featured_tag.d.ts @@ -0,0 +1,8 @@ +declare namespace PleromaEntity { + type FeaturedTag = { + id: string; + name: string; + statuses_count: number; + last_status_at: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/featured_tag.js b/packages/megalodon/lib/src/pleroma/entities/featured_tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/featured_tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/field.d.ts b/packages/megalodon/lib/src/pleroma/entities/field.d.ts new file mode 100644 index 000000000..a66dbf645 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/field.d.ts @@ -0,0 +1,7 @@ +declare namespace PleromaEntity { + type Field = { + name: string; + value: string; + verified_at: string | null; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/field.js b/packages/megalodon/lib/src/pleroma/entities/field.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/field.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/filter.d.ts b/packages/megalodon/lib/src/pleroma/entities/filter.d.ts new file mode 100644 index 000000000..d59cb56cc --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/filter.d.ts @@ -0,0 +1,11 @@ +declare namespace PleromaEntity { + type Filter = { + id: string; + phrase: string; + context: Array; + expires_at: string | null; + irreversible: boolean; + whole_word: boolean; + }; + type FilterContext = string; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/filter.js b/packages/megalodon/lib/src/pleroma/entities/filter.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/filter.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/history.d.ts b/packages/megalodon/lib/src/pleroma/entities/history.d.ts new file mode 100644 index 000000000..12ee93cbf --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/history.d.ts @@ -0,0 +1,7 @@ +declare namespace PleromaEntity { + type History = { + day: string; + uses: number; + accounts: number; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/history.js b/packages/megalodon/lib/src/pleroma/entities/history.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/history.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/identity_proof.d.ts b/packages/megalodon/lib/src/pleroma/entities/identity_proof.d.ts new file mode 100644 index 000000000..519521513 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/identity_proof.d.ts @@ -0,0 +1,9 @@ +declare namespace PleromaEntity { + type IdentityProof = { + provider: string; + provider_username: string; + updated_at: string; + proof_url: string; + profile_url: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/identity_proof.js b/packages/megalodon/lib/src/pleroma/entities/identity_proof.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/identity_proof.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/instance.d.ts b/packages/megalodon/lib/src/pleroma/entities/instance.d.ts new file mode 100644 index 000000000..24c6d489b --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/instance.d.ts @@ -0,0 +1,40 @@ +/// +/// +/// +declare namespace PleromaEntity { + type Instance = { + uri: string; + title: string; + description: string; + email: string; + version: string; + thumbnail: string | null; + urls: URLs; + stats: Stats; + languages: Array; + contact_account: Account | null; + max_toot_chars?: number; + registrations?: boolean; + configuration?: { + statuses: { + max_characters: number; + max_media_attachments: number; + characters_reserved_per_url: number; + }; + media_attachments: { + supported_mime_types: Array; + image_size_limit: number; + image_matrix_limit: number; + video_size_limit: number; + video_frame_limit: number; + video_matrix_limit: number; + }; + polls: { + max_options: number; + max_characters_per_option: number; + min_expiration: number; + max_expiration: number; + }; + }; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/instance.js b/packages/megalodon/lib/src/pleroma/entities/instance.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/instance.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/list.d.ts b/packages/megalodon/lib/src/pleroma/entities/list.d.ts new file mode 100644 index 000000000..aa8429d8f --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/list.d.ts @@ -0,0 +1,6 @@ +declare namespace PleromaEntity { + type List = { + id: string; + title: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/list.js b/packages/megalodon/lib/src/pleroma/entities/list.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/list.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/marker.d.ts b/packages/megalodon/lib/src/pleroma/entities/marker.d.ts new file mode 100644 index 000000000..7a79f392f --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/marker.d.ts @@ -0,0 +1,12 @@ +declare namespace PleromaEntity { + type Marker = { + notifications: { + last_read_id: string; + version: number; + updated_at: string; + pleroma: { + unread_count: number; + }; + }; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/marker.js b/packages/megalodon/lib/src/pleroma/entities/marker.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/marker.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/mention.d.ts b/packages/megalodon/lib/src/pleroma/entities/mention.d.ts new file mode 100644 index 000000000..3fde306c6 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/mention.d.ts @@ -0,0 +1,8 @@ +declare namespace PleromaEntity { + type Mention = { + id: string; + username: string; + url: string; + acct: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/mention.js b/packages/megalodon/lib/src/pleroma/entities/mention.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/mention.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/notification.d.ts b/packages/megalodon/lib/src/pleroma/entities/notification.d.ts new file mode 100644 index 000000000..02ddf0866 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/notification.d.ts @@ -0,0 +1,13 @@ +/// +/// +declare namespace PleromaEntity { + type Notification = { + account: Account; + created_at: string; + id: string; + status?: Status; + emoji?: string; + type: NotificationType; + }; + type NotificationType = string; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/notification.js b/packages/megalodon/lib/src/pleroma/entities/notification.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/notification.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/poll.d.ts b/packages/megalodon/lib/src/pleroma/entities/poll.d.ts new file mode 100644 index 000000000..0ec209510 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/poll.d.ts @@ -0,0 +1,12 @@ +/// +declare namespace PleromaEntity { + type Poll = { + id: string; + expires_at: string | null; + expired: boolean; + multiple: boolean; + votes_count: number; + options: Array; + voted: boolean; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/poll.js b/packages/megalodon/lib/src/pleroma/entities/poll.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/poll.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/poll_option.d.ts b/packages/megalodon/lib/src/pleroma/entities/poll_option.d.ts new file mode 100644 index 000000000..6714d51bd --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/poll_option.d.ts @@ -0,0 +1,6 @@ +declare namespace PleromaEntity { + type PollOption = { + title: string; + votes_count: number | null; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/poll_option.js b/packages/megalodon/lib/src/pleroma/entities/poll_option.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/poll_option.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/preferences.d.ts b/packages/megalodon/lib/src/pleroma/entities/preferences.d.ts new file mode 100644 index 000000000..d8cf7d2a2 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/preferences.d.ts @@ -0,0 +1,9 @@ +declare namespace PleromaEntity { + type Preferences = { + 'posting:default:visibility': 'public' | 'unlisted' | 'private' | 'direct'; + 'posting:default:sensitive': boolean; + 'posting:default:language': string | null; + 'reading:expand:media': 'default' | 'show_all' | 'hide_all'; + 'reading:expand:spoilers': boolean; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/preferences.js b/packages/megalodon/lib/src/pleroma/entities/preferences.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/preferences.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/push_subscription.d.ts b/packages/megalodon/lib/src/pleroma/entities/push_subscription.d.ts new file mode 100644 index 000000000..221f49820 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/push_subscription.d.ts @@ -0,0 +1,15 @@ +declare namespace PleromaEntity { + type Alerts = { + follow: boolean; + favourite: boolean; + mention: boolean; + reblog: boolean; + poll: boolean; + }; + type PushSubscription = { + id: string; + endpoint: string; + server_key: string; + alerts: Alerts; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/push_subscription.js b/packages/megalodon/lib/src/pleroma/entities/push_subscription.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/push_subscription.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/reaction.d.ts b/packages/megalodon/lib/src/pleroma/entities/reaction.d.ts new file mode 100644 index 000000000..6c7315d0e --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/reaction.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace PleromaEntity { + type Reaction = { + count: number; + me: boolean; + name: string; + accounts?: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/reaction.js b/packages/megalodon/lib/src/pleroma/entities/reaction.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/reaction.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/relationship.d.ts b/packages/megalodon/lib/src/pleroma/entities/relationship.d.ts new file mode 100644 index 000000000..4a830e7f1 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/relationship.d.ts @@ -0,0 +1,16 @@ +declare namespace PleromaEntity { + type Relationship = { + id: string; + following: boolean; + followed_by: boolean; + blocking: boolean; + blocked_by: boolean; + muting: boolean; + muting_notifications: boolean; + requested: boolean; + domain_blocking: boolean; + showing_reblogs: boolean; + endorsed: boolean; + subscribing: boolean; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/relationship.js b/packages/megalodon/lib/src/pleroma/entities/relationship.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/relationship.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/report.d.ts b/packages/megalodon/lib/src/pleroma/entities/report.d.ts new file mode 100644 index 000000000..1d8b383ef --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/report.d.ts @@ -0,0 +1,9 @@ +declare namespace PleromaEntity { + type Report = { + id: string; + action_taken: string; + comment: string; + account_id: string; + status_ids: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/report.js b/packages/megalodon/lib/src/pleroma/entities/report.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/report.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/results.d.ts b/packages/megalodon/lib/src/pleroma/entities/results.d.ts new file mode 100644 index 000000000..44fac696d --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/results.d.ts @@ -0,0 +1,10 @@ +/// +/// +/// +declare namespace PleromaEntity { + type Results = { + accounts: Array; + statuses: Array; + hashtags: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/results.js b/packages/megalodon/lib/src/pleroma/entities/results.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/results.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/scheduled_status.d.ts b/packages/megalodon/lib/src/pleroma/entities/scheduled_status.d.ts new file mode 100644 index 000000000..12b15029d --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/scheduled_status.d.ts @@ -0,0 +1,10 @@ +/// +/// +declare namespace PleromaEntity { + type ScheduledStatus = { + id: string; + scheduled_at: string; + params: StatusParams; + media_attachments: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/scheduled_status.js b/packages/megalodon/lib/src/pleroma/entities/scheduled_status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/scheduled_status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/source.d.ts b/packages/megalodon/lib/src/pleroma/entities/source.d.ts new file mode 100644 index 000000000..aa05282e1 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/source.d.ts @@ -0,0 +1,10 @@ +/// +declare namespace PleromaEntity { + type Source = { + privacy: string | null; + sensitive: boolean | null; + language: string | null; + note: string; + fields: Array; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/source.js b/packages/megalodon/lib/src/pleroma/entities/source.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/source.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/stats.d.ts b/packages/megalodon/lib/src/pleroma/entities/stats.d.ts new file mode 100644 index 000000000..ddceb5496 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/stats.d.ts @@ -0,0 +1,7 @@ +declare namespace PleromaEntity { + type Stats = { + user_count: number; + status_count: number; + domain_count: number; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/stats.js b/packages/megalodon/lib/src/pleroma/entities/stats.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/stats.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/status.d.ts b/packages/megalodon/lib/src/pleroma/entities/status.d.ts new file mode 100644 index 000000000..e49bfaa0a --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/status.d.ts @@ -0,0 +1,58 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +declare namespace PleromaEntity { + type Status = { + id: string; + uri: string; + url: string; + account: Account; + in_reply_to_id: string | null; + in_reply_to_account_id: string | null; + reblog: Status | null; + content: string; + created_at: string; + emojis: Emoji[]; + replies_count: number; + reblogs_count: number; + favourites_count: number; + reblogged: boolean | null; + favourited: boolean | null; + muted: boolean | null; + sensitive: boolean; + spoiler_text: string; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + media_attachments: Array; + mentions: Array; + tags: Array; + card: Card | null; + poll: Poll | null; + application: Application | null; + language: string | null; + pinned: boolean | null; + bookmarked?: boolean; + pleroma: { + content?: { + 'text/plain': string; + }; + spoiler_text?: { + 'text/plain': string; + }; + conversation_id?: number; + direct_conversation_id?: number | null; + emoji_reactions?: Array; + expires_at?: string; + in_reply_to_account_acct?: string; + local: boolean; + parent_visible?: boolean; + pinned_at?: string; + thread_muted?: boolean; + }; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/status.js b/packages/megalodon/lib/src/pleroma/entities/status.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/status.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/status_params.d.ts b/packages/megalodon/lib/src/pleroma/entities/status_params.d.ts new file mode 100644 index 000000000..56252e5e6 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/status_params.d.ts @@ -0,0 +1,12 @@ +declare namespace PleromaEntity { + type StatusParams = { + text: string; + in_reply_to_id: string | null; + media_ids: Array | null; + sensitive: boolean | null; + spoiler_text: string | null; + visibility: 'public' | 'unlisted' | 'private' | 'direct'; + scheduled_at: string | null; + application_id: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/status_params.js b/packages/megalodon/lib/src/pleroma/entities/status_params.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/status_params.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/tag.d.ts b/packages/megalodon/lib/src/pleroma/entities/tag.d.ts new file mode 100644 index 000000000..aa7ba9477 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/tag.d.ts @@ -0,0 +1,9 @@ +/// +declare namespace PleromaEntity { + type Tag = { + name: string; + url: string; + history: Array | null; + following?: boolean; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/tag.js b/packages/megalodon/lib/src/pleroma/entities/tag.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/tag.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/token.d.ts b/packages/megalodon/lib/src/pleroma/entities/token.d.ts new file mode 100644 index 000000000..f341f9f69 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/token.d.ts @@ -0,0 +1,8 @@ +declare namespace PleromaEntity { + type Token = { + access_token: string; + token_type: string; + scope: string; + created_at: number; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/token.js b/packages/megalodon/lib/src/pleroma/entities/token.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/token.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entities/urls.d.ts b/packages/megalodon/lib/src/pleroma/entities/urls.d.ts new file mode 100644 index 000000000..53960cbdd --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/urls.d.ts @@ -0,0 +1,5 @@ +declare namespace PleromaEntity { + type URLs = { + streaming_api: string; + }; +} diff --git a/packages/megalodon/lib/src/pleroma/entities/urls.js b/packages/megalodon/lib/src/pleroma/entities/urls.js new file mode 100644 index 000000000..3918c74e4 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entities/urls.js @@ -0,0 +1 @@ +"use strict"; diff --git a/packages/megalodon/lib/src/pleroma/entity.d.ts b/packages/megalodon/lib/src/pleroma/entity.d.ts new file mode 100644 index 000000000..08a7f15d1 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entity.d.ts @@ -0,0 +1,37 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +export default PleromaEntity; diff --git a/packages/megalodon/lib/src/pleroma/entity.js b/packages/megalodon/lib/src/pleroma/entity.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/entity.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/src/pleroma/notification.d.ts b/packages/megalodon/lib/src/pleroma/notification.d.ts new file mode 100644 index 000000000..7645aea65 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/notification.d.ts @@ -0,0 +1,11 @@ +import PleromaEntity from './entity'; +declare namespace PleromaNotificationType { + const Mention: PleromaEntity.NotificationType; + const Reblog: PleromaEntity.NotificationType; + const Favourite: PleromaEntity.NotificationType; + const Follow: PleromaEntity.NotificationType; + const Poll: PleromaEntity.NotificationType; + const PleromaEmojiReaction: PleromaEntity.NotificationType; + const FollowRequest: PleromaEntity.NotificationType; +} +export default PleromaNotificationType; diff --git a/packages/megalodon/lib/src/pleroma/notification.js b/packages/megalodon/lib/src/pleroma/notification.js new file mode 100644 index 000000000..fa9499ca3 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/notification.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var PleromaNotificationType; +(function (PleromaNotificationType) { + PleromaNotificationType.Mention = 'mention'; + PleromaNotificationType.Reblog = 'reblog'; + PleromaNotificationType.Favourite = 'favourite'; + PleromaNotificationType.Follow = 'follow'; + PleromaNotificationType.Poll = 'poll'; + PleromaNotificationType.PleromaEmojiReaction = 'pleroma:emoji_reaction'; + PleromaNotificationType.FollowRequest = 'follow_request'; +})(PleromaNotificationType || (PleromaNotificationType = {})); +exports.default = PleromaNotificationType; diff --git a/packages/megalodon/lib/src/pleroma/web_socket.d.ts b/packages/megalodon/lib/src/pleroma/web_socket.d.ts new file mode 100644 index 000000000..639afab43 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/web_socket.d.ts @@ -0,0 +1,39 @@ +/// +import WS from 'ws'; +import { EventEmitter } from 'events'; +import { ProxyConfig } from '../proxy_config'; +import { WebSocketInterface } from '../megalodon'; +export default class WebSocket extends EventEmitter implements WebSocketInterface { + url: string; + stream: string; + params: string | null; + parser: Parser; + headers: { + [key: string]: string; + }; + proxyConfig: ProxyConfig | false; + private _accessToken; + private _reconnectInterval; + private _reconnectMaxAttempts; + private _reconnectCurrentAttempts; + private _connectionClosed; + private _client; + private _pongReceivedTimestamp; + private _heartbeatInterval; + private _pongWaiting; + constructor(url: string, stream: string, params: string | undefined, accessToken: string, userAgent: string, proxyConfig?: ProxyConfig | false); + start(): void; + private _startWebSocketConnection; + stop(): void; + private _resetConnection; + private _resetRetryParams; + private _reconnect; + private _connect; + private _clearBinding; + private _bindSocket; + private _setupParser; + private _checkAlive; +} +export declare class Parser extends EventEmitter { + parse(data: WS.Data, isBinary: boolean): void; +} diff --git a/packages/megalodon/lib/src/pleroma/web_socket.js b/packages/megalodon/lib/src/pleroma/web_socket.js new file mode 100644 index 000000000..f37876729 --- /dev/null +++ b/packages/megalodon/lib/src/pleroma/web_socket.js @@ -0,0 +1,260 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Parser = void 0; +var ws_1 = __importDefault(require("ws")); +var dayjs_1 = __importDefault(require("dayjs")); +var events_1 = require("events"); +var proxy_config_1 = __importDefault(require("../proxy_config")); +var api_client_1 = __importDefault(require("./api_client")); +var WebSocket = (function (_super) { + __extends(WebSocket, _super); + function WebSocket(url, stream, params, accessToken, userAgent, proxyConfig) { + if (proxyConfig === void 0) { proxyConfig = false; } + var _this = _super.call(this) || this; + _this.proxyConfig = false; + _this._heartbeatInterval = 60000; + _this._pongWaiting = false; + _this.url = url; + _this.stream = stream; + if (params === undefined) { + _this.params = null; + } + else { + _this.params = params; + } + _this.parser = new Parser(); + _this.headers = { + 'User-Agent': userAgent + }; + _this.proxyConfig = proxyConfig; + _this._accessToken = accessToken; + _this._reconnectInterval = 10000; + _this._reconnectMaxAttempts = Infinity; + _this._reconnectCurrentAttempts = 0; + _this._connectionClosed = false; + _this._client = null; + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + return _this; + } + WebSocket.prototype.start = function () { + this._connectionClosed = false; + this._resetRetryParams(); + this._startWebSocketConnection(); + }; + WebSocket.prototype._startWebSocketConnection = function () { + this._resetConnection(); + this._setupParser(); + this._client = this._connect(this.url, this.stream, this.params, this._accessToken, this.headers, this.proxyConfig); + this._bindSocket(this._client); + }; + WebSocket.prototype.stop = function () { + this._connectionClosed = true; + this._resetConnection(); + this._resetRetryParams(); + }; + WebSocket.prototype._resetConnection = function () { + if (this._client) { + this._client.close(1000); + this._client.removeAllListeners(); + this._client = null; + } + if (this.parser) { + this.parser.removeAllListeners(); + } + }; + WebSocket.prototype._resetRetryParams = function () { + this._reconnectCurrentAttempts = 0; + }; + WebSocket.prototype._reconnect = function () { + var _this = this; + setTimeout(function () { + if (_this._client && _this._client.readyState === ws_1.default.CONNECTING) { + return; + } + if (_this._reconnectCurrentAttempts < _this._reconnectMaxAttempts) { + _this._reconnectCurrentAttempts++; + _this._clearBinding(); + if (_this._client) { + _this._client.terminate(); + } + console.log('Reconnecting'); + _this._client = _this._connect(_this.url, _this.stream, _this.params, _this._accessToken, _this.headers, _this.proxyConfig); + _this._bindSocket(_this._client); + } + }, this._reconnectInterval); + }; + WebSocket.prototype._connect = function (url, stream, params, accessToken, headers, proxyConfig) { + var parameter = ["stream=".concat(stream)]; + if (params) { + parameter.push(params); + } + if (accessToken !== null) { + parameter.push("access_token=".concat(accessToken)); + } + var requestURL = "".concat(url, "/?").concat(parameter.join('&')); + var options = { + headers: headers + }; + if (proxyConfig) { + options = Object.assign(options, { + agent: (0, proxy_config_1.default)(proxyConfig) + }); + } + var cli = new ws_1.default(requestURL, options); + return cli; + }; + WebSocket.prototype._clearBinding = function () { + if (this._client) { + this._client.removeAllListeners('close'); + this._client.removeAllListeners('pong'); + this._client.removeAllListeners('open'); + this._client.removeAllListeners('message'); + this._client.removeAllListeners('error'); + } + }; + WebSocket.prototype._bindSocket = function (client) { + var _this = this; + client.on('close', function (code, _reason) { + if (code === 1000) { + _this.emit('close', {}); + } + else { + console.log("Closed connection with ".concat(code)); + if (!_this._connectionClosed) { + _this._reconnect(); + } + } + }); + client.on('pong', function () { + _this._pongWaiting = false; + _this.emit('pong', {}); + _this._pongReceivedTimestamp = (0, dayjs_1.default)(); + setTimeout(function () { return _this._checkAlive(_this._pongReceivedTimestamp); }, _this._heartbeatInterval); + }); + client.on('open', function () { + _this.emit('connect', {}); + setTimeout(function () { + client.ping(''); + }, 10000); + }); + client.on('message', function (data, isBinary) { + _this.parser.parse(data, isBinary); + }); + client.on('error', function (err) { + _this.emit('error', err); + }); + }; + WebSocket.prototype._setupParser = function () { + var _this = this; + this.parser.on('update', function (status) { + _this.emit('update', api_client_1.default.Converter.status(status)); + }); + this.parser.on('notification', function (notification) { + _this.emit('notification', api_client_1.default.Converter.notification(notification)); + }); + this.parser.on('delete', function (id) { + _this.emit('delete', id); + }); + this.parser.on('conversation', function (conversation) { + _this.emit('conversation', api_client_1.default.Converter.conversation(conversation)); + }); + this.parser.on('status_update', function (status) { + _this.emit('status_update', api_client_1.default.Converter.status(status)); + }); + this.parser.on('error', function (err) { + _this.emit('parser-error', err); + }); + this.parser.on('heartbeat', function (_) { + _this.emit('heartbeat', 'heartbeat'); + }); + }; + WebSocket.prototype._checkAlive = function (timestamp) { + var _this = this; + var now = (0, dayjs_1.default)(); + if (now.diff(timestamp) > this._heartbeatInterval - 1000 && !this._connectionClosed) { + if (this._client && this._client.readyState !== ws_1.default.CONNECTING) { + this._pongWaiting = true; + this._client.ping(''); + setTimeout(function () { + if (_this._pongWaiting) { + _this._pongWaiting = false; + _this._reconnect(); + } + }, 10000); + } + } + }; + return WebSocket; +}(events_1.EventEmitter)); +exports.default = WebSocket; +var Parser = (function (_super) { + __extends(Parser, _super); + function Parser() { + return _super !== null && _super.apply(this, arguments) || this; + } + Parser.prototype.parse = function (data, isBinary) { + var message = isBinary ? data : data.toString(); + if (typeof message !== 'string') { + this.emit('heartbeat', {}); + return; + } + if (message === '') { + this.emit('heartbeat', {}); + return; + } + var event = ''; + var payload = ''; + var mes = {}; + try { + var obj = JSON.parse(message); + event = obj.event; + payload = obj.payload; + mes = JSON.parse(payload); + } + catch (err) { + if (event !== 'delete') { + this.emit('error', new Error("Error parsing websocket reply: ".concat(message, ", error message: ").concat(err))); + return; + } + } + switch (event) { + case 'update': + this.emit('update', mes); + break; + case 'notification': + this.emit('notification', mes); + break; + case 'conversation': + this.emit('conversation', mes); + break; + case 'delete': + this.emit('delete', payload); + break; + case 'status.update': + this.emit('status_update', mes); + break; + default: + this.emit('error', new Error("Unknown event has received: ".concat(message))); + } + }; + return Parser; +}(events_1.EventEmitter)); +exports.Parser = Parser; diff --git a/packages/megalodon/lib/src/proxy_config.d.ts b/packages/megalodon/lib/src/proxy_config.d.ts new file mode 100644 index 000000000..a2ba7ded7 --- /dev/null +++ b/packages/megalodon/lib/src/proxy_config.d.ts @@ -0,0 +1,13 @@ +import { HttpsProxyAgent } from 'https-proxy-agent'; +import { SocksProxyAgent } from 'socks-proxy-agent'; +export type ProxyConfig = { + host: string; + port: number; + auth?: { + username: string; + password: string; + }; + protocol: 'http' | 'https' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' | 'socks'; +}; +declare const proxyAgent: (proxyConfig: ProxyConfig) => HttpsProxyAgent | SocksProxyAgent; +export default proxyAgent; diff --git a/packages/megalodon/lib/src/proxy_config.js b/packages/megalodon/lib/src/proxy_config.js new file mode 100644 index 000000000..d087c0f73 --- /dev/null +++ b/packages/megalodon/lib/src/proxy_config.js @@ -0,0 +1,94 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var https_proxy_agent_1 = require("https-proxy-agent"); +var socks_proxy_agent_1 = require("socks-proxy-agent"); +var ProxyProtocolError = (function (_super) { + __extends(ProxyProtocolError, _super); + function ProxyProtocolError() { + return _super !== null && _super.apply(this, arguments) || this; + } + return ProxyProtocolError; +}(Error)); +var proxyAgent = function (proxyConfig) { + switch (proxyConfig.protocol) { + case 'http': { + var options = { + host: proxyConfig.host, + port: proxyConfig.port, + secureProxy: false + }; + if (proxyConfig.auth) { + options = Object.assign(options, { + auth: "".concat(proxyConfig.auth.username, ":").concat(proxyConfig.auth.password) + }); + } + var httpsAgent = new https_proxy_agent_1.HttpsProxyAgent(options); + return httpsAgent; + } + case 'https': { + var options = { + host: proxyConfig.host, + port: proxyConfig.port, + secureProxy: true + }; + if (proxyConfig.auth) { + options = Object.assign(options, { + auth: "".concat(proxyConfig.auth.username, ":").concat(proxyConfig.auth.password) + }); + } + var httpsAgent = new https_proxy_agent_1.HttpsProxyAgent(options); + return httpsAgent; + } + case 'socks4': + case 'socks4a': { + var options = { + type: 4, + hostname: proxyConfig.host, + port: proxyConfig.port + }; + if (proxyConfig.auth) { + options = Object.assign(options, { + userId: proxyConfig.auth.username, + password: proxyConfig.auth.password + }); + } + var socksAgent = new socks_proxy_agent_1.SocksProxyAgent(options); + return socksAgent; + } + case 'socks5': + case 'socks5h': + case 'socks': { + var options = { + type: 5, + hostname: proxyConfig.host, + port: proxyConfig.port + }; + if (proxyConfig.auth) { + options = Object.assign(options, { + userId: proxyConfig.auth.username, + password: proxyConfig.auth.password + }); + } + var socksAgent = new socks_proxy_agent_1.SocksProxyAgent(options); + return socksAgent; + } + default: + throw new ProxyProtocolError('protocol is not accepted'); + } +}; +exports.default = proxyAgent; diff --git a/packages/megalodon/lib/src/response.d.ts b/packages/megalodon/lib/src/response.d.ts new file mode 100644 index 000000000..ad96223f7 --- /dev/null +++ b/packages/megalodon/lib/src/response.d.ts @@ -0,0 +1,7 @@ +type Response = { + data: T; + status: number; + statusText: string; + headers: any; +}; +export default Response; diff --git a/packages/megalodon/lib/src/response.js b/packages/megalodon/lib/src/response.js new file mode 100644 index 000000000..c8ad2e549 --- /dev/null +++ b/packages/megalodon/lib/src/response.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/packages/megalodon/lib/test/integration/cancel.spec.d.ts b/packages/megalodon/lib/test/integration/cancel.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/cancel.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/cancel.spec.js b/packages/megalodon/lib/test/integration/cancel.spec.js new file mode 100644 index 000000000..cc61e4429 --- /dev/null +++ b/packages/megalodon/lib/test/integration/cancel.spec.js @@ -0,0 +1,91 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("@/mastodon/api_client")); +var jest_worker_1 = require("jest-worker"); +jest.mock('axios', function () { + var mockAxios = jest.requireActual('axios'); + mockAxios.get = function (_path) { + return new Promise(function (resolve) { + setTimeout(function () { + console.log('hoge'); + resolve({ + data: 'hoge', + status: 200, + statusText: '200OK', + headers: [], + config: {} + }); + }, 5000); + }); + }; + return mockAxios; +}); +var worker = function (client) { return __awaiter(void 0, void 0, void 0, function () { + var w; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + w = new jest_worker_1.Worker(require.resolve('./cancelWorker.ts')); + return [4, w.cancel(client)]; + case 1: + _a.sent(); + return [2]; + } + }); +}); }; +describe.skip('cancel', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + it('should be raised', function () { return __awaiter(void 0, void 0, void 0, function () { + var getPromise; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + getPromise = client.get('/timelines/home'); + worker(client); + return [4, expect(getPromise).rejects.toThrow()]; + case 1: + _a.sent(); + return [2]; + } + }); + }); }); +}); diff --git a/packages/megalodon/lib/test/integration/cancelWorker.d.ts b/packages/megalodon/lib/test/integration/cancelWorker.d.ts new file mode 100644 index 000000000..ff4f6d1d4 --- /dev/null +++ b/packages/megalodon/lib/test/integration/cancelWorker.d.ts @@ -0,0 +1,2 @@ +import MastodonAPI from '@/mastodon/api_client'; +export declare function cancel(client: MastodonAPI.Client): any; diff --git a/packages/megalodon/lib/test/integration/cancelWorker.js b/packages/megalodon/lib/test/integration/cancelWorker.js new file mode 100644 index 000000000..a2bbcce8b --- /dev/null +++ b/packages/megalodon/lib/test/integration/cancelWorker.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cancel = void 0; +function cancel(client) { + return client.cancel(); +} +exports.cancel = cancel; diff --git a/packages/megalodon/lib/test/integration/mastodon.spec.d.ts b/packages/megalodon/lib/test/integration/mastodon.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/mastodon.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/mastodon.spec.js b/packages/megalodon/lib/test/integration/mastodon.spec.js new file mode 100644 index 000000000..5a94cd3c4 --- /dev/null +++ b/packages/megalodon/lib/test/integration/mastodon.spec.js @@ -0,0 +1,219 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var notification_1 = __importDefault(require("@/mastodon/notification")); +var mastodon_1 = __importDefault(require("@/mastodon")); +var notification_2 = __importDefault(require("@/notification")); +var axios_1 = __importDefault(require("axios")); +jest.mock('axios'); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +var status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + bookmarked: false +}; +var follow = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '1', + type: notification_1.default.Follow +}; +var favourite = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '2', + status: status, + type: notification_1.default.Favourite +}; +var mention = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '3', + status: status, + type: notification_1.default.Mention +}; +var reblog = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '4', + status: status, + type: notification_1.default.Reblog +}; +var poll = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '5', + type: notification_1.default.Poll +}; +var followRequest = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '6', + type: notification_1.default.FollowRequest +}; +var toot = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '7', + status: status, + type: notification_1.default.Status +}; +axios_1.default.CancelToken.source.mockImplementation(function () { + return { + token: { + throwIfRequested: function () { }, + promise: { + then: function () { }, + catch: function () { } + } + } + }; +}); +describe('getNotifications', function () { + var client = new mastodon_1.default('http://localhost', 'sample token'); + var cases = [ + { + event: follow, + expected: notification_2.default.Follow, + title: 'follow' + }, + { + event: favourite, + expected: notification_2.default.Favourite, + title: 'favourite' + }, + { + event: mention, + expected: notification_2.default.Mention, + title: 'mention' + }, + { + event: reblog, + expected: notification_2.default.Reblog, + title: 'reblog' + }, + { + event: poll, + expected: notification_2.default.PollExpired, + title: 'poll' + }, + { + event: followRequest, + expected: notification_2.default.FollowRequest, + title: 'followRequest' + }, + { + event: toot, + expected: notification_2.default.Status, + title: 'status' + } + ]; + cases.forEach(function (c) { + it("should be ".concat(c.title, " event"), function () { return __awaiter(void 0, void 0, void 0, function () { + var mockResponse, res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + mockResponse = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + axios_1.default.get.mockResolvedValue(mockResponse); + return [4, client.getNotifications()]; + case 1: + res = _a.sent(); + expect(res.data[0].type).toEqual(c.expected); + return [2]; + } + }); + }); }); + }); +}); diff --git a/packages/megalodon/lib/test/integration/mastodon/api_client.spec.d.ts b/packages/megalodon/lib/test/integration/mastodon/api_client.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/mastodon/api_client.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/mastodon/api_client.spec.js b/packages/megalodon/lib/test/integration/mastodon/api_client.spec.js new file mode 100644 index 000000000..90ded51cc --- /dev/null +++ b/packages/megalodon/lib/test/integration/mastodon/api_client.spec.js @@ -0,0 +1,242 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("@/mastodon/api_client")); +var axios_1 = __importDefault(require("axios")); +jest.mock('axios'); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +var status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + plain_content: null, + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + emoji_reactions: [], + bookmarked: false, + quote: null +}; +axios_1.default.CancelToken.source.mockImplementation(function () { + return { + token: { + throwIfRequested: function () { }, + promise: { + then: function () { }, + catch: function () { } + } + } + }; +}); +describe('get', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + var mockResponse = { + data: [status], + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + it('should be responsed', function () { return __awaiter(void 0, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ; + axios_1.default.get.mockResolvedValue(mockResponse); + return [4, client.get('/timelines/home')]; + case 1: + response = _a.sent(); + expect(response.data).toEqual([status]); + return [2]; + } + }); + }); }); +}); +describe('put', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + var mockResponse = { + data: account, + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + it('should be responsed', function () { return __awaiter(void 0, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ; + axios_1.default.put.mockResolvedValue(mockResponse); + return [4, client.put('/accounts/update_credentials', { + display_name: 'hoge' + })]; + case 1: + response = _a.sent(); + expect(response.data).toEqual(account); + return [2]; + } + }); + }); }); +}); +describe('patch', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + var mockResponse = { + data: account, + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + it('should be responsed', function () { return __awaiter(void 0, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ; + axios_1.default.patch.mockResolvedValue(mockResponse); + return [4, client.patch('/accounts/update_credentials', { + display_name: 'hoge' + })]; + case 1: + response = _a.sent(); + expect(response.data).toEqual(account); + return [2]; + } + }); + }); }); +}); +describe('post', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + var mockResponse = { + data: status, + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + it('should be responsed', function () { return __awaiter(void 0, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ; + axios_1.default.post.mockResolvedValue(mockResponse); + return [4, client.post('/statuses', { + status: 'hoge' + })]; + case 1: + response = _a.sent(); + expect(response.data).toEqual(status); + return [2]; + } + }); + }); }); +}); +describe('del', function () { + var client = new api_client_1.default.Client('testToken', 'https://pleroma.io/api/v1'); + var mockResponse = { + data: {}, + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + it('should be responsed', function () { return __awaiter(void 0, void 0, void 0, function () { + var response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + ; + axios_1.default.delete.mockResolvedValue(mockResponse); + return [4, client.del('/statuses/12asdf34')]; + case 1: + response = _a.sent(); + expect(response.data).toEqual({}); + return [2]; + } + }); + }); }); +}); diff --git a/packages/megalodon/lib/test/integration/megalodon.spec.d.ts b/packages/megalodon/lib/test/integration/megalodon.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/megalodon.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/megalodon.spec.js b/packages/megalodon/lib/test/integration/megalodon.spec.js new file mode 100644 index 000000000..7a822a019 --- /dev/null +++ b/packages/megalodon/lib/test/integration/megalodon.spec.js @@ -0,0 +1,86 @@ +"use strict"; +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 }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var index_1 = require("../../src/index"); +describe('detector', function () { + describe('mastodon', function () { + var url = 'https://fedibird.com'; + it('should be mastodon', function () { return __awaiter(void 0, void 0, void 0, function () { + var mastodon; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, (0, index_1.detector)(url)]; + case 1: + mastodon = _a.sent(); + expect(mastodon).toEqual('mastodon'); + return [2]; + } + }); + }); }); + }); + describe('pleroma', function () { + var url = 'https://pleroma.soykaf.com'; + it('should be pleroma', function () { return __awaiter(void 0, void 0, void 0, function () { + var pleroma; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, (0, index_1.detector)(url)]; + case 1: + pleroma = _a.sent(); + expect(pleroma).toEqual('pleroma'); + return [2]; + } + }); + }); }); + }); + describe('misskey', function () { + var url = 'https://misskey.io'; + it('should be misskey', function () { return __awaiter(void 0, void 0, void 0, function () { + var misskey; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4, (0, index_1.detector)(url)]; + case 1: + misskey = _a.sent(); + expect(misskey).toEqual('misskey'); + return [2]; + } + }); + }); }); + }); +}); diff --git a/packages/megalodon/lib/test/integration/misskey.spec.d.ts b/packages/megalodon/lib/test/integration/misskey.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/misskey.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/misskey.spec.js b/packages/megalodon/lib/test/integration/misskey.spec.js new file mode 100644 index 000000000..cbf48dd7f --- /dev/null +++ b/packages/megalodon/lib/test/integration/misskey.spec.js @@ -0,0 +1,238 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var notification_1 = __importDefault(require("@/misskey/notification")); +var misskey_1 = __importDefault(require("@/misskey")); +var notification_2 = __importDefault(require("@/notification")); +var axios_1 = __importDefault(require("axios")); +jest.mock('axios'); +var user = { + id: '1', + name: 'test_user', + username: 'TestUser', + host: 'misskey.io', + avatarUrl: 'https://example.com/icon.png', + avatarColor: '#000000', + emojis: [] +}; +var note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: 'hogehoge', + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null +}; +var follow = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Follow +}; +var mention = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Mention, + note: note +}; +var reply = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Reply, + note: note +}; +var renote = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Renote, + note: note +}; +var quote = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Quote, + note: note +}; +var reaction = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.Reaction, + note: note, + reaction: '♥' +}; +var pollVote = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.PollVote, + note: note +}; +var receiveFollowRequest = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.ReceiveFollowRequest +}; +var followRequestAccepted = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.FollowRequestAccepted +}; +var groupInvited = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: notification_1.default.GroupInvited +}; +axios_1.default.CancelToken.source.mockImplementation(function () { + return { + token: { + throwIfRequested: function () { }, + promise: { + then: function () { }, + catch: function () { } + } + } + }; +}); +describe('getNotifications', function () { + var client = new misskey_1.default('http://localhost', 'sample token'); + var cases = [ + { + event: follow, + expected: notification_2.default.Follow, + title: 'follow' + }, + { + event: mention, + expected: notification_2.default.Mention, + title: 'mention' + }, + { + event: reply, + expected: notification_2.default.Mention, + title: 'reply' + }, + { + event: renote, + expected: notification_2.default.Reblog, + title: 'renote' + }, + { + event: quote, + expected: notification_2.default.Reblog, + title: 'quote' + }, + { + event: reaction, + expected: notification_2.default.EmojiReaction, + title: 'reaction' + }, + { + event: pollVote, + expected: notification_2.default.PollVote, + title: 'pollVote' + }, + { + event: receiveFollowRequest, + expected: notification_2.default.FollowRequest, + title: 'receiveFollowRequest' + }, + { + event: followRequestAccepted, + expected: notification_2.default.Follow, + title: 'followRequestAccepted' + }, + { + event: groupInvited, + expected: notification_1.default.GroupInvited, + title: 'groupInvited' + } + ]; + cases.forEach(function (c) { + it("should be ".concat(c.title, " event"), function () { return __awaiter(void 0, void 0, void 0, function () { + var mockResponse, res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + mockResponse = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + axios_1.default.post.mockResolvedValue(mockResponse); + return [4, client.getNotifications()]; + case 1: + res = _a.sent(); + expect(res.data[0].type).toEqual(c.expected); + return [2]; + } + }); + }); }); + }); +}); diff --git a/packages/megalodon/lib/test/integration/pleroma.spec.d.ts b/packages/megalodon/lib/test/integration/pleroma.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/integration/pleroma.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/integration/pleroma.spec.js b/packages/megalodon/lib/test/integration/pleroma.spec.js new file mode 100644 index 000000000..655f16e4e --- /dev/null +++ b/packages/megalodon/lib/test/integration/pleroma.spec.js @@ -0,0 +1,224 @@ +"use strict"; +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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var pleroma_1 = __importDefault(require("@/pleroma")); +var notification_1 = __importDefault(require("@/notification")); +var notification_2 = __importDefault(require("@/pleroma/notification")); +var axios_1 = __importDefault(require("axios")); +jest.mock('axios'); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +var status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + bookmarked: false, + pleroma: { + local: false + } +}; +var follow = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '1', + type: notification_2.default.Follow +}; +var favourite = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '2', + type: notification_2.default.Favourite, + status: status +}; +var mention = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '3', + type: notification_2.default.Mention, + status: status +}; +var reblog = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '4', + type: notification_2.default.Reblog, + status: status +}; +var poll = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '5', + type: notification_2.default.Poll, + status: status +}; +var emojiReaction = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '6', + type: notification_2.default.PleromaEmojiReaction, + status: status, + emoji: '♥' +}; +var followRequest = { + account: account, + created_at: '2021-01-31T23:33:26', + id: '7', + type: notification_2.default.FollowRequest +}; +axios_1.default.CancelToken.source.mockImplementation(function () { + return { + token: { + throwIfRequested: function () { }, + promise: { + then: function () { }, + catch: function () { } + } + } + }; +}); +describe('getNotifications', function () { + var client = new pleroma_1.default('http://localhost', 'sample token'); + var cases = [ + { + event: follow, + expected: notification_1.default.Follow, + title: 'follow' + }, + { + event: favourite, + expected: notification_1.default.Favourite, + title: 'favourite' + }, + { + event: mention, + expected: notification_1.default.Mention, + title: 'mention' + }, + { + event: reblog, + expected: notification_1.default.Reblog, + title: 'reblog' + }, + { + event: poll, + expected: notification_1.default.PollExpired, + title: 'poll' + }, + { + event: emojiReaction, + expected: notification_1.default.EmojiReaction, + title: 'emojiReaction' + }, + { + event: followRequest, + expected: notification_1.default.FollowRequest, + title: 'followRequest' + } + ]; + cases.forEach(function (c) { + it("should be ".concat(c.title, " event"), function () { return __awaiter(void 0, void 0, void 0, function () { + var mockResponse, res; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + mockResponse = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: {} + }; + axios_1.default.get.mockResolvedValue(mockResponse); + return [4, client.getNotifications()]; + case 1: + res = _a.sent(); + expect(res.data[0].type).toEqual(c.expected); + return [2]; + } + }); + }); }); + }); +}); diff --git a/packages/megalodon/lib/test/unit/mastodon.spec.d.ts b/packages/megalodon/lib/test/unit/mastodon.spec.d.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/megalodon/lib/test/unit/mastodon.spec.js b/packages/megalodon/lib/test/unit/mastodon.spec.js new file mode 100644 index 000000000..6c5e8b997 --- /dev/null +++ b/packages/megalodon/lib/test/unit/mastodon.spec.js @@ -0,0 +1,7 @@ +"use strict"; +describe('test', function () { + it('should be true', function () { + var res = true; + expect(res).toEqual(true); + }); +}); diff --git a/packages/megalodon/lib/test/unit/mastodon/api_client.spec.d.ts b/packages/megalodon/lib/test/unit/mastodon/api_client.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/unit/mastodon/api_client.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/unit/mastodon/api_client.spec.js b/packages/megalodon/lib/test/unit/mastodon/api_client.spec.js new file mode 100644 index 000000000..bf8bc751f --- /dev/null +++ b/packages/megalodon/lib/test/unit/mastodon/api_client.spec.js @@ -0,0 +1,82 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("@/mastodon/api_client")); +var notification_1 = __importDefault(require("@/notification")); +var notification_2 = __importDefault(require("@/mastodon/notification")); +describe('api_client', function () { + describe('notification', function () { + describe('encode', function () { + it('megalodon notification type should be encoded to mastodon notification type', function () { + var cases = [ + { + src: notification_1.default.Follow, + dist: notification_2.default.Follow + }, + { + src: notification_1.default.Favourite, + dist: notification_2.default.Favourite + }, + { + src: notification_1.default.Reblog, + dist: notification_2.default.Reblog + }, + { + src: notification_1.default.Mention, + dist: notification_2.default.Mention + }, + { + src: notification_1.default.PollExpired, + dist: notification_2.default.Poll + }, + { + src: notification_1.default.FollowRequest, + dist: notification_2.default.FollowRequest + }, + { + src: notification_1.default.Status, + dist: notification_2.default.Status + } + ]; + cases.forEach(function (c) { + expect(api_client_1.default.Converter.encodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + describe('decode', function () { + it('mastodon notification type should be decoded to megalodon notification type', function () { + var cases = [ + { + src: notification_2.default.Follow, + dist: notification_1.default.Follow + }, + { + src: notification_2.default.Favourite, + dist: notification_1.default.Favourite + }, + { + src: notification_2.default.Mention, + dist: notification_1.default.Mention + }, + { + src: notification_2.default.Reblog, + dist: notification_1.default.Reblog + }, + { + src: notification_2.default.Poll, + dist: notification_1.default.PollExpired + }, + { + src: notification_2.default.FollowRequest, + dist: notification_1.default.FollowRequest + } + ]; + cases.forEach(function (c) { + expect(api_client_1.default.Converter.decodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + }); +}); diff --git a/packages/megalodon/lib/test/unit/misskey/api_client.spec.d.ts b/packages/megalodon/lib/test/unit/misskey/api_client.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/unit/misskey/api_client.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/unit/misskey/api_client.spec.js b/packages/megalodon/lib/test/unit/misskey/api_client.spec.js new file mode 100644 index 000000000..5c7635567 --- /dev/null +++ b/packages/megalodon/lib/test/unit/misskey/api_client.spec.js @@ -0,0 +1,231 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("@/misskey/api_client")); +var notification_1 = __importDefault(require("@/notification")); +var notification_2 = __importDefault(require("@/misskey/notification")); +var user = { + id: '1', + name: 'test_user', + username: 'TestUser', + host: 'misskey.io', + avatarUrl: 'https://example.com/icon.png', + avatarColor: '#000000', + emojis: [] +}; +var converter = new api_client_1.default.Converter("https://example.com"); +describe('api_client', function () { + describe('notification', function () { + describe('encode', function () { + it('megalodon notification type should be encoded to misskey notification type', function () { + var cases = [ + { + src: notification_1.default.Follow, + dist: notification_2.default.Follow + }, + { + src: notification_1.default.Mention, + dist: notification_2.default.Reply + }, + { + src: notification_1.default.Favourite, + dist: notification_2.default.Reaction + }, + { + src: notification_1.default.EmojiReaction, + dist: notification_2.default.Reaction + }, + { + src: notification_1.default.Reblog, + dist: notification_2.default.Renote + }, + { + src: notification_1.default.PollVote, + dist: notification_2.default.PollVote + }, + { + src: notification_1.default.FollowRequest, + dist: notification_2.default.ReceiveFollowRequest + } + ]; + cases.forEach(function (c) { + expect(converter.encodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + describe('decode', function () { + it('misskey notification type should be decoded to megalodon notification type', function () { + var cases = [ + { + src: notification_2.default.Follow, + dist: notification_1.default.Follow + }, + { + src: notification_2.default.Mention, + dist: notification_1.default.Mention + }, + { + src: notification_2.default.Reply, + dist: notification_1.default.Mention + }, + { + src: notification_2.default.Renote, + dist: notification_1.default.Reblog + }, + { + src: notification_2.default.Quote, + dist: notification_1.default.Reblog + }, + { + src: notification_2.default.Reaction, + dist: notification_1.default.EmojiReaction + }, + { + src: notification_2.default.PollVote, + dist: notification_1.default.PollVote + }, + { + src: notification_2.default.ReceiveFollowRequest, + dist: notification_1.default.FollowRequest + }, + { + src: notification_2.default.FollowRequestAccepted, + dist: notification_1.default.Follow + } + ]; + cases.forEach(function (c) { + expect(converter.decodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + }); + describe('reactions', function () { + it('should be mapped', function () { + var misskeyReactions = [ + { + id: '1', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + }, + { + id: '2', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + }, + { + id: '3', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '☺' + }, + { + id: '4', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + } + ]; + var reactions = converter.reactions(misskeyReactions); + expect(reactions).toEqual([ + { + count: 3, + me: false, + name: '❤' + }, + { + count: 1, + me: false, + name: '☺' + } + ]); + }); + }); + describe('status', function () { + describe('plain content', function () { + it('should be exported plain content and html content', function () { + var plainContent = 'hoge\nfuga\nfuga'; + var content = 'hoge
fuga
fuga'; + var note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: plainContent, + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null + }; + var megalodonStatus = converter.note(note, user.host || 'misskey.io'); + expect(megalodonStatus.plain_content).toEqual(plainContent); + expect(megalodonStatus.content).toEqual(content); + }); + it('html tags should be escaped', function () { + var plainContent = '

hoge\nfuga\nfuga

'; + var content = '<p>hoge
fuga
fuga<p>'; + var note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: plainContent, + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null + }; + var megalodonStatus = converter.note(note, user.host || 'misskey.io'); + expect(megalodonStatus.plain_content).toEqual(plainContent); + expect(megalodonStatus.content).toEqual(content); + }); + }); + }); +}); diff --git a/packages/megalodon/lib/test/unit/parser.spec.d.ts b/packages/megalodon/lib/test/unit/parser.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/unit/parser.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/unit/parser.spec.js b/packages/megalodon/lib/test/unit/parser.spec.js new file mode 100644 index 000000000..acb3f79fe --- /dev/null +++ b/packages/megalodon/lib/test/unit/parser.spec.js @@ -0,0 +1,141 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var parser_1 = require("@/parser"); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +var status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + plain_content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + emoji_reactions: [], + bookmarked: false, + quote: null +}; +var notification = { + id: '1', + account: account, + status: status, + type: 'favourite', + created_at: '2019-04-01T17:01:32' +}; +var conversation = { + id: '1', + accounts: [account], + last_status: status, + unread: true +}; +describe('Parser', function () { + var parser; + beforeEach(function () { + parser = new parser_1.Parser(); + }); + describe('parse', function () { + describe('message is heartbeat', function () { + var message = ':thump\n'; + it('should be called', function () { + var spy = jest.fn(); + parser.on('heartbeat', spy); + parser.parse(message); + expect(spy).toHaveBeenLastCalledWith({}); + }); + }); + describe('message is not json', function () { + describe('event is delete', function () { + var message = "event: delete\ndata: 12asdf34\n\n"; + it('should be called', function () { + var spy = jest.fn(); + parser.once('delete', spy); + parser.parse(message); + expect(spy).toHaveBeenCalledWith('12asdf34'); + }); + }); + describe('event is not delete', function () { + var message = "event: event\ndata: 12asdf34\n\n"; + it('should be error', function () { + var error = jest.fn(); + var deleted = jest.fn(); + parser.once('error', error); + parser.once('delete', deleted); + parser.parse(message); + expect(error).toHaveBeenCalled(); + expect(deleted).not.toHaveBeenCalled(); + }); + }); + }); + describe('message is json', function () { + describe('event is update', function () { + var message = "event: update\ndata: ".concat(JSON.stringify(status), "\n\n"); + it('should be called', function () { + var spy = jest.fn(); + parser.once('update', spy); + parser.parse(message); + expect(spy).toHaveBeenCalledWith(status); + }); + }); + describe('event is notification', function () { + var message = "event: notification\ndata: ".concat(JSON.stringify(notification), "\n\n"); + it('should be called', function () { + var spy = jest.fn(); + parser.once('notification', spy); + parser.parse(message); + expect(spy).toHaveBeenCalledWith(notification); + }); + }); + describe('event is conversation', function () { + var message = "event: conversation\ndata: ".concat(JSON.stringify(conversation), "\n\n"); + it('should be called', function () { + var spy = jest.fn(); + parser.once('conversation', spy); + parser.parse(message); + expect(spy).toHaveBeenCalledWith(conversation); + }); + }); + }); + }); +}); diff --git a/packages/megalodon/lib/test/unit/pleroma/api_client.spec.d.ts b/packages/megalodon/lib/test/unit/pleroma/api_client.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/unit/pleroma/api_client.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/unit/pleroma/api_client.spec.js b/packages/megalodon/lib/test/unit/pleroma/api_client.spec.js new file mode 100644 index 000000000..4233db038 --- /dev/null +++ b/packages/megalodon/lib/test/unit/pleroma/api_client.spec.js @@ -0,0 +1,199 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var api_client_1 = __importDefault(require("@/pleroma/api_client")); +var notification_1 = __importDefault(require("@/notification")); +var notification_2 = __importDefault(require("@/pleroma/notification")); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +describe('api_client', function () { + describe('notification', function () { + describe('encode', function () { + it('megalodon notification type should be encoded to pleroma notification type', function () { + var cases = [ + { + src: notification_1.default.Follow, + dist: notification_2.default.Follow + }, + { + src: notification_1.default.Favourite, + dist: notification_2.default.Favourite + }, + { + src: notification_1.default.Reblog, + dist: notification_2.default.Reblog + }, + { + src: notification_1.default.Mention, + dist: notification_2.default.Mention + }, + { + src: notification_1.default.PollExpired, + dist: notification_2.default.Poll + }, + { + src: notification_1.default.EmojiReaction, + dist: notification_2.default.PleromaEmojiReaction + }, + { + src: notification_1.default.FollowRequest, + dist: notification_2.default.FollowRequest + } + ]; + cases.forEach(function (c) { + expect(api_client_1.default.Converter.encodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + describe('decode', function () { + it('pleroma notification type should be decoded to megalodon notification type', function () { + var cases = [ + { + src: notification_2.default.Follow, + dist: notification_1.default.Follow + }, + { + src: notification_2.default.Favourite, + dist: notification_1.default.Favourite + }, + { + src: notification_2.default.Mention, + dist: notification_1.default.Mention + }, + { + src: notification_2.default.Reblog, + dist: notification_1.default.Reblog + }, + { + src: notification_2.default.Poll, + dist: notification_1.default.PollExpired + }, + { + src: notification_2.default.PleromaEmojiReaction, + dist: notification_1.default.EmojiReaction + }, + { + src: notification_2.default.FollowRequest, + dist: notification_1.default.FollowRequest + } + ]; + cases.forEach(function (c) { + expect(api_client_1.default.Converter.decodeNotificationType(c.src)).toEqual(c.dist); + }); + }); + }); + }); + describe('status', function () { + describe('plain content is included', function () { + it('plain content in pleroma entity should be exported in plain_content column', function () { + var plainContent = 'hoge\nfuga\nfuga'; + var content = '

hoge
fuga
fuga

'; + var pleromaStatus = { + id: '1', + uri: 'https://pleroma.io/notice/1', + url: 'https://pleroma.io/notice/1', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: content, + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + bookmarked: false, + pleroma: { + content: { + 'text/plain': plainContent + }, + local: false + } + }; + var megalodonStatus = api_client_1.default.Converter.status(pleromaStatus); + expect(megalodonStatus.plain_content).toEqual(plainContent); + expect(megalodonStatus.content).toEqual(content); + }); + }); + describe('plain content is not included', function () { + it('plain_content should be null', function () { + var content = '

hoge
fuga
fuga

'; + var pleromaStatus = { + id: '1', + uri: 'https://pleroma.io/notice/1', + url: 'https://pleroma.io/notice/1', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: content, + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + bookmarked: false, + pleroma: { + local: false + } + }; + var megalodonStatus = api_client_1.default.Converter.status(pleromaStatus); + expect(megalodonStatus.plain_content).toBeNull(); + expect(megalodonStatus.content).toEqual(content); + }); + }); + }); +}); diff --git a/packages/megalodon/lib/test/unit/webo_socket.spec.d.ts b/packages/megalodon/lib/test/unit/webo_socket.spec.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/packages/megalodon/lib/test/unit/webo_socket.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/megalodon/lib/test/unit/webo_socket.spec.js b/packages/megalodon/lib/test/unit/webo_socket.spec.js new file mode 100644 index 000000000..bb18640af --- /dev/null +++ b/packages/megalodon/lib/test/unit/webo_socket.spec.js @@ -0,0 +1,167 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var web_socket_1 = require("@/mastodon/web_socket"); +var account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +}; +var status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + plain_content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + }, + language: null, + pinned: null, + emoji_reactions: [], + bookmarked: false, + quote: null +}; +var notification = { + id: '1', + account: account, + status: status, + type: 'favourite', + created_at: '2019-04-01T17:01:32' +}; +var conversation = { + id: '1', + accounts: [account], + last_status: status, + unread: true +}; +describe('Parser', function () { + var parser; + beforeEach(function () { + parser = new web_socket_1.Parser(); + }); + describe('parse', function () { + describe('message is heartbeat', function () { + describe('message is an object', function () { + var message = Buffer.alloc(0); + it('should be called', function () { + var spy = jest.fn(); + parser.once('heartbeat', spy); + parser.parse(message, true); + expect(spy).toHaveBeenCalledWith({}); + }); + }); + describe('message is empty string', function () { + var message = ''; + it('should be called', function () { + var spy = jest.fn(); + parser.once('heartbeat', spy); + parser.parse(Buffer.from(message), false); + expect(spy).toHaveBeenCalledWith({}); + }); + }); + }); + describe('message is not json', function () { + describe('event is delete', function () { + var message = JSON.stringify({ + event: 'delete', + payload: '12asdf34' + }); + it('should be called', function () { + var spy = jest.fn(); + parser.once('delete', spy); + parser.parse(Buffer.from(message), false); + expect(spy).toHaveBeenCalledWith('12asdf34'); + }); + }); + describe('event is not delete', function () { + var message = JSON.stringify({ + event: 'event', + payload: '12asdf34' + }); + it('should be called', function () { + var error = jest.fn(); + var deleted = jest.fn(); + parser.once('error', error); + parser.once('delete', deleted); + parser.parse(Buffer.from(message), false); + expect(error).toHaveBeenCalled(); + expect(deleted).not.toHaveBeenCalled(); + }); + }); + }); + describe('message is json', function () { + describe('event is update', function () { + var message = JSON.stringify({ + event: 'update', + payload: JSON.stringify(status) + }); + it('should be called', function () { + var spy = jest.fn(); + parser.once('update', spy); + parser.parse(Buffer.from(message), false); + expect(spy).toHaveBeenCalledWith(status); + }); + }); + describe('event is notification', function () { + var message = JSON.stringify({ + event: 'notification', + payload: JSON.stringify(notification) + }); + it('should be called', function () { + var spy = jest.fn(); + parser.once('notification', spy); + parser.parse(Buffer.from(message), false); + expect(spy).toHaveBeenCalledWith(notification); + }); + }); + describe('event is conversation', function () { + var message = JSON.stringify({ + event: 'conversation', + payload: JSON.stringify(conversation) + }); + it('should be called', function () { + var spy = jest.fn(); + parser.once('conversation', spy); + parser.parse(Buffer.from(message), false); + expect(spy).toHaveBeenCalledWith(conversation); + }); + }); + }); + }); +}); diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json new file mode 100644 index 000000000..5e9d80967 --- /dev/null +++ b/packages/megalodon/package.json @@ -0,0 +1,103 @@ +{ + "name": "@calckey/megalodon", + "private": false, + "version": "5.1.23", + "description": "Mastodon+Calckey API client for node.js and browser", + "main": "./lib/src/index.js", + "typings": "./lib/src/index.d.ts", + "scripts": { + "build": "tsc -p ./", + "lint": "eslint --ext .js,.ts src", + "doc": "typedoc --out ../docs ./src", + "test": "NODE_ENV=test jest -u --maxWorkers=3" + }, + "engines": { + "node": ">=15.0.0" + }, + "repository": { + "type": "git", + "url": "git+https://codeberg.org/calckey/megalodon.git" + }, + "keywords": [ + "mastodon", + "client", + "api", + "streaming", + "rest", + "proxy" + ], + "author": "thatonecalculator", + "license": "MIT", + "bugs": { + "url": "https://codeberg.org/calckey/megalodon/issues" + }, + "jest": { + "moduleFileExtensions": [ + "ts", + "js" + ], + "moduleNameMapper": { + "^@/(.+)": "/src/$1", + "^~/(.+)": "/$1" + }, + "testMatch": [ + "**/test/**/*.spec.ts" + ], + "preset": "ts-jest/presets/default", + "transform": { + "^.+\\.(ts|tsx)$": "ts-jest" + }, + "globals": { + "ts-jest": { + "tsconfig": "tsconfig.json" + } + }, + "testEnvironment": "node" + }, + "homepage": "https://codeberg.org/calckey/megalodon", + "dependencies": { + "@types/oauth": "^0.9.0", + "@types/ws": "^8.5.4", + "axios": "1.2.2", + "dayjs": "^1.11.7", + "form-data": "^4.0.0", + "https-proxy-agent": "^5.0.1", + "oauth": "^0.10.0", + "object-assign-deep": "^0.4.0", + "parse-link-header": "^2.0.0", + "socks-proxy-agent": "^7.0.0", + "typescript": "4.9.4", + "uuid": "^9.0.0", + "ws": "8.12.0", + "async-lock": "1.4.0" + }, + "devDependencies": { + "@types/core-js": "^2.5.0", + "@types/form-data": "^2.5.0", + "@types/jest": "^29.4.0", + "@types/object-assign-deep": "^0.4.0", + "@types/parse-link-header": "^2.0.0", + "@types/uuid": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^5.49.0", + "@typescript-eslint/parser": "^5.49.0", + "@types/async-lock": "1.4.0", + "eslint": "^8.32.0", + "eslint-config-prettier": "^8.6.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-node": "^11.0.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-standard": "^5.0.0", + "jest": "^29.4.0", + "jest-worker": "^29.4.0", + "lodash": "^4.17.14", + "prettier": "^2.8.3", + "ts-jest": "^29.0.5", + "typedoc": "^0.23.24" + }, + "directories": { + "lib": "lib", + "test": "test" + } +} diff --git a/packages/megalodon/src/axios.d.ts b/packages/megalodon/src/axios.d.ts new file mode 100644 index 000000000..114cb06aa --- /dev/null +++ b/packages/megalodon/src/axios.d.ts @@ -0,0 +1 @@ +declare module 'axios/lib/adapters/http' diff --git a/packages/megalodon/src/cancel.ts b/packages/megalodon/src/cancel.ts new file mode 100644 index 000000000..3b905a492 --- /dev/null +++ b/packages/megalodon/src/cancel.ts @@ -0,0 +1,13 @@ +export class RequestCanceledError extends Error { + public isCancel: boolean + + constructor(msg: string) { + super(msg) + this.isCancel = true + Object.setPrototypeOf(this, RequestCanceledError) + } +} + +export const isCancel = (value: any): boolean => { + return value && value.isCancel +} diff --git a/packages/megalodon/src/converter.ts b/packages/megalodon/src/converter.ts new file mode 100644 index 000000000..113be823c --- /dev/null +++ b/packages/megalodon/src/converter.ts @@ -0,0 +1,3 @@ +import MisskeyAPI from "./misskey/api_client"; + +export default MisskeyAPI.Converter \ No newline at end of file diff --git a/packages/megalodon/src/default.ts b/packages/megalodon/src/default.ts new file mode 100644 index 000000000..0194b3dcc --- /dev/null +++ b/packages/megalodon/src/default.ts @@ -0,0 +1,3 @@ +export const NO_REDIRECT = 'urn:ietf:wg:oauth:2.0:oob' +export const DEFAULT_SCOPE = ['read', 'write', 'follow'] +export const DEFAULT_UA = 'megalodon' diff --git a/packages/megalodon/src/entities/account.ts b/packages/megalodon/src/entities/account.ts new file mode 100644 index 000000000..77f0e71d5 --- /dev/null +++ b/packages/megalodon/src/entities/account.ts @@ -0,0 +1,27 @@ +/// +/// +/// +namespace Entity { + export type Account = { + id: string + username: string + acct: string + display_name: string + locked: boolean + created_at: string + followers_count: number + following_count: number + statuses_count: number + note: string + url: string + avatar: string + avatar_static: string + header: string + header_static: string + emojis: Array + moved: Account | null + fields: Array + bot: boolean | null + source?: Source + } +} diff --git a/packages/megalodon/src/entities/activity.ts b/packages/megalodon/src/entities/activity.ts new file mode 100644 index 000000000..2494916a9 --- /dev/null +++ b/packages/megalodon/src/entities/activity.ts @@ -0,0 +1,8 @@ +namespace Entity { + export type Activity = { + week: string + statuses: string + logins: string + registrations: string + } +} diff --git a/packages/megalodon/src/entities/announcement.ts b/packages/megalodon/src/entities/announcement.ts new file mode 100644 index 000000000..00fa8a04b --- /dev/null +++ b/packages/megalodon/src/entities/announcement.ts @@ -0,0 +1,34 @@ +/// +/// +/// + +namespace Entity { + export type Announcement = { + id: string + content: string + starts_at: string | null + ends_at: string | null + published: boolean + all_day: boolean + published_at: string + updated_at: string + read?: boolean + mentions: Array + statuses: Array + tags: Array + emojis: Array + reactions: Array + } + + export type AnnouncementAccount = { + id: string + username: string + url: string + acct: string + } + + export type AnnouncementStatus = { + id: string + url: string + } +} diff --git a/packages/megalodon/src/entities/application.ts b/packages/megalodon/src/entities/application.ts new file mode 100644 index 000000000..3af64fcf9 --- /dev/null +++ b/packages/megalodon/src/entities/application.ts @@ -0,0 +1,7 @@ +namespace Entity { + export type Application = { + name: string + website?: string | null + vapid_key?: string | null + } +} diff --git a/packages/megalodon/src/entities/async_attachment.ts b/packages/megalodon/src/entities/async_attachment.ts new file mode 100644 index 000000000..b383f90c5 --- /dev/null +++ b/packages/megalodon/src/entities/async_attachment.ts @@ -0,0 +1,14 @@ +/// +namespace Entity { + export type AsyncAttachment = { + id: string + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio' + url: string | null + remote_url: string | null + preview_url: string + text_url: string | null + meta: Meta | null + description: string | null + blurhash: string | null + } +} diff --git a/packages/megalodon/src/entities/attachment.ts b/packages/megalodon/src/entities/attachment.ts new file mode 100644 index 000000000..aab1deade --- /dev/null +++ b/packages/megalodon/src/entities/attachment.ts @@ -0,0 +1,49 @@ +namespace Entity { + export type Sub = { + // For Image, Gifv, and Video + width?: number + height?: number + size?: string + aspect?: number + + // For Gifv and Video + frame_rate?: string + + // For Audio, Gifv, and Video + duration?: number + bitrate?: number + } + + export type Focus = { + x: number + y: number + } + + export type Meta = { + original?: Sub + small?: Sub + focus?: Focus + length?: string + duration?: number + fps?: number + size?: string + width?: number + height?: number + aspect?: number + audio_encode?: string + audio_bitrate?: string + audio_channel?: string + } + + export type Attachment = { + id: string + type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio' + url: string + remote_url: string | null + preview_url: string | null + text_url: string | null + meta: Meta | null + description: string | null + blurhash: string | null + } +} diff --git a/packages/megalodon/src/entities/card.ts b/packages/megalodon/src/entities/card.ts new file mode 100644 index 000000000..b39cbb8f2 --- /dev/null +++ b/packages/megalodon/src/entities/card.ts @@ -0,0 +1,16 @@ +namespace Entity { + export type Card = { + url: string + title: string + description: string + type: 'link' | 'photo' | 'video' | 'rich' + image?: string + author_name?: string + author_url?: string + provider_name?: string + provider_url?: string + html?: string + width?: number + height?: number + } +} diff --git a/packages/megalodon/src/entities/context.ts b/packages/megalodon/src/entities/context.ts new file mode 100644 index 000000000..3f2eda58f --- /dev/null +++ b/packages/megalodon/src/entities/context.ts @@ -0,0 +1,8 @@ +/// + +namespace Entity { + export type Context = { + ancestors: Array + descendants: Array + } +} diff --git a/packages/megalodon/src/entities/conversation.ts b/packages/megalodon/src/entities/conversation.ts new file mode 100644 index 000000000..cdadf1e0f --- /dev/null +++ b/packages/megalodon/src/entities/conversation.ts @@ -0,0 +1,11 @@ +/// +/// + +namespace Entity { + export type Conversation = { + id: string + accounts: Array + last_status: Status | null + unread: boolean + } +} diff --git a/packages/megalodon/src/entities/emoji.ts b/packages/megalodon/src/entities/emoji.ts new file mode 100644 index 000000000..c2bc5a1ef --- /dev/null +++ b/packages/megalodon/src/entities/emoji.ts @@ -0,0 +1,9 @@ +namespace Entity { + export type Emoji = { + shortcode: string + static_url: string + url: string + visible_in_picker: boolean + category: string + } +} diff --git a/packages/megalodon/src/entities/featured_tag.ts b/packages/megalodon/src/entities/featured_tag.ts new file mode 100644 index 000000000..06ae6d7a9 --- /dev/null +++ b/packages/megalodon/src/entities/featured_tag.ts @@ -0,0 +1,8 @@ +namespace Entity { + export type FeaturedTag = { + id: string + name: string + statuses_count: number + last_status_at: string + } +} diff --git a/packages/megalodon/src/entities/field.ts b/packages/megalodon/src/entities/field.ts new file mode 100644 index 000000000..03e4604b0 --- /dev/null +++ b/packages/megalodon/src/entities/field.ts @@ -0,0 +1,7 @@ +namespace Entity { + export type Field = { + name: string + value: string + verified_at: string | null + } +} diff --git a/packages/megalodon/src/entities/filter.ts b/packages/megalodon/src/entities/filter.ts new file mode 100644 index 000000000..ffbacb728 --- /dev/null +++ b/packages/megalodon/src/entities/filter.ts @@ -0,0 +1,12 @@ +namespace Entity { + export type Filter = { + id: string + phrase: string + context: Array + expires_at: string | null + irreversible: boolean + whole_word: boolean + } + + export type FilterContext = string +} diff --git a/packages/megalodon/src/entities/history.ts b/packages/megalodon/src/entities/history.ts new file mode 100644 index 000000000..070969426 --- /dev/null +++ b/packages/megalodon/src/entities/history.ts @@ -0,0 +1,7 @@ +namespace Entity { + export type History = { + day: string + uses: number + accounts: number + } +} diff --git a/packages/megalodon/src/entities/identity_proof.ts b/packages/megalodon/src/entities/identity_proof.ts new file mode 100644 index 000000000..ff857addb --- /dev/null +++ b/packages/megalodon/src/entities/identity_proof.ts @@ -0,0 +1,9 @@ +namespace Entity { + export type IdentityProof = { + provider: string + provider_username: string + updated_at: string + proof_url: string + profile_url: string + } +} diff --git a/packages/megalodon/src/entities/instance.ts b/packages/megalodon/src/entities/instance.ts new file mode 100644 index 000000000..e0aaf99b1 --- /dev/null +++ b/packages/megalodon/src/entities/instance.ts @@ -0,0 +1,41 @@ +/// +/// +/// + +namespace Entity { + export type Instance = { + uri: string + title: string + description: string + email: string + version: string + thumbnail: string | null + urls: URLs + stats: Stats + languages: Array + contact_account: Account | null + max_toot_chars?: number + registrations?: boolean + configuration?: { + statuses: { + max_characters: number + max_media_attachments: number + characters_reserved_per_url: number + } + media_attachments: { + supported_mime_types: Array + image_size_limit: number + image_matrix_limit: number + video_size_limit: number + video_frame_limit: number + video_matrix_limit: number + } + polls: { + max_options: number + max_characters_per_option: number + min_expiration: number + max_expiration: number + } + } + } +} diff --git a/packages/megalodon/src/entities/list.ts b/packages/megalodon/src/entities/list.ts new file mode 100644 index 000000000..2cee0db3c --- /dev/null +++ b/packages/megalodon/src/entities/list.ts @@ -0,0 +1,6 @@ +namespace Entity { + export type List = { + id: string + title: string + } +} diff --git a/packages/megalodon/src/entities/marker.ts b/packages/megalodon/src/entities/marker.ts new file mode 100644 index 000000000..33cb98a10 --- /dev/null +++ b/packages/megalodon/src/entities/marker.ts @@ -0,0 +1,15 @@ +namespace Entity { + export type Marker = { + home?: { + last_read_id: string + version: number + updated_at: string + } + notifications?: { + last_read_id: string + version: number + updated_at: string + unread_count?: number + } + } +} diff --git a/packages/megalodon/src/entities/mention.ts b/packages/megalodon/src/entities/mention.ts new file mode 100644 index 000000000..046912971 --- /dev/null +++ b/packages/megalodon/src/entities/mention.ts @@ -0,0 +1,8 @@ +namespace Entity { + export type Mention = { + id: string + username: string + url: string + acct: string + } +} diff --git a/packages/megalodon/src/entities/notification.ts b/packages/megalodon/src/entities/notification.ts new file mode 100644 index 000000000..d42dfe375 --- /dev/null +++ b/packages/megalodon/src/entities/notification.ts @@ -0,0 +1,15 @@ +/// +/// + +namespace Entity { + export type Notification = { + account: Account + created_at: string + id: string + status?: Status + emoji?: string + type: NotificationType + } + + export type NotificationType = string +} diff --git a/packages/megalodon/src/entities/poll.ts b/packages/megalodon/src/entities/poll.ts new file mode 100644 index 000000000..69706e8ae --- /dev/null +++ b/packages/megalodon/src/entities/poll.ts @@ -0,0 +1,13 @@ +/// + +namespace Entity { + export type Poll = { + id: string + expires_at: string | null + expired: boolean + multiple: boolean + votes_count: number + options: Array + voted: boolean + } +} diff --git a/packages/megalodon/src/entities/poll_option.ts b/packages/megalodon/src/entities/poll_option.ts new file mode 100644 index 000000000..ae4c63849 --- /dev/null +++ b/packages/megalodon/src/entities/poll_option.ts @@ -0,0 +1,6 @@ +namespace Entity { + export type PollOption = { + title: string + votes_count: number | null + } +} diff --git a/packages/megalodon/src/entities/preferences.ts b/packages/megalodon/src/entities/preferences.ts new file mode 100644 index 000000000..cb5797c4c --- /dev/null +++ b/packages/megalodon/src/entities/preferences.ts @@ -0,0 +1,9 @@ +namespace Entity { + export type Preferences = { + 'posting:default:visibility': 'public' | 'unlisted' | 'private' | 'direct' + 'posting:default:sensitive': boolean + 'posting:default:language': string | null + 'reading:expand:media': 'default' | 'show_all' | 'hide_all' + 'reading:expand:spoilers': boolean + } +} diff --git a/packages/megalodon/src/entities/push_subscription.ts b/packages/megalodon/src/entities/push_subscription.ts new file mode 100644 index 000000000..fe7464e8e --- /dev/null +++ b/packages/megalodon/src/entities/push_subscription.ts @@ -0,0 +1,16 @@ +namespace Entity { + export type Alerts = { + follow: boolean + favourite: boolean + mention: boolean + reblog: boolean + poll: boolean + } + + export type PushSubscription = { + id: string + endpoint: string + server_key: string + alerts: Alerts + } +} diff --git a/packages/megalodon/src/entities/reaction.ts b/packages/megalodon/src/entities/reaction.ts new file mode 100644 index 000000000..ccdc2d26a --- /dev/null +++ b/packages/megalodon/src/entities/reaction.ts @@ -0,0 +1,11 @@ +/// + +namespace Entity { + export type Reaction = { + count: number + me: boolean + name: string + url?: string + accounts?: Array + } +} diff --git a/packages/megalodon/src/entities/relationship.ts b/packages/megalodon/src/entities/relationship.ts new file mode 100644 index 000000000..5f10b9c98 --- /dev/null +++ b/packages/megalodon/src/entities/relationship.ts @@ -0,0 +1,17 @@ +namespace Entity { + export type Relationship = { + id: string + following: boolean + followed_by: boolean + delivery_following?: boolean + blocking: boolean + blocked_by: boolean + muting: boolean + muting_notifications: boolean + requested: boolean + domain_blocking: boolean + showing_reblogs: boolean + endorsed: boolean + notifying: boolean + } +} diff --git a/packages/megalodon/src/entities/report.ts b/packages/megalodon/src/entities/report.ts new file mode 100644 index 000000000..28f029981 --- /dev/null +++ b/packages/megalodon/src/entities/report.ts @@ -0,0 +1,9 @@ +namespace Entity { + export type Report = { + id: string + action_taken: string + comment: string + account_id: string + status_ids: Array + } +} diff --git a/packages/megalodon/src/entities/results.ts b/packages/megalodon/src/entities/results.ts new file mode 100644 index 000000000..fe168de67 --- /dev/null +++ b/packages/megalodon/src/entities/results.ts @@ -0,0 +1,11 @@ +/// +/// +/// + +namespace Entity { + export type Results = { + accounts: Array + statuses: Array + hashtags: Array + } +} diff --git a/packages/megalodon/src/entities/scheduled_status.ts b/packages/megalodon/src/entities/scheduled_status.ts new file mode 100644 index 000000000..fb6f63f10 --- /dev/null +++ b/packages/megalodon/src/entities/scheduled_status.ts @@ -0,0 +1,10 @@ +/// +/// +namespace Entity { + export type ScheduledStatus = { + id: string + scheduled_at: string + params: StatusParams + media_attachments: Array + } +} diff --git a/packages/megalodon/src/entities/source.ts b/packages/megalodon/src/entities/source.ts new file mode 100644 index 000000000..d87cf55d8 --- /dev/null +++ b/packages/megalodon/src/entities/source.ts @@ -0,0 +1,10 @@ +/// +namespace Entity { + export type Source = { + privacy: string | null + sensitive: boolean | null + language: string | null + note: string + fields: Array + } +} diff --git a/packages/megalodon/src/entities/stats.ts b/packages/megalodon/src/entities/stats.ts new file mode 100644 index 000000000..76f0bad34 --- /dev/null +++ b/packages/megalodon/src/entities/stats.ts @@ -0,0 +1,7 @@ +namespace Entity { + export type Stats = { + user_count: number + status_count: number + domain_count: number + } +} diff --git a/packages/megalodon/src/entities/status.ts b/packages/megalodon/src/entities/status.ts new file mode 100644 index 000000000..7fd72e20c --- /dev/null +++ b/packages/megalodon/src/entities/status.ts @@ -0,0 +1,45 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// + +namespace Entity { + export type Status = { + id: string + uri: string + url: string + account: Account + in_reply_to_id: string | null + in_reply_to_account_id: string | null + reblog: Status | null + content: string + plain_content: string | null + created_at: string + emojis: Emoji[] + replies_count: number + reblogs_count: number + favourites_count: number + reblogged: boolean | null + favourited: boolean | null + muted: boolean | null + sensitive: boolean + spoiler_text: string + visibility: 'public' | 'unlisted' | 'private' | 'direct' + media_attachments: Array + mentions: Array + tags: Array + card: Card | null + poll: Poll | null + application: Application | null + language: string | null + pinned: boolean | null + emoji_reactions: Array + quote: Status | null + bookmarked: boolean + } +} diff --git a/packages/megalodon/src/entities/status_edit.ts b/packages/megalodon/src/entities/status_edit.ts new file mode 100644 index 000000000..30bbee8e6 --- /dev/null +++ b/packages/megalodon/src/entities/status_edit.ts @@ -0,0 +1,23 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// + +namespace Entity { + export type StatusEdit = { + account: Account + content: string + plain_content: string | null + created_at: string + emojis: Emoji[] + sensitive: boolean + spoiler_text: string + media_attachments: Array + poll: Poll | null + } +} diff --git a/packages/megalodon/src/entities/status_params.ts b/packages/megalodon/src/entities/status_params.ts new file mode 100644 index 000000000..6de12423c --- /dev/null +++ b/packages/megalodon/src/entities/status_params.ts @@ -0,0 +1,12 @@ +namespace Entity { + export type StatusParams = { + text: string + in_reply_to_id: string | null + media_ids: Array | null + sensitive: boolean | null + spoiler_text: string | null + visibility: 'public' | 'unlisted' | 'private' | 'direct' + scheduled_at: string | null + application_id: string + } +} diff --git a/packages/megalodon/src/entities/tag.ts b/packages/megalodon/src/entities/tag.ts new file mode 100644 index 000000000..ff5b93381 --- /dev/null +++ b/packages/megalodon/src/entities/tag.ts @@ -0,0 +1,10 @@ +/// + +namespace Entity { + export type Tag = { + name: string + url: string + history: Array | null + following?: boolean + } +} diff --git a/packages/megalodon/src/entities/token.ts b/packages/megalodon/src/entities/token.ts new file mode 100644 index 000000000..6fa28e39b --- /dev/null +++ b/packages/megalodon/src/entities/token.ts @@ -0,0 +1,8 @@ +namespace Entity { + export type Token = { + access_token: string + token_type: string + scope: string + created_at: number + } +} diff --git a/packages/megalodon/src/entities/urls.ts b/packages/megalodon/src/entities/urls.ts new file mode 100644 index 000000000..4a980d589 --- /dev/null +++ b/packages/megalodon/src/entities/urls.ts @@ -0,0 +1,5 @@ +namespace Entity { + export type URLs = { + streaming_api: string + } +} diff --git a/packages/megalodon/src/entity.ts b/packages/megalodon/src/entity.ts new file mode 100644 index 000000000..39dd4b617 --- /dev/null +++ b/packages/megalodon/src/entity.ts @@ -0,0 +1,38 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +export default Entity diff --git a/packages/megalodon/src/filter_context.ts b/packages/megalodon/src/filter_context.ts new file mode 100644 index 000000000..c69be98cd --- /dev/null +++ b/packages/megalodon/src/filter_context.ts @@ -0,0 +1,11 @@ +import Entity from './entity' + +namespace FilterContext { + export const Home: Entity.FilterContext = 'home' + export const Notifications: Entity.FilterContext = 'notifications' + export const Public: Entity.FilterContext = 'public' + export const Thread: Entity.FilterContext = 'thread' + export const Account: Entity.FilterContext = 'account' +} + +export default FilterContext diff --git a/packages/megalodon/src/index.ts b/packages/megalodon/src/index.ts new file mode 100644 index 000000000..15486ad28 --- /dev/null +++ b/packages/megalodon/src/index.ts @@ -0,0 +1,28 @@ +import Response from './response' +import OAuth from './oauth' +import { isCancel, RequestCanceledError } from './cancel' +import { ProxyConfig } from './proxy_config' +import generator, { detector, MegalodonInterface, WebSocketInterface } from './megalodon' +import Misskey from './misskey' +import Entity from './entity' +import NotificationType from './notification' +import FilterContext from './filter_context' +import Converter from './converter' + +export { + Response, + OAuth, + RequestCanceledError, + isCancel, + ProxyConfig, + detector, + MegalodonInterface, + WebSocketInterface, + NotificationType, + FilterContext, + Misskey, + Entity, + Converter +} + +export default generator diff --git a/packages/megalodon/src/megalodon.ts b/packages/megalodon/src/megalodon.ts new file mode 100644 index 000000000..74966ccf4 --- /dev/null +++ b/packages/megalodon/src/megalodon.ts @@ -0,0 +1,1396 @@ +import Response from './response' +import OAuth from './oauth' +import proxyAgent, { ProxyConfig } from './proxy_config' +import Entity from './entity' +import axios, { AxiosRequestConfig } from 'axios' +import Misskey from './misskey' +import { DEFAULT_UA } from './default' + +export interface WebSocketInterface { + start(): void + stop(): void + // EventEmitter + on(event: string | symbol, listener: (...args: any[]) => void): this + once(event: string | symbol, listener: (...args: any[]) => void): this + removeListener(event: string | symbol, listener: (...args: any[]) => void): this + removeAllListeners(event?: string | symbol): this +} + +export interface MegalodonInterface { + /** + * Cancel all requests in this instance. + * + * @return void + */ + cancel(): void + + /** + * First, call createApp to get client_id and client_secret. + * Next, call generateAuthUrl to get authorization url. + * @param client_name Form Data, which is sent to /api/v1/apps + * @param options Form Data, which is sent to /api/v1/apps. and properties should be **snake_case** + */ + registerApp( + client_name: string, + options: Partial<{ scopes: Array; redirect_uris: string; website: string }> + ): Promise + + /** + * Call /api/v1/apps + * + * Create an application. + * @param client_name your application's name + * @param options Form Data + */ + createApp( + client_name: string, + options: Partial<{ scopes: Array; redirect_uris: string; website: string }> + ): Promise + + // ====================================== + // apps + // ====================================== + /** + * GET /api/v1/apps/verify_credentials + * + * @return An Application + */ + verifyAppCredentials(): Promise> + + // ====================================== + // apps/oauth + // ====================================== + + /** + * POST /oauth/token + * + * Fetch OAuth access token. + * Get an access token based client_id and client_secret and authorization code. + * @param client_id will be generated by #createApp or #registerApp + * @param client_secret will be generated by #createApp or #registerApp + * @param code will be generated by the link of #generateAuthUrl or #registerApp + * @param redirect_uri must be the same uri as the time when you register your OAuth application + */ + fetchAccessToken(client_id: string | null, client_secret: string, code: string, redirect_uri?: string): Promise + + /** + * POST /oauth/token + * + * Refresh OAuth access token. + * Send refresh token and get new access token. + * @param client_id will be generated by #createApp or #registerApp + * @param client_secret will be generated by #createApp or #registerApp + * @param refresh_token will be get #fetchAccessToken + */ + refreshToken(client_id: string, client_secret: string, refresh_token: string): Promise + + /** + * POST /oauth/revoke + * + * Revoke an OAuth token. + * @param client_id will be generated by #createApp or #registerApp + * @param client_secret will be generated by #createApp or #registerApp + * @param token will be get #fetchAccessToken + */ + revokeToken(client_id: string, client_secret: string, token: string): Promise> + + // ====================================== + // accounts + // ====================================== + /** + * POST /api/v1/accounts + * + * @param username Username for the account. + * @param email Email for the account. + * @param password Password for the account. + * @param agreement Whether the user agrees to the local rules, terms, and policies. + * @param locale The language of the confirmation email that will be sent + * @param reason Text that will be reviewed by moderators if registrations require manual approval. + * @return An account token. + */ + registerAccount( + username: string, + email: string, + password: string, + agreement: boolean, + locale: string, + reason?: string | null + ): Promise> + /** + * GET /api/v1/accounts/verify_credentials + * + * @return Account. + */ + verifyAccountCredentials(): Promise> + /** + * PATCH /api/v1/accounts/update_credentials + * + * @return An account. + */ + updateCredentials(options?: { + discoverable?: boolean + bot?: boolean + display_name?: string + note?: string + avatar?: string + header?: string + locked?: boolean + source?: { + privacy?: string + sensitive?: boolean + language?: string + } + fields_attributes?: Array<{ name: string; value: string }> + }): Promise> + /** + * GET /api/v1/accounts/:id + * + * @param id The account ID. + * @return An account. + */ + getAccount(id: string): Promise> + /** + * GET /api/v1/accounts/:id/statuses + * + * @param id The account ID. + + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID but starting with most recent. + * @param options.min_id Return results newer than ID. + * @param options.pinned Return statuses which include pinned statuses. + * @param options.exclude_replies Return statuses which exclude replies. + * @param options.exclude_reblogs Return statuses which exclude reblogs. + * @param options.only_media Show only statuses with media attached? Defaults to false. + * @return Account's statuses. + */ + getAccountStatuses( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + pinned?: boolean + exclude_replies?: boolean + exclude_reblogs?: boolean + only_media?: boolean + } + ): Promise>> + /** + * GET /api/v1/pleroma/accounts/:id/favourites + * + * @param id Target account ID. + * @param options.limit Max number of results to return. + * @param options.max_id Return results order than ID. + * @param options.since_id Return results newer than ID. + * @return Array of statuses. + */ + getAccountFavourites( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> + /** + * POST /api/v1/pleroma/accounts/:id/subscribe + * + * @param id Target account ID. + * @return Relationship. + */ + subscribeAccount(id: string): Promise> + /** + * POST /api/v1/pleroma/accounts/:id/unsubscribe + * + * @param id Target account ID. + * @return Relationship. + */ + unsubscribeAccount(id: string): Promise> + /** + * GET /api/v1/accounts/:id/followers + * + * @param id The account ID. + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @return The array of accounts. + */ + getAccountFollowers( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + get_all?: boolean + sleep_ms?: number + } + ): Promise>> + + /** + * GET /api/v1/accounts/:id/featured_tags + * + * @param id The account ID. + * @return The array of accounts. + */ + getAccountFeaturedTags( + id: string + ): Promise>> + + /** + * GET /api/v1/accounts/:id/following + * + * @param id The account ID. + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @return The array of accounts. + */ + getAccountFollowing( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + get_all?: boolean + sleep_ms?: number + } + ): Promise>> + /** + * GET /api/v1/accounts/:id/lists + * + * @param id The account ID. + * @return The array of lists. + */ + getAccountLists(id: string): Promise>> + /** + * GET /api/v1/accounts/:id/identity_proofs + * + * @param id The account ID. + * @return Array of IdentityProof + */ + getIdentityProof(id: string): Promise>> + /** + * POST /api/v1/accounts/:id/follow + * + * @param id The account ID. + * @param reblog Receive this account's reblogs in home timeline. + * @return Relationship + */ + followAccount( + id: string, + options?: { + reblog?: boolean + } + ): Promise> + /** + * POST /api/v1/accounts/:id/unfollow + * + * @param id The account ID. + * @return Relationship + */ + unfollowAccount(id: string): Promise> + /** + * POST /api/v1/accounts/:id/block + * + * @param id The account ID. + * @return Relationship + */ + blockAccount(id: string): Promise> + /** + * POST /api/v1/accounts/:id/unblock + * + * @param id The account ID. + * @return RElationship + */ + unblockAccount(id: string): Promise> + /** + * POST /api/v1/accounts/:id/mute + * + * @param id The account ID. + * @param notifications Mute notifications in addition to statuses. + * @return Relationship + */ + muteAccount(id: string, notifications: boolean): Promise> + /** + * POST /api/v1/accounts/:id/unmute + * + * @param id The account ID. + * @return Relationship + */ + unmuteAccount(id: string): Promise> + /** + * POST /api/v1/accounts/:id/pin + * + * @param id The account ID. + * @return Relationship + */ + pinAccount(id: string): Promise> + /** + * POST /api/v1/accounts/:id/unpin + * + * @param id The account ID. + * @return Relationship + */ + unpinAccount(id: string): Promise> + /** + * GET /api/v1/accounts/relationships + * + * @param id The account ID. + * @return Relationship + */ + getRelationship(id: string): Promise> + /** + * Get multiple relationships in one method + * + * @param ids Array of account IDs. + * @return Array of Relationship. + */ + getRelationships(ids: Array): Promise>> + /** + * GET /api/v1/accounts/search + * + * @param q Search query. + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @return The array of accounts. + */ + searchAccount( + q: string, + options?: { + following?: boolean + resolve?: boolean + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> + // ====================================== + // accounts/bookmarks + // ====================================== + /** + * GET /api/v1/bookmarks + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getBookmarks(options?: { limit?: number; max_id?: string; since_id?: string; min_id?: string }): Promise>> + // ====================================== + // accounts/favourites + // ====================================== + /** + * GET /api/v1/favourites + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getFavourites(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> + // ====================================== + // accounts/mutes + // ====================================== + /** + * GET /api/v1/mutes + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of accounts. + */ + getMutes(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> + // ====================================== + // accounts/blocks + // ====================================== + /** + * GET /api/v1/blocks + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of accounts. + */ + getBlocks(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> + // ====================================== + // accounts/domain_blocks + // ====================================== + /** + * GET /api/v1/domain_blocks + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of domain name. + */ + getDomainBlocks(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> + /** + * POST/api/v1/domain_blocks + * + * @param domain Domain to block. + */ + blockDomain(domain: string): Promise> + /** + * DELETE /api/v1/domain_blocks + * + * @param domain Domain to unblock + */ + unblockDomain(domain: string): Promise> + // ====================================== + // accounts/filters + // ====================================== + /** + * GET /api/v1/filters + * + * @return Array of filters. + */ + getFilters(): Promise>> + /** + * GET /api/v1/filters/:id + * + * @param id The filter ID. + * @return Filter. + */ + getFilter(id: string): Promise> + /** + * POST /api/v1/filters + * + * @param phrase Text to be filtered. + * @param context Array of enumerable strings home, notifications, public, thread, account. At least one context must be specified. + * @param options.irreversible Should the server irreversibly drop matching entities from home and notifications? + * @param options.whole_word Consider word boundaries? + * @param options.expires_in ISO 8601 Datetime for when the filter expires. + * @return Filter + */ + createFilter( + phrase: string, + context: Array, + options?: { + irreversible?: boolean + whole_word?: boolean + expires_in?: string + } + ): Promise> + /** + * PUT /api/v1/filters/:id + * + * @param id The filter ID. + * @param phrase Text to be filtered. + * @param context Array of enumerable strings home, notifications, public, thread, account. At least one context must be specified. + * @param options.irreversible Should the server irreversibly drop matching entities from home and notifications? + * @param options.whole_word Consider word boundaries? + * @param options.expires_in ISO 8601 Datetime for when the filter expires. + * @return Filter + */ + updateFilter( + id: string, + phrase: string, + context: Array, + options?: { + irreversible?: boolean + whole_word?: boolean + expires_in?: string + } + ): Promise> + /** + * DELETE /api/v1/filters/:id + * + * @param id The filter ID. + * @return Removed filter. + */ + deleteFilter(id: string): Promise> + // ====================================== + // accounts/reports + // ====================================== + /** + * POST /api/v1/reports + * + * @param account_id Target account ID. + * @param comment Reason of the report. + * @param options.status_ids Array of Statuses ids to attach to the report. + * @param options.forward If the account is remote, should the report be forwarded to the remote admin? + * @return Report + */ + report(account_id: string, comment: string, options?: { status_ids?: Array; forward?: boolean }): Promise> + // ====================================== + // accounts/follow_requests + // ====================================== + /** + * GET /api/v1/follow_requests + * + * @param limit Maximum number of results. + * @return Array of account. + */ + getFollowRequests(limit?: number): Promise>> + /** + * POST /api/v1/follow_requests/:id/authorize + * + * @param id Target account ID. + * @return Relationship. + */ + acceptFollowRequest(id: string): Promise> + /** + * POST /api/v1/follow_requests/:id/reject + * + * @param id Target account ID. + * @return Relationship. + */ + rejectFollowRequest(id: string): Promise> + // ====================================== + // accounts/endorsements + // ====================================== + /** + * GET /api/v1/endorsements + * + * @param options.limit Max number of results to return. Defaults to 40. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @return Array of accounts. + */ + getEndorsements(options?: { limit?: number; max_id?: string; since_id?: string }): Promise>> + // ====================================== + // accounts/featured_tags + // ====================================== + /** + * GET /api/v1/featured_tags + * + * @return Array of featured tag. + */ + getFeaturedTags(): Promise>> + /** + * POST /api/v1/featured_tags + * + * @param name Target hashtag name. + * @return FeaturedTag. + */ + createFeaturedTag(name: string): Promise> + /** + * DELETE /api/v1/featured_tags/:id + * + * @param id Target featured tag id. + * @return Empty + */ + deleteFeaturedTag(id: string): Promise> + /** + * GET /api/v1/featured_tags/suggestions + * + * @return Array of tag. + */ + getSuggestedTags(): Promise>> + // ====================================== + // accounts/preferences + // ====================================== + /** + * GET /api/v1/preferences + * + * @return Preferences. + */ + getPreferences(): Promise> + // ====================================== + // accounts/suggestions + // ====================================== + /** + * GET /api/v1/suggestions + * + * @param limit Maximum number of results. + * @return Array of accounts. + */ + getSuggestions(limit?: number): Promise>> + // ====================================== + // accounts/tags + // ====================================== + getFollowedTags(): Promise>> + /** + * GET /api/v1/tags/:id + * + * @param id Target hashtag id. + * @return Tag + */ + getTag(id: string): Promise> + /** + * POST /api/v1/tags/:id/follow + * + * @param id Target hashtag id. + * @return Tag + */ + followTag(id: string): Promise> + /** + * POST /api/v1/tags/:id/unfollow + * + * @param id Target hashtag id. + * @return Tag + */ + unfollowTag(id: string): Promise> + // ====================================== + // statuses + // ====================================== + /** + * POST /api/v1/statuses + * + * @param status Text content of status. + * @param options.media_ids Array of Attachment ids. + * @param options.poll Poll object. + * @param options.in_reply_to_id ID of the status being replied to, if status is a reply. + * @param options.sensitive Mark status and attached media as sensitive? + * @param options.spoiler_text Text to be shown as a warning or subject before the actual content. + * @param options.visibility Visibility of the posted status. + * @param options.scheduled_at ISO 8601 Datetime at which to schedule a status. + * @param options.language ISO 639 language code for this status. + * @param options.quote_id ID of the status being quoted to, if status is a quote. + * @return Status + */ + postStatus( + status: string, + options?: { + media_ids?: Array + poll?: { options: Array; expires_in: number; multiple?: boolean; hide_totals?: boolean } + in_reply_to_id?: string + sensitive?: boolean + spoiler_text?: string + visibility?: 'public' | 'unlisted' | 'private' | 'direct' + scheduled_at?: string + language?: string + quote_id?: string + } + ): Promise> + /** + * GET /api/v1/statuses/:id + * + * @param id The target status id. + * @return Status + */ + getStatus(id: string): Promise> + /** + PUT /api/v1/statuses/:id + * + * @param id The target status id. + * @return Status + */ + editStatus( + id: string, + options: { + status?: string + spoiler_text?: string + sensitive?: boolean + media_ids?: Array + poll?: { options?: Array; expires_in?: number; multiple?: boolean; hide_totals?: boolean } + } + ): Promise> + /** + * DELETE /api/v1/statuses/:id + * + * @param id The target status id. + * @return Status + */ + deleteStatus(id: string): Promise> + /** + * GET /api/v1/statuses/:id/context + * + * Get parent and child statuses. + * @param id The target status id. + * @return Context + */ + getStatusContext(id: string, options?: { limit?: number; max_id?: string; since_id?: string }): Promise> + /** + * GET /api/v1/statuses/:id/history + * + * Get status edit history. + * @param id The target status id. + * @return StatusEdit + */ + getStatusHistory(id: string): Promise>> + /** + * GET /api/v1/statuses/:id/reblogged_by + * + * @param id The target status id. + * @return Array of accounts. + */ + getStatusRebloggedBy(id: string): Promise>> + /** + * GET /api/v1/statuses/:id/favourited_by + * + * @param id The target status id. + * @return Array of accounts. + */ + getStatusFavouritedBy(id: string): Promise>> + /** + * POST /api/v1/statuses/:id/favourite + * + * @param id The target status id. + * @return Status. + */ + favouriteStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/unfavourite + * + * @param id The target status id. + * @return Status. + */ + unfavouriteStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/reblog + * + * @param id The target status id. + * @return Status. + */ + reblogStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/unreblog + * + * @param id The target status id. + * @return Status. + */ + unreblogStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/bookmark + * + * @param id The target status id. + * @return Status. + */ + bookmarkStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/unbookmark + * + * @param id The target status id. + * @return Status. + */ + unbookmarkStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/mute + * + * @param id The target status id. + * @return Status + */ + muteStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/unmute + * + * @param id The target status id. + * @return Status + */ + unmuteStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/pin + * @param id The target status id. + * @return Status + */ + pinStatus(id: string): Promise> + /** + * POST /api/v1/statuses/:id/unpin + * + * @param id The target status id. + * @return Status + */ + unpinStatus(id: string): Promise> + // ====================================== + // statuses/media + // ====================================== + /** + * POST /api/v2/media + * + * @param file The file to be attached, using multipart form data. + * @param options.description A plain-text description of the media. + * @param options.focus Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. + * @return Attachment + */ + uploadMedia(file: any, options?: { description?: string; focus?: string }): Promise> + /** + * GET /api/v1/media/:id + * + * @param id Target media ID. + * @return Attachment + */ + getMedia(id: string): Promise> + /** + * PUT /api/v1/media/:id + * + * @param id Target media ID. + * @param options.file The file to be attached, using multipart form data. + * @param options.description A plain-text description of the media. + * @param options.focus Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. + * @param options.is_sensitive Whether the media is sensitive. + * @return Attachment + */ + updateMedia( + id: string, + options?: { + file?: any + description?: string + focus?: string + is_sensitive?: boolean + } + ): Promise> + // ====================================== + // statuses/polls + // ====================================== + /** + * GET /api/v1/polls/:id + * + * @param id Target poll ID. + * @return Poll + */ + getPoll(id: string): Promise> + /** + * POST /api/v1/polls/:id/votes + * + * @param id Target poll ID. + * @param choices Array of own votes containing index for each option (starting from 0). + * @return Poll + */ + votePoll(id: string, choices: Array, status_id?: string | null): Promise> + // ====================================== + // statuses/scheduled_statuses + // ====================================== + /** + * GET /api/v1/scheduled_statuses + * + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of scheduled statuses. + */ + getScheduledStatuses(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> + /** + * GET /api/v1/scheduled_statuses/:id + * + * @param id Target status ID. + * @return ScheduledStatus. + */ + getScheduledStatus(id: string): Promise> + /** + * PUT /api/v1/scheduled_statuses/:id + * + * @param id Target scheduled status ID. + * @param scheduled_at ISO 8601 Datetime at which the status will be published. + * @return ScheduledStatus. + */ + scheduleStatus(id: string, scheduled_at?: string | null): Promise> + /** + * DELETE /api/v1/scheduled_statuses/:id + * + * @param id Target scheduled status ID. + */ + cancelScheduledStatus(id: string): Promise> + // ====================================== + // timelines + // ====================================== + /** + * GET /api/v1/timelines/public + * + * @param options.only_media Show only statuses with media attached? Defaults to false. + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getPublicTimeline(options?: { + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> + /** + * GET /api/v1/timelines/public + * + * @param options.only_media Show only statuses with media attached? Defaults to false. + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getLocalTimeline(options?: { + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> + /** + * GET /api/v1/timelines/tag/:hashtag + * + * @param hashtag Content of a #hashtag, not including # symbol. + * @param options.local Show only local statuses? Defaults to false. + * @param options.only_media Show only statuses with media attached? Defaults to false. + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getTagTimeline( + hashtag: string, + options?: { + local?: boolean + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + } + ): Promise>> + /** + * GET /api/v1/timelines/home + * + * @param options.local Show only local statuses? Defaults to false. + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getHomeTimeline(options?: { + local?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> + /** + * GET /api/v1/timelines/list/:list_id + * + * @param list_id Local ID of the list in the database. + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getListTimeline( + list_id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + } + ): Promise>> + // ====================================== + // timelines/conversations + // ====================================== + /** + * GET /api/v1/conversations + * + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of statuses. + */ + getConversationTimeline(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> + /** + * DELETE /api/v1/conversations/:id + * + * @param id Target conversation ID. + */ + deleteConversation(id: string): Promise> + /** + * POST /api/v1/conversations/:id/read + * + * @param id Target conversation ID. + * @return Conversation. + */ + readConversation(id: string): Promise> + // ====================================== + // timelines/lists + // ====================================== + /** + * GET /api/v1/lists + * + * @return Array of lists. + */ + getLists(): Promise>> + /** + * GET /api/v1/lists/:id + * + * @param id Target list ID. + * @return List. + */ + getList(id: string): Promise> + /** + * POST /api/v1/lists + * + * @param title List name. + * @return List. + */ + createList(title: string): Promise> + /** + * PUT /api/v1/lists/:id + * + * @param id Target list ID. + * @param title New list name. + * @return List. + */ + updateList(id: string, title: string): Promise> + /** + * DELETE /api/v1/lists/:id + * + * @param id Target list ID. + */ + deleteList(id: string): Promise> + /** + * GET /api/v1/lists/:id/accounts + * + * @param id Target list ID. + * @param options.limit Max number of results to return. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @return Array of accounts. + */ + getAccountsInList( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> + /** + * POST /api/v1/lists/:id/accounts + * + * @param id Target list ID. + * @param account_ids Array of account IDs to add to the list. + */ + addAccountsToList(id: string, account_ids: Array): Promise> + /** + * DELETE /api/v1/lists/:id/accounts + * + * @param id Target list ID. + * @param account_ids Array of account IDs to add to the list. + */ + deleteAccountsFromList(id: string, account_ids: Array): Promise> + // ====================================== + // timelines/markers + // ====================================== + /** + * GET /api/v1/markers + * + * @param timelines Array of timeline names, String enum anyOf home, notifications. + * @return Marker or empty object. + */ + getMarkers(timeline: Array): Promise> + /** + * POST /api/v1/markers + * + * @param options.home Marker position of the last read status ID in home timeline. + * @param options.notifications Marker position of the last read notification ID in notifications. + * @return Marker. + */ + saveMarkers(options?: { home?: { last_read_id: string }; notifications?: { last_read_id: string } }): Promise> + // ====================================== + // notifications + // ====================================== + /** + * GET /api/v1/notifications + * + * @param options.limit Max number of results to return. Defaults to 20. + * @param options.max_id Return results older than ID. + * @param options.since_id Return results newer than ID. + * @param options.min_id Return results immediately newer than ID. + * @param options.exclude_types Array of types to exclude. + * @param options.account_id Return only notifications received from this account. + * @return Array of notifications. + */ + getNotifications(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + exclude_types?: Array + account_id?: string + }): Promise>> + /** + * GET /api/v1/notifications/:id + * + * @param id Target notification ID. + * @return Notification. + */ + getNotification(id: string): Promise> + /** + * POST /api/v1/notifications/clear + */ + dismissNotifications(): Promise> + /** + * POST /api/v1/notifications/:id/dismiss + * + * @param id Target notification ID. + */ + dismissNotification(id: string): Promise> + /** + * POST /api/v1/pleroma/notifcations/read + * + * @param id A single notification ID to read + * @param max_id Read all notifications up to this ID + * @return Array of notifications + */ + readNotifications(options: { id?: string; max_id?: string }): Promise>> + // ====================================== + // notifications/push + // ====================================== + /** + * POST /api/v1/push/subscription + * + * @param subscription[endpoint] Endpoint URL that is called when a notification event occurs. + * @param subscription[keys][p256dh] User agent public key. Base64 encoded string of public key of ECDH key using prime256v1 curve. + * @param subscription[keys] Auth secret. Base64 encoded string of 16 bytes of random data. + * @param data[alerts][follow] Receive follow notifications? + * @param data[alerts][favourite] Receive favourite notifications? + * @param data[alerts][reblog] Receive reblog notifictaions? + * @param data[alerts][mention] Receive mention notifications? + * @param data[alerts][poll] Receive poll notifications? + * @return PushSubscription. + */ + subscribePushNotification( + subscription: { endpoint: string; keys: { p256dh: string; auth: string } }, + data?: { alerts: { follow?: boolean; favourite?: boolean; reblog?: boolean; mention?: boolean; poll?: boolean } } | null + ): Promise> + /** + * GET /api/v1/push/subscription + * + * @return PushSubscription. + */ + getPushSubscription(): Promise> + /** + * PUT /api/v1/push/subscription + * + * @param data[alerts][follow] Receive follow notifications? + * @param data[alerts][favourite] Receive favourite notifications? + * @param data[alerts][reblog] Receive reblog notifictaions? + * @param data[alerts][mention] Receive mention notifications? + * @param data[alerts][poll] Receive poll notifications? + * @return PushSubscription. + */ + updatePushSubscription( + data?: { alerts: { follow?: boolean; favourite?: boolean; reblog?: boolean; mention?: boolean; poll?: boolean } } | null + ): Promise> + /** + * DELETE /api/v1/push/subscription + */ + deletePushSubscription(): Promise> + // ====================================== + // search + // ====================================== + /** + * GET /api/v2/search + * + * @param q The search query. + * @param type Enum of search target. + * @param options.limit Maximum number of results to load, per type. Defaults to 20. Max 40. + * @param options.max_id Return results older than this id. + * @param options.min_id Return results immediately newer than this id. + * @param options.resolve Attempt WebFinger lookup. Defaults to false. + * @param options.following Only include accounts that the user is following. Defaults to false. + * @param options.account_id If provided, statuses returned will be authored only by this account. + * @param options.exclude_unreviewed Filter out unreviewed tags? Defaults to false. + * @return Results. + */ + search( + q: string, + type: 'accounts' | 'hashtags' | 'statuses', + options?: { + limit?: number + max_id?: string + min_id?: string + resolve?: boolean + offset?: number + following?: boolean + account_id?: string + exclude_unreviewed?: boolean + } + ): Promise> + + // ====================================== + // instance + // ====================================== + /** + * GET /api/v1/instance + */ + getInstance(): Promise> + + /** + * GET /api/v1/instance/peers + */ + getInstancePeers(): Promise>> + + /** + * GET /api/v1/instance/activity + */ + getInstanceActivity(): Promise>> + + // ====================================== + // instance/trends + // ====================================== + /** + * GET /api/v1/trends + * + * @param limit Maximum number of results to return. Defaults to 10. + */ + getInstanceTrends(limit?: number | null): Promise>> + + // ====================================== + // instance/directory + // ====================================== + /** + * GET /api/v1/directory + * + * @param options.limit How many accounts to load. Default 40. + * @param options.offset How many accounts to skip before returning results. Default 0. + * @param options.order Order of results. + * @param options.local Only return local accounts. + * @return Array of accounts. + */ + getInstanceDirectory(options?: { + limit?: number + offset?: number + order?: 'active' | 'new' + local?: boolean + }): Promise>> + + // ====================================== + // instance/custom_emojis + // ====================================== + /** + * GET /api/v1/custom_emojis + * + * @return Array of emojis. + */ + getInstanceCustomEmojis(): Promise>> + + // ====================================== + // instance/announcements + // ====================================== + /** + * GET /api/v1/announcements + * + * @param with_dismissed Include announcements dismissed by the user. Defaults to false. + * @return Array of announcements. + */ + getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>> + + /** + * POST /api/v1/announcements/:id/dismiss + */ + dismissInstanceAnnouncement(id: string): Promise> + + // ====================================== + // Emoji reactions + // ====================================== + createEmojiReaction(id: string, emoji: string): Promise> + deleteEmojiReaction(id: string, emoji: string): Promise> + getEmojiReactions(id: string): Promise>> + getEmojiReaction(id: string, emoji: string): Promise> + + // ====================================== + // WebSocket + // ====================================== + userSocket(): WebSocketInterface + publicSocket(): WebSocketInterface + localSocket(): WebSocketInterface + tagSocket(tag: string): WebSocketInterface + listSocket(list_id: string): WebSocketInterface + directSocket(): WebSocketInterface +} + +export class NoImplementedError extends Error { + constructor(err?: string) { + super(err) + + this.name = new.target.name + Object.setPrototypeOf(this, new.target.prototype) + } +} + +export class ArgumentError extends Error { + constructor(err?: string) { + super(err) + + this.name = new.target.name + Object.setPrototypeOf(this, new.target.prototype) + } +} + +export class UnexpectedError extends Error { + constructor(err?: string) { + super(err) + + this.name = new.target.name + Object.setPrototypeOf(this, new.target.prototype) + } +} + +type Instance = { + title: string + uri: string + urls: { + streaming_api: string + } + version: string +} + +/** + * Detect SNS type. + * Now support Mastodon, Pleroma and Pixelfed. + * + * @param url Base URL of SNS. + * @param proxyConfig Proxy setting, or set false if don't use proxy. + * @return SNS name. + */ +export const detector = async (url: string, proxyConfig: ProxyConfig | false = false): Promise<'mastodon' | 'pleroma' | 'misskey'> => { + let options: AxiosRequestConfig = { + headers: { + 'User-Agent': DEFAULT_UA + } + } + if (proxyConfig) { + options = Object.assign(options, { + httpsAgent: proxyAgent(proxyConfig) + }) + } + try { + const res = await axios.get(url + '/api/v1/instance', options) + if (res.data.version.includes('Pleroma')) { + return 'pleroma' + } else { + return 'mastodon' + } + } catch (err) { + await axios.post<{}>(url + '/api/meta', {}, options) + return 'misskey' + } +} + +/** + * Get client for each SNS according to megalodon interface. + * + * @param baseUrl hostname or base URL. + * @param accessToken access token from OAuth2 authorization + * @param userAgent UserAgent is specified in header on request. + * @param proxyConfig Proxy setting, or set false if don't use proxy. + * @return Client instance for each SNS you specified. + */ +const generator = ( + baseUrl: string, + accessToken: string | null = null, + userAgent: string | null = null, + proxyConfig: ProxyConfig | false = false +): MegalodonInterface => new Misskey(baseUrl, accessToken, userAgent, proxyConfig) + +export default generator diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts new file mode 100644 index 000000000..cc9447868 --- /dev/null +++ b/packages/megalodon/src/misskey.ts @@ -0,0 +1,2631 @@ +import FormData from 'form-data' +import AsyncLock from 'async-lock'; + +import MisskeyAPI from './misskey/api_client' +import { DEFAULT_UA } from './default' +import { ProxyConfig } from './proxy_config' +import OAuth from './oauth' +import Response from './response' +import Entity from './entity' +import { MegalodonInterface, WebSocketInterface, NoImplementedError, ArgumentError, UnexpectedError } from './megalodon' +import MegalodonEntity from "@/entity"; +import fs from "node:fs"; + +type AccountCache = { + locks: AsyncLock, + accounts: Entity.Account[] +} + +export default class Misskey implements MegalodonInterface { + public client: MisskeyAPI.Interface + public converter: MisskeyAPI.Converter + public baseUrl: string + public proxyConfig: ProxyConfig | false + + /** + * @param baseUrl hostname or base URL + * @param accessToken access token from OAuth2 authorization + * @param userAgent UserAgent is specified in header on request. + * @param proxyConfig Proxy setting, or set false if don't use proxy. + */ + constructor( + baseUrl: string, + accessToken: string | null = null, + userAgent: string | null = DEFAULT_UA, + proxyConfig: ProxyConfig | false = false + ) { + let token: string = '' + if (accessToken) { + token = accessToken + } + let agent: string = DEFAULT_UA + if (userAgent) { + agent = userAgent + } + this.converter = new MisskeyAPI.Converter(baseUrl) + this.client = new MisskeyAPI.Client(baseUrl, token, agent, proxyConfig, this.converter) + this.baseUrl = baseUrl + this.proxyConfig = proxyConfig + } + + private baseUrlToHost(baseUrl: string): string { + return baseUrl.replace('https://', '') + } + + public cancel(): void { + return this.client.cancel() + } + + public async registerApp( + client_name: string, + options: Partial<{ scopes: Array; redirect_uris: string; website: string }> = { + scopes: MisskeyAPI.DEFAULT_SCOPE, + redirect_uris: this.baseUrl + } + ): Promise { + return this.createApp(client_name, options).then(async appData => { + return this.generateAuthUrlAndToken(appData.client_secret).then(session => { + appData.url = session.url + appData.session_token = session.token + return appData + }) + }) + } + + + /** + * POST /api/app/create + * + * Create an application. + * @param client_name Your application's name. + * @param options Form data. + */ + public async createApp( + client_name: string, + options: Partial<{ scopes: Array; redirect_uris: string; website: string }> = { + scopes: MisskeyAPI.DEFAULT_SCOPE, + redirect_uris: this.baseUrl + } + ): Promise { + const redirect_uris = options.redirect_uris || this.baseUrl + const scopes = options.scopes || MisskeyAPI.DEFAULT_SCOPE + + const params: { + name: string + description: string + permission: Array + callbackUrl: string + } = { + name: client_name, + description: '', + permission: scopes, + callbackUrl: redirect_uris + } + + /** + * The response is: + { + "id": "xxxxxxxxxx", + "name": "string", + "callbackUrl": "string", + "permission": [ + "string" + ], + "secret": "string" + } + */ + return this.client.post('/api/app/create', params).then((res: Response) => { + const appData: OAuth.AppDataFromServer = { + id: res.data.id, + name: res.data.name, + website: null, + redirect_uri: res.data.callbackUrl, + client_id: '', + client_secret: res.data.secret + } + return OAuth.AppData.from(appData) + }) + } + + /** + * POST /api/auth/session/generate + */ + public async generateAuthUrlAndToken(clientSecret: string): Promise { + return this.client + .post('/api/auth/session/generate', { + appSecret: clientSecret + }) + .then((res: Response) => res.data) + } + + // ====================================== + // apps + // ====================================== + public async verifyAppCredentials(): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // apps/oauth + // ====================================== + /** + * POST /api/auth/session/userkey + * + * @param _client_id This parameter is not used in this method. + * @param client_secret Application secret key which will be provided in createApp. + * @param session_token Session token string which will be provided in generateAuthUrlAndToken. + * @param _redirect_uri This parameter is not used in this method. + */ + public async fetchAccessToken( + _client_id: string | null, + client_secret: string, + session_token: string, + _redirect_uri?: string + ): Promise { + return this.client + .post('/api/auth/session/userkey', { + appSecret: client_secret, + token: session_token + }) + .then(res => { + const token = new OAuth.TokenData(res.data.accessToken, 'misskey', '', 0, null, null) + return token + }) + } + + public async refreshToken(_client_id: string, _client_secret: string, _refresh_token: string): Promise { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async revokeToken(_client_id: string, _client_secret: string, _token: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // accounts + // ====================================== + public async registerAccount( + _username: string, + _email: string, + _password: string, + _agreement: boolean, + _locale: string, + _reason?: string | null + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/i + */ + public async verifyAccountCredentials(): Promise> { + return this.client.post('/api/i').then(res => { + return Object.assign(res, { + data: this.converter.userDetail(res.data, this.baseUrlToHost(this.baseUrl)) + }) + }) + } + + /** + * POST /api/i/update + */ + public async updateCredentials(options?: { + discoverable?: boolean + bot?: boolean + display_name?: string + note?: string + avatar?: string + header?: string + locked?: boolean + source?: { + privacy?: string + sensitive?: boolean + language?: string + } | null + fields_attributes?: Array<{ name: string; value: string }> + }): Promise> { + let params = {} + if (options) { + if (options.bot !== undefined) { + params = Object.assign(params, { + isBot: options.bot + }) + } + if (options.display_name) { + params = Object.assign(params, { + name: options.display_name + }) + } + if (options.note) { + params = Object.assign(params, { + description: options.note + }) + } + if (options.locked !== undefined) { + params = Object.assign(params, { + isLocked: options.locked + }) + } + if (options.source) { + if (options.source.language) { + params = Object.assign(params, { + lang: options.source.language + }) + } + if (options.source.sensitive) { + params = Object.assign(params, { + alwaysMarkNsfw: options.source.sensitive + }) + } + } + } + return this.client.post('/api/i', params).then(res => { + return Object.assign(res, { + data: this.converter.userDetail(res.data, this.baseUrlToHost(this.baseUrl)) + }) + }) + } + + /** + * POST /api/users/show + */ + public async getAccount(id: string): Promise> { + return this.client + .post('/api/users/show', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.userDetail(res.data, this.baseUrlToHost(this.baseUrl)) + }) + }) + } + + public async getAccountByName(user: string, host: string | null): Promise> { + return this.client + .post('/api/users/show', { + username: user, + host: host ?? null + }) + .then(res => { + return Object.assign(res, { + data: this.converter.userDetail(res.data, this.baseUrlToHost(this.baseUrl)) + }) + }) + } + + /** + * POST /api/users/notes + */ + public async getAccountStatuses( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + pinned?: boolean + exclude_replies: boolean + exclude_reblogs: boolean + only_media?: boolean + } + ): Promise>> { + const accountCache = this.getFreshAccountCache(); + + if (options?.pinned) { + return this.client + .post('/api/users/show', { + userId: id + }) + .then(async res => { + if (res.data.pinnedNotes) { + return { + ...res, + data: await Promise.all(res.data.pinnedNotes.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + } + } + return {...res, data: []} + }) + } + + let params = { + userId: id + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.exclude_replies) { + params = Object.assign(params, { + includeReplies: false + }) + } + if (options.exclude_reblogs) { + params = Object.assign(params, { + includeMyRenotes: false + }) + } + if (options.only_media) { + params = Object.assign(params, { + withFiles: options.only_media + }) + } + } else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client.post>('/api/users/notes', params).then(async res => { + const statuses: Array = await Promise.all(res.data.map(note => this.noteWithMentions(note, this.baseUrlToHost(this.baseUrl), accountCache))) + return Object.assign(res, { + data: statuses + }) + }) + } + + public async getAccountFavourites( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = { + userId: id + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + } + return this.client.post>('/api/users/reactions', params).then(async res => { + return Object.assign(res, { + data: await Promise.all(res.data.map(fav => this.noteWithMentions(fav.note, this.baseUrlToHost(this.baseUrl), accountCache))) + }) + }) + } + + public async subscribeAccount(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async unsubscribeAccount(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/users/followers + */ + public async getAccountFollowers( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> { + let params = { + userId: id + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + return this.client.post>('/api/users/followers', params).then(res => { + return Object.assign(res, { + data: res.data.map(f => this.converter.follower(f)) + }) + }) + } + + /** + * POST /api/users/following + */ + public async getAccountFollowing( + id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> { + let params = { + userId: id + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + } + return this.client.post>('/api/users/following', params).then(res => { + return Object.assign(res, { + data: res.data.map(f => this.converter.following(f)) + }) + }) + } + + public async getAccountLists(_id: string): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getIdentityProof(_id: string): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/following/create + */ + public async followAccount(id: string, _options?: { reblog?: boolean }): Promise> { + await this.client.post<{}>('/api/following/create', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/following/delete + */ + public async unfollowAccount(id: string): Promise> { + await this.client.post<{}>('/api/following/delete', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/blocking/create + */ + public async blockAccount(id: string): Promise> { + await this.client.post<{}>('/api/blocking/create', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/blocking/delete + */ + public async unblockAccount(id: string): Promise> { + await this.client.post<{}>('/api/blocking/delete', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/mute/create + */ + public async muteAccount(id: string, _notifications: boolean): Promise> { + await this.client.post<{}>('/api/mute/create', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/mute/delete + */ + public async unmuteAccount(id: string): Promise> { + await this.client.post<{}>('/api/mute/delete', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + public async pinAccount(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async unpinAccount(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/users/relation + * + * @param id The accountID, for example `'1sdfag'` + */ + public async getRelationship(id: string): Promise> { + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/users/relation + * + * @param id Array of account ID, for example `['1sdfag', 'ds12aa']`. + */ + public async getRelationships(ids: Array): Promise>> { + return Promise.all(ids.map(id => this.getRelationship(id))).then(results => ({ + ...results[0], + data: results.map(r => r.data) + })) + } + + /** + * POST /api/users/search + */ + public async searchAccount( + q: string, + options?: { + following?: boolean + resolve?: boolean + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> { + let params = { + query: q, + detail: true + } + if (options) { + if (options.resolve !== undefined) { + params = Object.assign(params, { + localOnly: options.resolve + }) + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + return this.client.post>('/api/users/search', params).then(res => { + return Object.assign(res, { + data: res.data.map(u => this.converter.userDetail(u, this.baseUrlToHost(this.baseUrl))) + }) + }) + } + + // ====================================== + // accounts/bookmarks + // ====================================== + /** + * POST /api/i/favorites + */ + public async getBookmarks(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = {} + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + return this.client.post>('/api/i/favorites', params).then(async res => { + return Object.assign(res, { + data: await Promise.all(res.data.map(s => this.noteWithMentions(s.note, this.baseUrlToHost(this.baseUrl), accountCache))) + }) + }) + } + + // ====================================== + // accounts/favourites + // ====================================== + public async getFavourites(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> { + const userId = await this.client.post('/api/i').then(res => res.data.id); + return this.getAccountFavourites(userId, options); + } + + // ====================================== + // accounts/mutes + // ====================================== + /** + * POST /api/mute/list + */ + public async getMutes(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> { + let params = {} + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + return this.client.post>('/api/mute/list', params).then(res => { + return Object.assign(res, { + data: res.data.map(mute => this.converter.userDetail(mute.mutee, this.baseUrlToHost(this.baseUrl))) + }) + }) + } + + // ====================================== + // accounts/blocks + // ====================================== + /** + * POST /api/blocking/list + */ + public async getBlocks(options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> { + let params = {} + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 40 + }) + } + return this.client.post>('/api/blocking/list', params).then(res => { + return Object.assign(res, { + data: res.data.map(blocking => this.converter.userDetail(blocking.blockee, this.baseUrlToHost(this.baseUrl))) + }) + }) + } + + // ====================================== + // accounts/domain_blocks + // ====================================== + public async getDomainBlocks(_options?: { limit?: number; max_id?: string; min_id?: string }): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async blockDomain(_domain: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async unblockDomain(_domain: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // accounts/filters + // ====================================== + public async getFilters(): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getFilter(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async createFilter( + _phrase: string, + _context: Array, + _options?: { + irreversible?: boolean + whole_word?: boolean + expires_in?: string + } + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async updateFilter( + _id: string, + _phrase: string, + _context: Array, + _options?: { + irreversible?: boolean + whole_word?: boolean + expires_in?: string + } + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async deleteFilter(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // accounts/reports + // ====================================== + /** + * POST /api/users/report-abuse + */ + public async report( + account_id: string, + comment: string, + _options?: { + status_ids?: Array + forward?: boolean + } + ): Promise> { + return this.client + .post<{}>('/api/users/report-abuse', { + userId: account_id, + comment: comment + }) + .then(res => { + return Object.assign(res, { + data: { + id: '', + action_taken: '', + comment: comment, + account_id: account_id, + status_ids: [] + } + }) + }) + } + + // ====================================== + // accounts/follow_requests + // ====================================== + /** + * POST /api/following/requests/list + */ + public async getFollowRequests(_limit?: number): Promise>> { + return this.client.post>('/api/following/requests/list').then(res => { + return Object.assign(res, { + data: res.data.map(r => this.converter.user(r.follower)) + }) + }) + } + + /** + * POST /api/following/requests/accept + */ + public async acceptFollowRequest(id: string): Promise> { + await this.client.post<{}>('/api/following/requests/accept', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + /** + * POST /api/following/requests/reject + */ + public async rejectFollowRequest(id: string): Promise> { + await this.client.post<{}>('/api/following/requests/reject', { + userId: id + }) + return this.client + .post('/api/users/relation', { + userId: id + }) + .then(res => { + return Object.assign(res, { + data: this.converter.relation(res.data) + }) + }) + } + + // ====================================== + // accounts/endorsements + // ====================================== + public async getEndorsements(_options?: { + limit?: number + max_id?: string + since_id?: string + }): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // accounts/featured_tags + // ====================================== + public async getFeaturedTags(): Promise>> { + return this.getAccountFeaturedTags(); + } + + public async getAccountFeaturedTags(): Promise>> { + const tags : Entity.FeaturedTag[] = []; + const res : Response = { + headers: undefined, + statusText: "", + status: 200, + data: tags + }; + return new Promise(resolve => resolve(res)) + } + + public async createFeaturedTag(_name: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async deleteFeaturedTag(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getSuggestedTags(): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // accounts/preferences + // ====================================== + public async getPreferences(): Promise> { + return this.client.post('/api/i').then(res => { + /* + return this.client.post('/api/i/registry/get-all', { + scope: ['client', 'base'], + }).then(ga => { + return Object.assign(res, { + data: this.converter.userPreferences(res.data, ga.data) + }) + }) + */ + + // TODO: + // FIXME: get this from api + return Object.assign(res, { + data: this.converter.userPreferences(res.data, {defaultNoteVisibility: "followers", tutorial: -1}) + }) + }) + } + + // ====================================== + // accounts/suggestions + // ====================================== + /** + * POST /api/users/recommendation + */ + public async getSuggestions(limit?: number): Promise>> { + let params = {} + if (limit) { + params = Object.assign(params, { + limit: limit + }) + } + return this.client + .post>('/api/users/recommendation', params) + .then(res => ({ ...res, data: res.data.map(u => this.converter.userDetail(u, this.baseUrlToHost(this.baseUrl))) })) + } + + // ====================================== + // accounts/tags + // ====================================== + public async getFollowedTags(): Promise>> { + const tags : Entity.Tag[] = []; + const res : Response = { + headers: undefined, + statusText: "", + status: 200, + data: tags + }; + return new Promise(resolve => resolve(res)) + } + + public async getTag(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async followTag(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async unfollowTag(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // statuses + // ====================================== + public async postStatus( + status: string, + options?: { + media_ids?: Array + poll?: { options: Array; expires_in: number; multiple?: boolean; hide_totals?: boolean } + in_reply_to_id?: string + sensitive?: boolean + spoiler_text?: string + visibility?: 'public' | 'unlisted' | 'private' | 'direct' + scheduled_at?: string + language?: string + quote_id?: string + } + ): Promise> { + let params = { + text: status + } + if (options) { + if (options.media_ids) { + params = Object.assign(params, { + fileIds: options.media_ids + }) + } + if (options.poll) { + let pollParam = { + choices: options.poll.options, + expiresAt: null, + expiredAfter: options.poll.expires_in + } + if (options.poll.multiple !== undefined) { + pollParam = Object.assign(pollParam, { + multiple: options.poll.multiple + }) + } + params = Object.assign(params, { + poll: pollParam + }) + } + if (options.in_reply_to_id) { + params = Object.assign(params, { + replyId: options.in_reply_to_id + }) + } + if (options.sensitive) { + params = Object.assign(params, { + cw: '' + }) + } + if (options.spoiler_text) { + params = Object.assign(params, { + cw: options.spoiler_text + }) + } + if (options.visibility) { + params = Object.assign(params, { + visibility: this.converter.encodeVisibility(options.visibility) + }) + } + if (options.quote_id) { + params = Object.assign(params, { + renoteId: options.quote_id + }) + } + } + return this.client + .post('/api/notes/create', params) + .then(async res => ({ + ...res, + data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + })) + } + + /** + * POST /api/notes/show + */ + public async getStatus(id: string): Promise> { + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({ ...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); + } + + private getFreshAccountCache() :AccountCache { + return { + locks: new AsyncLock(), + accounts: [] + } + } + + public async noteWithMentions(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { + const status = await this.converter.note(n, host); + return status.mentions.length === 0 ? this.addMentionsToStatus(status, cache) : status; + } + + public async addMentionsToStatus(status: Entity.Status, cache: AccountCache) : Promise { + status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); + for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { + status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); + } + return status; + } + + public async getMentions(text: string, cache: AccountCache): Promise { + const mentions :Entity.Mention[] = []; + const mentionMatch = text.matchAll(/(?<=^|\s)@(?.*?)(?:@(?.*?)|)(?=\s|$)/g); + + for (const m of mentionMatch) { + if (m.groups == null) + continue; + + const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); + + if (account == null) + continue; + + mentions.push({ + id: account.id, + url: account.url, + username: account.username, + acct: account.acct + }); + } + + return mentions; + } + + public async getAccountByNameCached(user: string, host: string | null, cache: AccountCache): Promise { + const acctToFind = host == null ? user : `${user}@${host}`; + + return await cache.locks.acquire(acctToFind, async () => { + const cacheHit = cache.accounts.find(p => p.acct === acctToFind); + const account = cacheHit ?? (await this.getAccountByName(user, host ?? null)).data; + + if (!account) { + return null; + } + + if (cacheHit == null) { + cache.accounts.push(account); + } + + return account; + }) + } + + public async editStatus( + _id: string, + _options: { + status?: string + spoiler_text?: string + sensitive?: boolean + media_ids?: Array + poll?: { options?: Array; expires_in?: number; multiple?: boolean; hide_totals?: boolean } + } + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/notes/delete + */ + public async deleteStatus(id: string): Promise> { + return this.client.post<{}>('/api/notes/delete', { + noteId: id + }) + } + + /** + * POST /api/notes/children + */ + public async getStatusContext( + id: string, + options?: { limit?: number; max_id?: string; since_id?: string } + ): Promise> { + let params = { + noteId: id + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit, + depth: 12 + }) + } + else { + params = Object.assign(params, { + limit: 30, + depth: 12 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + } + else { + params = Object.assign(params, { + limit: 30, + depth: 12 + }) + } + return this.client.post>('/api/notes/children', params).then(async res => { + const accountCache = this.getFreshAccountCache(); + const conversation = await this.client.post>('/api/notes/conversation', params); + const parents = await Promise.all(conversation.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))); + + const context: Entity.Context = { + ancestors: parents.reverse(), + descendants: this.dfs(await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache)))) + } + return { + ...res, + data: context + } + }) + } + + private dfs(graph: Entity.Status[]) { + // we don't need to run dfs if we have zero or one elements + if (graph.length <= 1) { + return graph; + } + + // sort the graph first, so we can grab the correct starting point + graph = graph.sort((a, b) => { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + return 0; + }); + + const initialPostId = graph[0].in_reply_to_id; + + // populate stack with all top level replies + const stack = graph.filter(reply => reply.in_reply_to_id === initialPostId).reverse(); + const visited = new Set(); + const result = []; + + while (stack.length) { + const currentPost = stack.pop(); + + if (currentPost === undefined) + return result; + + if (!visited.has(currentPost)) { + visited.add(currentPost); + result.push(currentPost); + + for (const reply of graph.filter(reply => reply.in_reply_to_id === currentPost.id).reverse()) { + stack.push(reply); + } + } + } + + return result; + } + + public async getStatusHistory(): Promise>> { + // FIXME: stub, implement once we have note edit history in the database + const history : Entity.StatusEdit[] = []; + const res : Response = { + headers: undefined, + statusText: "", + status: 200, + data: history + }; + return new Promise(resolve => resolve(res)) + } + + /** + * POST /api/notes/renotes + */ + public async getStatusRebloggedBy(id: string): Promise>> { + return this.client + .post>('/api/notes/renotes', { + noteId: id + }) + .then(res => ({ + ...res, + data: res.data.map(n => this.converter.user(n.user)) + })) + } + + public async getStatusFavouritedBy(_id: string): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async favouriteStatus(id: string): Promise> { + return this.createEmojiReaction(id, await this.getDefaultFavoriteEmoji()); + } + + private async getDefaultFavoriteEmoji(): Promise { + // NOTE: get-unsecure is calckey's extension. + // Misskey doesn't have this endpoint and regular `/i/registry/get` won't work + // unless you have a 'nativeToken', which is reserved for the frontend webapp. + + return await this.client + .post>('/api/i/registry/get-unsecure', { + key: 'reactions', + scope: ['client', 'base'], + }) + .then(res => res.data[0] ?? '⭐'); + } + + public async unfavouriteStatus(id: string): Promise> { + // NOTE: Misskey allows only one reaction per status, so we don't need to care what that emoji was. + return this.deleteEmojiReaction(id, ''); + } + + /** + * POST /api/notes/create + */ + public async reblogStatus(id: string): Promise> { + return this.client + .post('/api/notes/create', { + renoteId: id + }) + .then(async res => ({ + ...res, + data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + })) + } + + /** + * POST /api/notes/unrenote + */ + public async unreblogStatus(id: string): Promise> { + await this.client.post<{}>('/api/notes/unrenote', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + /** + * POST /api/notes/favorites/create + */ + public async bookmarkStatus(id: string): Promise> { + await this.client.post<{}>('/api/notes/favorites/create', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + /** + * POST /api/notes/favorites/delete + */ + public async unbookmarkStatus(id: string): Promise> { + await this.client.post<{}>('/api/notes/favorites/delete', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + public async muteStatus(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async unmuteStatus(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/i/pin + */ + public async pinStatus(id: string): Promise> { + await this.client.post<{}>('/api/i/pin', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + /** + * POST /api/i/unpin + */ + public async unpinStatus(id: string): Promise> { + await this.client.post<{}>('/api/i/unpin', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + // ====================================== + // statuses/media + // ====================================== + /** + * POST /api/drive/files/create + */ + public async uploadMedia(file: any, _options?: { description?: string; focus?: string }): Promise> { + const formData = new FormData() + formData.append('file', fs.createReadStream(file.path), { + contentType: file.mimetype, + filename: file.originalname, + }) + let headers: { [key: string]: string } = {} + if (typeof formData.getHeaders === 'function') { + headers = formData.getHeaders() + } + return this.client + .post('/api/drive/files/create', formData, headers) + .then(res => ({ ...res, data: this.converter.file(res.data) })) + } + + public async getMedia(id: string): Promise> { + const res = await this.client.post('/api/drive/files/show', { fileId: id }) + return { ...res, data: this.converter.file(res.data) } + } + + /** + * POST /api/drive/files/update + */ + public async updateMedia( + id: string, + options?: { + file?: any + description?: string + focus?: string + is_sensitive?: boolean + } + ): Promise> { + let params = { + fileId: id + } + if (options) { + if (options.is_sensitive !== undefined) { + params = Object.assign(params, { + isSensitive: options.is_sensitive + }) + } + } + return this.client + .post('/api/drive/files/update', params) + .then(res => ({ ...res, data: this.converter.file(res.data) })) + } + + // ====================================== + // statuses/polls + // ====================================== + public async getPoll(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/notes/polls/vote + */ + public async votePoll(_id: string, choices: Array, status_id?: string | null): Promise> { + if (!status_id) { + return new Promise((_, reject) => { + const err = new ArgumentError('status_id is required') + reject(err) + }) + } + const params = { + noteId: status_id, + choice: choices[0] + } + await this.client.post<{}>('/api/notes/polls/vote', params) + const res = await this.client + .post('/api/notes/show', { + noteId: status_id + }) + .then(async res => { + const note = await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + return {...res, data: note.poll} + }) + if (!res.data) { + return new Promise((_, reject) => { + const err = new UnexpectedError('poll does not exist') + reject(err) + }) + } + return { ...res, data: res.data } + } + + // ====================================== + // statuses/scheduled_statuses + // ====================================== + public async getScheduledStatuses(_options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getScheduledStatus(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async scheduleStatus(_id: string, _scheduled_at?: string | null): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async cancelScheduledStatus(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // timelines + // ====================================== + /** + * POST /api/notes/global-timeline + */ + public async getPublicTimeline(options?: { + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = {} + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }) + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/global-timeline', params) + .then(async res => ({ + ...res, + data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + })) + } + + /** + * POST /api/notes/local-timeline + */ + public async getLocalTimeline(options?: { + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = {} + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }) + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/local-timeline', params) + .then(async res => ({ + ...res, + data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + })) + } + + /** + * POST /api/notes/search-by-tag + */ + public async getTagTimeline( + hashtag: string, + options?: { + local?: boolean + only_media?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + } + ): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = { + tag: hashtag + } + if (options) { + if (options.only_media !== undefined) { + params = Object.assign(params, { + withFiles: options.only_media + }) + } + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/search-by-tag', params) + .then(async res => ({ + ...res, + data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + })) + } + + /** + * POST /api/notes/timeline + */ + public async getHomeTimeline(options?: { + local?: boolean + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = { + withFiles: false + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/timeline', params) + .then(async res => ({ + ...res, + data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + })) + } + + /** + * POST /api/notes/user-list-timeline + */ + public async getListTimeline( + list_id: string, + options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + } + ): Promise>> { + const accountCache = this.getFreshAccountCache(); + + let params = { + listId: list_id, + withFiles: false + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/user-list-timeline', params) + .then(async res => ({ ...res, data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) + } + + // ====================================== + // timelines/conversations + // ====================================== + /** + * POST /api/notes/mentions + */ + public async getConversationTimeline(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + }): Promise>> { + let params = { + visibility: 'specified' + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/notes/mentions', params) + .then(res => ({ ...res, data: res.data.map(n => this.converter.noteToConversation(n, this.baseUrlToHost(this.baseUrl))) })) + // FIXME: ^ this should also parse mentions + } + + public async deleteConversation(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async readConversation(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // timelines/lists + // ====================================== + /** + * POST /api/users/lists/list + */ + public async getLists(): Promise>> { + return this.client + .post>('/api/users/lists/list') + .then(res => ({ ...res, data: res.data.map(l => this.converter.list(l)) })) + } + + /** + * POST /api/users/lists/show + */ + public async getList(id: string): Promise> { + return this.client + .post('/api/users/lists/show', { + listId: id + }) + .then(res => ({ ...res, data: this.converter.list(res.data) })) + } + + /** + * POST /api/users/lists/create + */ + public async createList(title: string): Promise> { + return this.client + .post('/api/users/lists/create', { + name: title + }) + .then(res => ({ ...res, data: this.converter.list(res.data) })) + } + + /** + * POST /api/users/lists/update + */ + public async updateList(id: string, title: string): Promise> { + return this.client + .post('/api/users/lists/update', { + listId: id, + name: title + }) + .then(res => ({ ...res, data: this.converter.list(res.data) })) + } + + /** + * POST /api/users/lists/delete + */ + public async deleteList(id: string): Promise> { + return this.client.post<{}>('/api/users/lists/delete', { + listId: id + }) + } + + /** + * POST /api/users/lists/show + */ + public async getAccountsInList( + id: string, + _options?: { + limit?: number + max_id?: string + since_id?: string + } + ): Promise>> { + const res = await this.client.post('/api/users/lists/show', { + listId: id + }) + const promise = res.data.userIds.map(userId => this.getAccount(userId)) + const accounts = await Promise.all(promise) + return { ...res, data: accounts.map(r => r.data) } + } + + /** + * POST /api/users/lists/push + */ + public async addAccountsToList(id: string, account_ids: Array): Promise> { + return this.client.post<{}>('/api/users/lists/push', { + listId: id, + userId: account_ids[0] + }) + } + + /** + * POST /api/users/lists/pull + */ + public async deleteAccountsFromList(id: string, account_ids: Array): Promise> { + return this.client.post<{}>('/api/users/lists/pull', { + listId: id, + userId: account_ids[0] + }) + } + + // ====================================== + // timelines/markers + // ====================================== + public async getMarkers(_timeline: Array): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async saveMarkers(_options?: { + home?: { last_read_id: string } + notifications?: { last_read_id: string } + }): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // notifications + // ====================================== + /** + * POST /api/i/notifications + */ + public async getNotifications(options?: { + limit?: number + max_id?: string + since_id?: string + min_id?: string + exclude_type?: Array + account_id?: string + }): Promise>> { + let params = {} + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.since_id) { + params = Object.assign(params, { + sinceId: options.since_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + if (options.exclude_type) { + params = Object.assign(params, { + excludeType: options.exclude_type.map(e => this.converter.encodeNotificationType(e)) + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + return this.client + .post>('/api/i/notifications', params) + .then(res => ({ ...res, data: res.data.map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) + } + + public async getNotification(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * POST /api/notifications/mark-all-as-read + */ + public async dismissNotifications(): Promise> { + return this.client.post<{}>('/api/notifications/mark-all-as-read') + } + + public async dismissNotification(_id: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async readNotifications(_options: { + id?: string + max_id?: string + }): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('mastodon does not support') + reject(err) + }) + } + + // ====================================== + // notifications/push + // ====================================== + public async subscribePushNotification( + _subscription: { endpoint: string; keys: { p256dh: string; auth: string } }, + _data?: { alerts: { follow?: boolean; favourite?: boolean; reblog?: boolean; mention?: boolean; poll?: boolean } } | null + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getPushSubscription(): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async updatePushSubscription( + _data?: { alerts: { follow?: boolean; favourite?: boolean; reblog?: boolean; mention?: boolean; poll?: boolean } } | null + ): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + /** + * DELETE /api/v1/push/subscription + */ + public async deletePushSubscription(): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // search + // ====================================== + public async search( + q: string, + type: 'accounts' | 'hashtags' | 'statuses', + options?: { + limit?: number + max_id?: string + min_id?: string + resolve?: boolean + offset?: number + following?: boolean + account_id?: string + exclude_unreviewed?: boolean + } + ): Promise> { + const accountCache = this.getFreshAccountCache(); + + switch (type) { + case 'accounts': { + let params = { + query: q + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }) + } + if (options.resolve) { + params = Object.assign(params, { + localOnly: options.resolve + }) + } + } + else { + params = Object.assign(params, { + limit: 20 + }) + } + + try { + const match = q.match(/^@(?.*?)(?:@(?.*?)|)$/); + if (match) { + const lookupQuery = { + username: match.groups?.user, + host: match.groups?.host + }; + + const result = await this.client.post('/api/users/show', lookupQuery).then(res => ({ + ...res, + data: { + accounts: [this.converter.userDetail(res.data, this.baseUrlToHost(this.baseUrl))], + statuses: [], + hashtags: [] + } + })); + + if (result.status !== 200) { + result.status = 200; + result.statusText = "OK"; + result.data = { + accounts: [], + statuses: [], + hashtags: [] + }; + } + + return result; + } + } + catch {} + + return this.client.post>('/api/users/search', params).then(res => ({ + ...res, + data: { + accounts: res.data.map(u => this.converter.userDetail(u, this.baseUrlToHost(this.baseUrl))), + statuses: [], + hashtags: [] + } + })) + } + case 'statuses': { + let params = { + query: q + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }) + } + if (options.max_id) { + params = Object.assign(params, { + untilId: options.max_id + }) + } + if (options.min_id) { + params = Object.assign(params, { + sinceId: options.min_id + }) + } + if (options.account_id) { + params = Object.assign(params, { + userId: options.account_id + }) + } + } + return this.client.post>('/api/notes/search', params).then(async res => ({ + ...res, + data: { + accounts: [], + statuses: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))), + hashtags: [] + } + })) + } + case 'hashtags': { + let params = { + query: q + } + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit + }) + } + if (options.offset) { + params = Object.assign(params, { + offset: options.offset + }) + } + } + return this.client.post>('/api/hashtags/search', params).then(res => ({ + ...res, + data: { + accounts: [], + statuses: [], + hashtags: res.data.map(h => ({ name: h, url: h, history: null, following: false })) + } + })) + } + } + } + + // ====================================== + // instance + // ====================================== + /** + * POST /api/meta + * POST /api/stats + */ + public async getInstance(): Promise> { + const meta = await this.client.post('/api/meta').then(res => res.data) + return this.client + .post('/api/stats') + .then(res => ({ ...res, data: this.converter.meta(meta, res.data) })) + } + + public async getInstancePeers(): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public async getInstanceActivity(): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // instance/trends + // ====================================== + /** + * POST /api/hashtags/trend + */ + public async getInstanceTrends(_limit?: number | null): Promise>> { + return this.client + .post>('/api/hashtags/trend') + .then(res => ({ ...res, data: res.data.map(h => this.converter.hashtag(h)) })) + } + + // ====================================== + // instance/directory + // ====================================== + public async getInstanceDirectory(_options?: { + limit?: number + offset?: number + order?: 'active' | 'new' + local?: boolean + }): Promise>> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + // ====================================== + // instance/custom_emojis + // ====================================== + /** + * POST /api/meta + */ + public async getInstanceCustomEmojis(): Promise>> { + return this.client + .post('/api/meta') + .then(res => ({ ...res, data: res.data.emojis.map(e => this.converter.emoji(e)) })) + } + + // ====================================== + // instance/announcements + // ====================================== + public async getInstanceAnnouncements(with_dismissed?: boolean | null): Promise>> { + let params = {} + if (with_dismissed) { + params = Object.assign(params, { + withUnreads: with_dismissed + }) + } + return this.client.post>('/api/announcements', params).then(res => ({ + ...res, + data: res.data.map(t => this.converter.announcement(t)) + })) + } + + public async dismissInstanceAnnouncement(id: string): Promise> { + return this.client.post<{}>('/api/i/read-announcement', { announcementId: id }) + } + + // ====================================== + // Emoji reactions + // ====================================== + /** + * POST /api/notes/reactions/create + * + * @param {string} id Target note ID. + * @param {string} emoji Reaction emoji string. This string is raw unicode emoji. + */ + public async createEmojiReaction(id: string, emoji: string): Promise> { + await this.client.post<{}>('/api/notes/reactions/create', { + noteId: id, + reaction: emoji + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + /** + * POST /api/notes/reactions/delete + */ + public async deleteEmojiReaction(id: string, _emoji: string): Promise> { + await this.client.post<{}>('/api/notes/reactions/delete', { + noteId: id + }) + return this.client + .post('/api/notes/show', { + noteId: id + }) + .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + } + + public async getEmojiReactions(id: string): Promise>> { + return this.client + .post>('/api/notes/reactions', { + noteId: id + }) + .then(res => ({ + ...res, + data: this.converter.reactions(res.data) + })) + } + + public async getEmojiReaction(_id: string, _emoji: string): Promise> { + return new Promise((_, reject) => { + const err = new NoImplementedError('misskey does not support') + reject(err) + }) + } + + public userSocket(): WebSocketInterface { + return this.client.socket('user') + } + + public publicSocket(): WebSocketInterface { + return this.client.socket('globalTimeline') + } + + public localSocket(): WebSocketInterface { + return this.client.socket('localTimeline') + } + + public tagSocket(_tag: string): WebSocketInterface { + throw new NoImplementedError('TODO: implement') + } + + public listSocket(list_id: string): WebSocketInterface { + return this.client.socket('list', list_id) + } + + public directSocket(): WebSocketInterface { + return this.client.socket('conversation') + } +} diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts new file mode 100644 index 000000000..8185b222a --- /dev/null +++ b/packages/megalodon/src/misskey/api_client.ts @@ -0,0 +1,641 @@ +import axios, { AxiosResponse, AxiosRequestConfig } from 'axios' +import dayjs from 'dayjs' +import FormData from 'form-data' + +import { DEFAULT_UA } from '../default' +import proxyAgent, { ProxyConfig } from '../proxy_config' +import Response from '../response' +import MisskeyEntity from './entity' +import MegalodonEntity from '../entity' +import WebSocket from './web_socket' +import MisskeyNotificationType from './notification' +import NotificationType from '../notification' + +namespace MisskeyAPI { + export namespace Entity { + export type App = MisskeyEntity.App + export type Announcement = MisskeyEntity.Announcement + export type Blocking = MisskeyEntity.Blocking + export type Choice = MisskeyEntity.Choice + export type CreatedNote = MisskeyEntity.CreatedNote + export type Emoji = MisskeyEntity.Emoji + export type Favorite = MisskeyEntity.Favorite + export type Field = MisskeyEntity.Field + export type File = MisskeyEntity.File + export type Follower = MisskeyEntity.Follower + export type Following = MisskeyEntity.Following + export type FollowRequest = MisskeyEntity.FollowRequest + export type Hashtag = MisskeyEntity.Hashtag + export type List = MisskeyEntity.List + export type Meta = MisskeyEntity.Meta + export type Mute = MisskeyEntity.Mute + export type Note = MisskeyEntity.Note + export type Notification = MisskeyEntity.Notification + export type Poll = MisskeyEntity.Poll + export type Reaction = MisskeyEntity.Reaction + export type Relation = MisskeyEntity.Relation + export type User = MisskeyEntity.User + export type UserDetail = MisskeyEntity.UserDetail + export type UserDetailMe = MisskeyEntity.UserDetailMe + export type GetAll = MisskeyEntity.GetAll + export type UserKey = MisskeyEntity.UserKey + export type Session = MisskeyEntity.Session + export type Stats = MisskeyEntity.Stats + export type APIEmoji = { emojis: Emoji[] } + } + + export class Converter { + private baseUrl: string + private instanceHost: string + private plcUrl: string + private 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: 'plc', + avatar: 'plc', + avatar_static: 'plc', + header: 'plc', + header_static: 'plc', + followers_count: -1, + following_count: 0, + statuses_count: 0, + last_status_at: '1971-01-01T00:00:00.000Z', + noindex: true, + emojis: [], + fields: [], + moved: null + } + + constructor(baseUrl: string) { + this.baseUrl = baseUrl; + this.instanceHost = baseUrl.substring(baseUrl.indexOf('//') + 2); + this.plcUrl = `${baseUrl}/static-assets/transparent.png`; + this.modelOfAcct.url = this.plcUrl; + this.modelOfAcct.avatar = this.plcUrl; + this.modelOfAcct.avatar_static = this.plcUrl; + this.modelOfAcct.header = this.plcUrl; + this.modelOfAcct.header_static = this.plcUrl; + } + + + + // FIXME: Properly render MFM instead of just escaping HTML characters. + escapeMFM = (text: string): string => text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/`/g, '`') + .replace(/\r?\n/g, '
'); + + emoji = (e: Entity.Emoji): MegalodonEntity.Emoji => { + return { + shortcode: e.name, + static_url: e.url, + url: e.url, + visible_in_picker: true, + category: e.category + } + } + + field = (f: Entity.Field): MegalodonEntity.Field => ({ + name: f.name, + value: this.escapeMFM(f.value), + verified_at: null + }) + + user = (u: Entity.User): MegalodonEntity.Account => { + let acct = u.username + let acctUrl = `https://${u.host || this.instanceHost}/@${u.username}` + if (u.host) { + acct = `${u.username}@${u.host}` + acctUrl = `https://${u.host}/@${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: this.plcUrl, // FIXME + header_static: this.plcUrl, // FIXME + emojis: u.emojis.map(e => this.emoji(e)), + moved: null, + fields: [], + bot: false + } + } + + userDetail = (u: Entity.UserDetail, host: string): MegalodonEntity.Account => { + let acct = u.username + host = host.replace('https://', '') + let acctUrl = `https://${host || u.host || this.instanceHost}/@${u.username}` + if (u.host) { + acct = `${u.username}@${u.host}` + acctUrl = `https://${u.host}/@${u.username}` + } + return { + id: u.id, + username: u.username, + acct: acct, + display_name: u.name, + locked: u.isLocked, + created_at: u.createdAt, + followers_count: u.followersCount, + following_count: u.followingCount, + statuses_count: u.notesCount, + note: u.description, + url: acctUrl, + avatar: u.avatarUrl, + avatar_static: u.avatarUrl, + header: u.bannerUrl ?? this.plcUrl, + header_static: u.bannerUrl ?? this.plcUrl, + emojis: u.emojis.map(e => this.emoji(e)), + moved: null, + fields: u.fields.map(f => this.field(f)), + bot: u.isBot, + } + } + + userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll): MegalodonEntity.Preferences => { + return { + "reading:expand:media": "default", + "reading:expand:spoilers": false, + "posting:default:language": u.lang, + "posting:default:sensitive": u.alwaysMarkNsfw, + "posting:default:visibility": this.visibility(g.defaultNoteVisibility) + } + } + + visibility = (v: 'public' | 'home' | 'followers' | 'specified'): 'public' | 'unlisted' | 'private' | 'direct' => { + switch (v) { + case 'public': + return v + case 'home': + return 'unlisted' + case 'followers': + return 'private' + case 'specified': + return 'direct' + } + } + + encodeVisibility = (v: 'public' | 'unlisted' | 'private' | 'direct'): 'public' | 'home' | 'followers' | 'specified' => { + switch (v) { + case 'public': + return v + case 'unlisted': + return 'home' + case 'private': + return 'followers' + case 'direct': + return 'specified' + } + } + + fileType = (s: string): 'unknown' | 'image' | 'gifv' | 'video' | 'audio' => { + 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' + } + + file = (f: Entity.File): MegalodonEntity.Attachment => { + return { + id: f.id, + type: this.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: f.comment, + blurhash: f.blurhash + } + } + + follower = (f: Entity.Follower): MegalodonEntity.Account => { + return this.user(f.follower) + } + + following = (f: Entity.Following): MegalodonEntity.Account => { + return this.user(f.followee) + } + + relation = (r: Entity.Relation): MegalodonEntity.Relationship => { + 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 + } + } + + choice = (c: Entity.Choice): MegalodonEntity.PollOption => { + return { + title: c.text, + votes_count: c.votes + } + } + + poll = (p: Entity.Poll): MegalodonEntity.Poll => { + const now = dayjs() + const expire = dayjs(p.expiresAt) + const count = p.choices.reduce((sum, choice) => sum + choice.votes, 0) + return { + id: '', + expires_at: p.expiresAt, + expired: now.isAfter(expire), + multiple: p.multiple, + votes_count: count, + options: p.choices.map(c => this.choice(c)), + voted: p.choices.some(c => c.isVoted) + } + } + + note = (n: Entity.Note, host: string): MegalodonEntity.Status => { + host = host.replace('https://', '') + + return { + id: n.id, + uri: n.uri ? n.uri : `https://${host}/notes/${n.id}`, + url: n.uri ? n.uri : `https://${host}/notes/${n.id}`, + account: this.user(n.user), + in_reply_to_id: n.replyId, + in_reply_to_account_id: n.reply?.userId ?? null, + reblog: n.renote ? this.note(n.renote, host) : null, + content: n.text ? this.escapeMFM(n.text) : '', + plain_content: n.text ? n.text : null, + created_at: n.createdAt, + emojis: n.emojis.map(e => this.emoji(e)), + replies_count: n.repliesCount, + reblogs_count: n.renoteCount, + favourites_count: this.getTotalReactions(n.reactions), // FIXME: instead get # of default reaction emoji reactions + reblogged: false, + favourited: !!n.myReaction, + muted: false, + sensitive: n.files ? n.files.some(f => f.isSensitive) : false, + spoiler_text: n.cw ? n.cw : '', + visibility: this.visibility(n.visibility), + media_attachments: n.files ? n.files.map(f => this.file(f)) : [], + mentions: [], + tags: [], + card: null, + poll: n.poll ? this.poll(n.poll) : null, + application: null, + language: null, + pinned: null, + emoji_reactions: this.mapReactions(n.reactions, n.myReaction), + bookmarked: false, + quote: n.renote && n.text ? this.note(n.renote, host) : null + } + } + + mapReactions = (r: { [key: string]: number }, myReaction?: string): Array => { + return Object.keys(r).map(key => { + if (myReaction && key === myReaction) { + return { + count: r[key], + me: true, + name: key + } + } + return { + count: r[key], + me: false, + name: key + } + }) + } + + getTotalReactions = (r: { [key: string]: number }): number => { + return Object.values(r).length > 0 ? Object.values(r).reduce((previousValue, currentValue) => previousValue + currentValue) : 0 + } + + reactions = (r: Array): Array => { + const result: Array = [] + for (const e of r) { + const i = result.findIndex(res => res.name === e.type) + if (i >= 0) { + result[i].count++ + } else { + result.push({ + count: 1, + me: false, + name: e.type + }) + } + } + return result + } + + noteToConversation = (n: Entity.Note, host: string): MegalodonEntity.Conversation => { + const accounts: Array = [this.user(n.user)] + if (n.reply) { + accounts.push(this.user(n.reply.user)) + } + return { + id: n.id, + accounts: accounts, + last_status: this.note(n, host), + unread: false + } + } + + list = (l: Entity.List): MegalodonEntity.List => ({ + id: l.id, + title: l.name + }) + + encodeNotificationType = (e: MegalodonEntity.NotificationType): MisskeyEntity.NotificationType => { + switch (e) { + case NotificationType.Follow: + return MisskeyNotificationType.Follow + case NotificationType.Mention: + return MisskeyNotificationType.Reply + case NotificationType.Favourite: + case NotificationType.EmojiReaction: + return MisskeyNotificationType.Reaction + case NotificationType.Reblog: + return MisskeyNotificationType.Renote + case NotificationType.PollVote: + return MisskeyNotificationType.PollVote + case NotificationType.FollowRequest: + return MisskeyNotificationType.ReceiveFollowRequest + default: + return e + } + } + + decodeNotificationType = (e: MisskeyEntity.NotificationType): MegalodonEntity.NotificationType => { + 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.EmojiReaction + case MisskeyNotificationType.PollVote: + return NotificationType.PollVote + case MisskeyNotificationType.ReceiveFollowRequest: + return NotificationType.FollowRequest + case MisskeyNotificationType.FollowRequestAccepted: + return NotificationType.Follow + default: + return e + } + } + + + + announcement = (a: Entity.Announcement): MegalodonEntity.Announcement => ({ + id: a.id, + content: `

${this.escapeMFM(a.title)}

${this.escapeMFM(a.text)}`, + starts_at: null, + ends_at: null, + published: true, + all_day: false, + published_at: a.createdAt, + updated_at: a.updatedAt, + read: a.isRead, + mentions: [], + statuses: [], + tags: [], + emojis: [], + reactions: [], + }) + + notification = (n: Entity.Notification, host: string): MegalodonEntity.Notification => { + let notification = { + id: n.id, + account: n.user ? this.user(n.user) : this.modelOfAcct, + created_at: n.createdAt, + type: this.decodeNotificationType(n.type) + } + if (n.note) { + notification = Object.assign(notification, { + status: this.note(n.note, host) + }) + } + if (n.reaction) { + notification = Object.assign(notification, { + emoji: n.reaction + }) + } + return notification + } + + stats = (s: Entity.Stats): MegalodonEntity.Stats => { + return { + user_count: s.usersCount, + status_count: s.notesCount, + domain_count: s.instances + } + } + + meta = (m: Entity.Meta, s: Entity.Stats): MegalodonEntity.Instance => { + const 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: `${wss}/streaming` + }, + stats: this.stats(s), + languages: m.langs, + contact_account: null, + max_toot_chars: m.maxNoteTextLength, + registrations: !m.disableRegistration + } + } + + hashtag = (h: Entity.Hashtag): MegalodonEntity.Tag => { + return { + name: h.tag, + url: h.tag, + history: null, + following: false + } + } + } + + export const 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' + ] + + /** + * Interface + */ + export interface Interface { + post(path: string, params?: any, headers?: { [key: string]: string }): Promise> + cancel(): void + socket(channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', listId?: string): WebSocket + } + + /** + * Misskey API client. + * + * Usign axios for request, you will handle promises. + */ + export class Client implements Interface { + private accessToken: string | null + private baseUrl: string + private userAgent: string + private abortController: AbortController + private proxyConfig: ProxyConfig | false = false + private converter: Converter + + /** + * @param baseUrl hostname or base URL + * @param accessToken access token from OAuth2 authorization + * @param userAgent UserAgent is specified in header on request. + * @param proxyConfig Proxy setting, or set false if don't use proxy. + * @param converter Converter instance. + */ + constructor(baseUrl: string, accessToken: string | null, userAgent: string = DEFAULT_UA, proxyConfig: ProxyConfig | false = false, converter: Converter) { + this.accessToken = accessToken + this.baseUrl = baseUrl + this.userAgent = userAgent + this.proxyConfig = proxyConfig + this.abortController = new AbortController() + this.converter = converter + axios.defaults.signal = this.abortController.signal + } + + /** + * POST request to mastodon REST API. + * @param path relative path from baseUrl + * @param params Form data + * @param headers Request header object + */ + public async post(path: string, params: any = {}, headers: { [key: string]: string } = {}): Promise> { + let options: AxiosRequestConfig = { + headers: headers, + maxContentLength: Infinity, + maxBodyLength: Infinity + } + if (this.proxyConfig) { + options = Object.assign(options, { + httpAgent: proxyAgent(this.proxyConfig), + httpsAgent: proxyAgent(this.proxyConfig) + }) + } + let bodyParams = params + if (this.accessToken) { + if (params instanceof FormData) { + bodyParams.append('i', this.accessToken) + } else { + bodyParams = Object.assign(params, { + i: this.accessToken + }) + } + } + + console.log(`sending request to ${this.baseUrl}${path} with params:`); + console.log(JSON.stringify(bodyParams, null, 2)); + + return axios.post(this.baseUrl + path, bodyParams, options).then((resp: AxiosResponse) => { + const res: Response = { + data: resp.data, + status: resp.status, + statusText: resp.statusText, + headers: resp.headers + } + return res + }) + } + + /** + * Cancel all requests in this instance. + * @returns void + */ + public cancel(): void { + return this.abortController.abort() + } + + /** + * Get connection and receive websocket connection for Misskey API. + * + * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. + * @param listId This parameter is required only list channel. + */ + public socket( + channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', + listId?: string + ): WebSocket { + if (!this.accessToken) { + throw new Error('accessToken is required') + } + const url = `${this.baseUrl}/streaming` + const streaming = new WebSocket(url, channel, this.accessToken, listId, this.userAgent, this.proxyConfig, this.converter) + process.nextTick(() => { + streaming.start() + }) + return streaming + } + } +} + +export default MisskeyAPI diff --git a/packages/megalodon/src/misskey/entities/GetAll.ts b/packages/megalodon/src/misskey/entities/GetAll.ts new file mode 100644 index 000000000..c41bd3f1b --- /dev/null +++ b/packages/megalodon/src/misskey/entities/GetAll.ts @@ -0,0 +1,6 @@ +namespace MisskeyEntity { + export type GetAll = { + tutorial: number + defaultNoteVisibility: 'public' | 'home' | 'followers' | 'specified' + } +} diff --git a/packages/megalodon/src/misskey/entities/announcement.ts b/packages/megalodon/src/misskey/entities/announcement.ts new file mode 100644 index 000000000..95100cbf1 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/announcement.ts @@ -0,0 +1,10 @@ +namespace MisskeyEntity { + export type Announcement = { + id: string + createdAt: string + updatedAt: string + text: string + title: string + isRead?: boolean + } +} diff --git a/packages/megalodon/src/misskey/entities/app.ts b/packages/megalodon/src/misskey/entities/app.ts new file mode 100644 index 000000000..40a704b94 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/app.ts @@ -0,0 +1,9 @@ +namespace MisskeyEntity { + export type App = { + id: string + name: string + callbackUrl: string + permission: Array + secret: string + } +} diff --git a/packages/megalodon/src/misskey/entities/blocking.ts b/packages/megalodon/src/misskey/entities/blocking.ts new file mode 100644 index 000000000..9900a777b --- /dev/null +++ b/packages/megalodon/src/misskey/entities/blocking.ts @@ -0,0 +1,10 @@ +/// + +namespace MisskeyEntity { + export type Blocking = { + id: string + createdAt: string + blockeeId: string + blockee: UserDetail + } +} diff --git a/packages/megalodon/src/misskey/entities/createdNote.ts b/packages/megalodon/src/misskey/entities/createdNote.ts new file mode 100644 index 000000000..88ba60040 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/createdNote.ts @@ -0,0 +1,7 @@ +/// + +namespace MisskeyEntity { + export type CreatedNote = { + createdNote: Note + } +} diff --git a/packages/megalodon/src/misskey/entities/emoji.ts b/packages/megalodon/src/misskey/entities/emoji.ts new file mode 100644 index 000000000..e545a465d --- /dev/null +++ b/packages/megalodon/src/misskey/entities/emoji.ts @@ -0,0 +1,9 @@ +namespace MisskeyEntity { + export type Emoji = { + name: string + host: string | null + url: string + aliases: Array + category: string + } +} diff --git a/packages/megalodon/src/misskey/entities/favorite.ts b/packages/megalodon/src/misskey/entities/favorite.ts new file mode 100644 index 000000000..8ed7a54bf --- /dev/null +++ b/packages/megalodon/src/misskey/entities/favorite.ts @@ -0,0 +1,10 @@ +/// + +namespace MisskeyEntity { + export type Favorite = { + id: string + createdAt: string + noteId: string + note: Note + } +} diff --git a/packages/megalodon/src/misskey/entities/field.ts b/packages/megalodon/src/misskey/entities/field.ts new file mode 100644 index 000000000..f56d21b63 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/field.ts @@ -0,0 +1,6 @@ +namespace MisskeyEntity { + export type Field = { + name: string + value: string + } +} diff --git a/packages/megalodon/src/misskey/entities/file.ts b/packages/megalodon/src/misskey/entities/file.ts new file mode 100644 index 000000000..e9e29ff65 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/file.ts @@ -0,0 +1,20 @@ +namespace MisskeyEntity { + export type File = { + id: string + createdAt: string + name: string + type: string + md5: string + size: number + isSensitive: boolean + properties: { + width: number + height: number + avgColor: string + } + url: string + thumbnailUrl: string + comment: string + blurhash: string + } +} diff --git a/packages/megalodon/src/misskey/entities/followRequest.ts b/packages/megalodon/src/misskey/entities/followRequest.ts new file mode 100644 index 000000000..bd2777b2d --- /dev/null +++ b/packages/megalodon/src/misskey/entities/followRequest.ts @@ -0,0 +1,9 @@ +/// + +namespace MisskeyEntity { + export type FollowRequest = { + id: string + follower: User + followee: User + } +} diff --git a/packages/megalodon/src/misskey/entities/follower.ts b/packages/megalodon/src/misskey/entities/follower.ts new file mode 100644 index 000000000..70ef632e1 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/follower.ts @@ -0,0 +1,11 @@ +/// + +namespace MisskeyEntity { + export type Follower = { + id: string + createdAt: string + followeeId: string + followerId: string + follower: UserDetail + } +} diff --git a/packages/megalodon/src/misskey/entities/following.ts b/packages/megalodon/src/misskey/entities/following.ts new file mode 100644 index 000000000..927a91354 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/following.ts @@ -0,0 +1,11 @@ +/// + +namespace MisskeyEntity { + export type Following = { + id: string + createdAt: string + followeeId: string + followerId: string + followee: UserDetail + } +} diff --git a/packages/megalodon/src/misskey/entities/hashtag.ts b/packages/megalodon/src/misskey/entities/hashtag.ts new file mode 100644 index 000000000..6a3fe43ad --- /dev/null +++ b/packages/megalodon/src/misskey/entities/hashtag.ts @@ -0,0 +1,7 @@ +namespace MisskeyEntity { + export type Hashtag = { + tag: string + chart: Array + usersCount: number + } +} diff --git a/packages/megalodon/src/misskey/entities/list.ts b/packages/megalodon/src/misskey/entities/list.ts new file mode 100644 index 000000000..8167d2981 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/list.ts @@ -0,0 +1,8 @@ +namespace MisskeyEntity { + export type List = { + id: string + createdAt: string + name: string + userIds: Array + } +} diff --git a/packages/megalodon/src/misskey/entities/meta.ts b/packages/megalodon/src/misskey/entities/meta.ts new file mode 100644 index 000000000..2e99266ab --- /dev/null +++ b/packages/megalodon/src/misskey/entities/meta.ts @@ -0,0 +1,18 @@ +/// + +namespace MisskeyEntity { + export type Meta = { + maintainerName: string + maintainerEmail: string + name: string + version: string + uri: string + description: string + langs: Array + disableRegistration: boolean + disableLocalTimeline: boolean + bannerUrl: string + maxNoteTextLength: 300 + emojis: Array + } +} diff --git a/packages/megalodon/src/misskey/entities/mute.ts b/packages/megalodon/src/misskey/entities/mute.ts new file mode 100644 index 000000000..3cd7ae409 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/mute.ts @@ -0,0 +1,10 @@ +/// + +namespace MisskeyEntity { + export type Mute = { + id: string + createdAt: string + muteeId: string + mutee: UserDetail + } +} diff --git a/packages/megalodon/src/misskey/entities/note.ts b/packages/megalodon/src/misskey/entities/note.ts new file mode 100644 index 000000000..1d7207de1 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/note.ts @@ -0,0 +1,32 @@ +/// +/// +/// +/// + +namespace MisskeyEntity { + export type Note = { + id: string + createdAt: string + userId: string + user: User + text: string | null + cw: string | null + visibility: 'public' | 'home' | 'followers' | 'specified' + renoteCount: number + repliesCount: number + reactions: { [key: string]: number } + emojis: Array + fileIds: Array + files: Array + replyId: string | null + renoteId: string | null + uri?: string + reply?: Note + renote?: Note + viaMobile?: boolean + tags?: Array + poll?: Poll + mentions?: Array + myReaction?: string + } +} diff --git a/packages/megalodon/src/misskey/entities/notification.ts b/packages/megalodon/src/misskey/entities/notification.ts new file mode 100644 index 000000000..c331a1ec8 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/notification.ts @@ -0,0 +1,17 @@ +/// +/// + +namespace MisskeyEntity { + export type Notification = { + id: string + createdAt: string + // https://github.com/syuilo/misskey/blob/056942391aee135eb6c77aaa63f6ed5741d701a6/src/models/entities/notification.ts#L50-L62 + type: NotificationType + userId: string + user: User + note?: Note + reaction?: string + } + + export type NotificationType = string +} diff --git a/packages/megalodon/src/misskey/entities/poll.ts b/packages/megalodon/src/misskey/entities/poll.ts new file mode 100644 index 000000000..a3f1d971a --- /dev/null +++ b/packages/megalodon/src/misskey/entities/poll.ts @@ -0,0 +1,13 @@ +namespace MisskeyEntity { + export type Choice = { + text: string + votes: number + isVoted: boolean + } + + export type Poll = { + multiple: boolean + expiresAt: string + choices: Array + } +} diff --git a/packages/megalodon/src/misskey/entities/reaction.ts b/packages/megalodon/src/misskey/entities/reaction.ts new file mode 100644 index 000000000..0c8903529 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/reaction.ts @@ -0,0 +1,11 @@ +/// + +namespace MisskeyEntity { + export type Reaction = { + id: string + createdAt: string + user: User + url?: string + type: string + } +} diff --git a/packages/megalodon/src/misskey/entities/relation.ts b/packages/megalodon/src/misskey/entities/relation.ts new file mode 100644 index 000000000..07653b486 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/relation.ts @@ -0,0 +1,12 @@ +namespace MisskeyEntity { + export type Relation = { + id: string + isFollowing: boolean + hasPendingFollowRequestFromYou: boolean + hasPendingFollowRequestToYou: boolean + isFollowed: boolean + isBlocking: boolean + isBlocked: boolean + isMuted: boolean + } +} diff --git a/packages/megalodon/src/misskey/entities/session.ts b/packages/megalodon/src/misskey/entities/session.ts new file mode 100644 index 000000000..47fe9cf82 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/session.ts @@ -0,0 +1,6 @@ +namespace MisskeyEntity { + export type Session = { + token: string + url: string + } +} diff --git a/packages/megalodon/src/misskey/entities/stats.ts b/packages/megalodon/src/misskey/entities/stats.ts new file mode 100644 index 000000000..7f080efda --- /dev/null +++ b/packages/megalodon/src/misskey/entities/stats.ts @@ -0,0 +1,9 @@ +namespace MisskeyEntity { + export type Stats = { + notesCount: number + originalNotesCount: number + usersCount: number + originalUsersCount: number + instances: number + } +} diff --git a/packages/megalodon/src/misskey/entities/user.ts b/packages/megalodon/src/misskey/entities/user.ts new file mode 100644 index 000000000..4ea7bde7c --- /dev/null +++ b/packages/megalodon/src/misskey/entities/user.ts @@ -0,0 +1,13 @@ +/// + +namespace MisskeyEntity { + export type User = { + id: string + name: string + username: string + host: string | null + avatarUrl: string + avatarColor: string + emojis: Array + } +} diff --git a/packages/megalodon/src/misskey/entities/userDetail.ts b/packages/megalodon/src/misskey/entities/userDetail.ts new file mode 100644 index 000000000..1c6d6431d --- /dev/null +++ b/packages/megalodon/src/misskey/entities/userDetail.ts @@ -0,0 +1,34 @@ +/// +/// +/// + +namespace MisskeyEntity { + export type UserDetail = { + id: string + name: string + username: string + host: string | null + avatarUrl: string + avatarColor: string + isAdmin: boolean + isModerator: boolean + isBot: boolean + isCat: boolean + emojis: Array + createdAt: string + bannerUrl: string + bannerColor: string + isLocked: boolean + isSilenced: boolean + isSuspended: boolean + description: string + followersCount: number + followingCount: number + notesCount: number + avatarId: string + bannerId: string + pinnedNoteIds?: Array + pinnedNotes?: Array + fields: Array + } +} diff --git a/packages/megalodon/src/misskey/entities/userDetailMe.ts b/packages/megalodon/src/misskey/entities/userDetailMe.ts new file mode 100644 index 000000000..2cb680863 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/userDetailMe.ts @@ -0,0 +1,36 @@ +/// +/// +/// + +namespace MisskeyEntity { + export type UserDetailMe = { + id: string + name: string + username: string + host: string | null + avatarUrl: string + avatarColor: string + isAdmin: boolean + isModerator: boolean + isBot: boolean + isCat: boolean + emojis: Array + createdAt: string + bannerUrl: string + bannerColor: string + isLocked: boolean + isSilenced: boolean + isSuspended: boolean + description: string + followersCount: number + followingCount: number + notesCount: number + avatarId: string + bannerId: string + pinnedNoteIds?: Array + pinnedNotes?: Array + fields: Array + alwaysMarkNsfw: boolean + lang: string | null + } +} diff --git a/packages/megalodon/src/misskey/entities/userkey.ts b/packages/megalodon/src/misskey/entities/userkey.ts new file mode 100644 index 000000000..5b66e95b8 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/userkey.ts @@ -0,0 +1,8 @@ +/// + +namespace MisskeyEntity { + export type UserKey = { + accessToken: string + user: User + } +} diff --git a/packages/megalodon/src/misskey/entity.ts b/packages/megalodon/src/misskey/entity.ts new file mode 100644 index 000000000..d0bfd15aa --- /dev/null +++ b/packages/megalodon/src/misskey/entity.ts @@ -0,0 +1,28 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +export default MisskeyEntity diff --git a/packages/megalodon/src/misskey/notification.ts b/packages/megalodon/src/misskey/notification.ts new file mode 100644 index 000000000..9cf3dc58a --- /dev/null +++ b/packages/megalodon/src/misskey/notification.ts @@ -0,0 +1,16 @@ +import MisskeyEntity from './entity' + +namespace MisskeyNotificationType { + export const Follow: MisskeyEntity.NotificationType = 'follow' + export const Mention: MisskeyEntity.NotificationType = 'mention' + export const Reply: MisskeyEntity.NotificationType = 'reply' + export const Renote: MisskeyEntity.NotificationType = 'renote' + export const Quote: MisskeyEntity.NotificationType = 'quote' + export const Reaction: MisskeyEntity.NotificationType = 'favourite' + export const PollVote: MisskeyEntity.NotificationType = 'pollVote' + export const ReceiveFollowRequest: MisskeyEntity.NotificationType = 'receiveFollowRequest' + export const FollowRequestAccepted: MisskeyEntity.NotificationType = 'followRequestAccepted' + export const GroupInvited: MisskeyEntity.NotificationType = 'groupInvited' +} + +export default MisskeyNotificationType diff --git a/packages/megalodon/src/misskey/web_socket.ts b/packages/megalodon/src/misskey/web_socket.ts new file mode 100644 index 000000000..d3642864a --- /dev/null +++ b/packages/megalodon/src/misskey/web_socket.ts @@ -0,0 +1,414 @@ +import WS from 'ws' +import dayjs, { Dayjs } from 'dayjs' +import { v4 as uuid } from 'uuid' +import { EventEmitter } from 'events' +import { WebSocketInterface } from '../megalodon' +import proxyAgent, { ProxyConfig } from '../proxy_config' +import MisskeyAPI from './api_client' + +/** + * WebSocket + * Misskey is not support http streaming. It supports websocket instead of streaming. + * So this class connect to Misskey server with WebSocket. + */ +export default class WebSocket extends EventEmitter implements WebSocketInterface { + public url: string + public channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list' + public parser: any + public headers: { [key: string]: string } + public proxyConfig: ProxyConfig | false = false + public listId: string | null = null + private _converter: MisskeyAPI.Converter + private _accessToken: string + private _reconnectInterval: number + private _reconnectMaxAttempts: number + private _reconnectCurrentAttempts: number + private _connectionClosed: boolean + private _client: WS | null = null + private _channelID: string + private _pongReceivedTimestamp: Dayjs + private _heartbeatInterval: number = 60000 + private _pongWaiting: boolean = false + + /** + * @param url Full url of websocket: e.g. wss://misskey.io/streaming + * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. + * @param accessToken The access token. + * @param listId This parameter is required when you specify list as channel. + */ + constructor( + url: string, + channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', + accessToken: string, + listId: string | undefined, + userAgent: string, + proxyConfig: ProxyConfig | false = false, + converter: MisskeyAPI.Converter + ) { + super() + this.url = url + this.parser = new Parser() + this.channel = channel + this.headers = { + 'User-Agent': userAgent + } + if (listId === undefined) { + this.listId = null + } else { + this.listId = listId + } + this.proxyConfig = proxyConfig + this._accessToken = accessToken + this._reconnectInterval = 10000 + this._reconnectMaxAttempts = Infinity + this._reconnectCurrentAttempts = 0 + this._connectionClosed = false + this._channelID = uuid() + this._pongReceivedTimestamp = dayjs() + this._converter = converter + } + + /** + * Start websocket connection. + */ + public start() { + this._connectionClosed = false + this._resetRetryParams() + this._startWebSocketConnection() + } + + private baseUrlToHost(baseUrl: string): string { + return baseUrl.replace('https://', '') + } + + /** + * Reset connection and start new websocket connection. + */ + private _startWebSocketConnection() { + this._resetConnection() + this._setupParser() + this._client = this._connect() + this._bindSocket(this._client) + } + + /** + * Stop current connection. + */ + public stop() { + this._connectionClosed = true + this._resetConnection() + this._resetRetryParams() + } + + /** + * Clean up current connection, and listeners. + */ + private _resetConnection() { + if (this._client) { + this._client.close(1000) + this._client.removeAllListeners() + this._client = null + } + + if (this.parser) { + this.parser.removeAllListeners() + } + } + + /** + * Resets the parameters used in reconnect. + */ + private _resetRetryParams() { + this._reconnectCurrentAttempts = 0 + } + + /** + * Connect to the endpoint. + */ + private _connect(): WS { + let options: WS.ClientOptions = { + headers: this.headers + } + if (this.proxyConfig) { + options = Object.assign(options, { + agent: proxyAgent(this.proxyConfig) + }) + } + const cli: WS = new WS(`${this.url}?i=${this._accessToken}`, options) + return cli + } + + /** + * Connect specified channels in websocket. + */ + private _channel() { + if (!this._client) { + return + } + switch (this.channel) { + case 'conversation': + this._client.send( + JSON.stringify({ + type: 'connect', + body: { + channel: 'main', + id: this._channelID + } + }) + ) + break + case 'user': + this._client.send( + JSON.stringify({ + type: 'connect', + body: { + channel: 'main', + id: this._channelID + } + }) + ) + this._client.send( + JSON.stringify({ + type: 'connect', + body: { + channel: 'homeTimeline', + id: this._channelID + } + }) + ) + break + case 'list': + this._client.send( + JSON.stringify({ + type: 'connect', + body: { + channel: 'userList', + id: this._channelID, + params: { + listId: this.listId + } + } + }) + ) + break + default: + this._client.send( + JSON.stringify({ + type: 'connect', + body: { + channel: this.channel, + id: this._channelID + } + }) + ) + break + } + } + + /** + * Reconnects to the same endpoint. + */ + + private _reconnect() { + setTimeout(() => { + // Skip reconnect when client is connecting. + // https://github.com/websockets/ws/blob/7.2.1/lib/websocket.js#L365 + if (this._client && this._client.readyState === WS.CONNECTING) { + return + } + + if (this._reconnectCurrentAttempts < this._reconnectMaxAttempts) { + this._reconnectCurrentAttempts++ + this._clearBinding() + if (this._client) { + // In reconnect, we want to close the connection immediately, + // because recoonect is necessary when some problems occur. + this._client.terminate() + } + // Call connect methods + console.log('Reconnecting') + this._client = this._connect() + this._bindSocket(this._client) + } + }, this._reconnectInterval) + } + + /** + * Clear binding event for websocket client. + */ + private _clearBinding() { + if (this._client) { + this._client.removeAllListeners('close') + this._client.removeAllListeners('pong') + this._client.removeAllListeners('open') + this._client.removeAllListeners('message') + this._client.removeAllListeners('error') + } + } + + /** + * Bind event for web socket client. + * @param client A WebSocket instance. + */ + private _bindSocket(client: WS) { + client.on('close', (code: number, _reason: Buffer) => { + if (code === 1000) { + this.emit('close', {}) + } else { + console.log(`Closed connection with ${code}`) + if (!this._connectionClosed) { + this._reconnect() + } + } + }) + client.on('pong', () => { + this._pongWaiting = false + this.emit('pong', {}) + this._pongReceivedTimestamp = dayjs() + // It is required to anonymous function since get this scope in checkAlive. + setTimeout(() => this._checkAlive(this._pongReceivedTimestamp), this._heartbeatInterval) + }) + client.on('open', () => { + this.emit('connect', {}) + this._channel() + // Call first ping event. + setTimeout(() => { + client.ping('') + }, 10000) + }) + client.on('message', (data: WS.Data, isBinary: boolean) => { + this.parser.parse(data, isBinary, this._channelID) + }) + client.on('error', (err: Error) => { + this.emit('error', err) + }) + } + + /** + * Set up parser when receive message. + */ + private _setupParser() { + this.parser.on('update', (note: MisskeyAPI.Entity.Note) => { + this.emit('update', this._converter.note(note, this.baseUrlToHost(this.url))) + }) + this.parser.on('notification', (notification: MisskeyAPI.Entity.Notification) => { + this.emit('notification', this._converter.notification(notification, this.baseUrlToHost(this.url))) + }) + this.parser.on('conversation', (note: MisskeyAPI.Entity.Note) => { + this.emit('conversation', this._converter.noteToConversation(note, this.baseUrlToHost(this.url))) + }) + this.parser.on('error', (err: Error) => { + this.emit('parser-error', err) + }) + } + + /** + * Call ping and wait to pong. + */ + private _checkAlive(timestamp: Dayjs) { + const now: Dayjs = dayjs() + // Block multiple calling, if multiple pong event occur. + // It the duration is less than interval, through ping. + if (now.diff(timestamp) > this._heartbeatInterval - 1000 && !this._connectionClosed) { + // Skip ping when client is connecting. + // https://github.com/websockets/ws/blob/7.2.1/lib/websocket.js#L289 + if (this._client && this._client.readyState !== WS.CONNECTING) { + this._pongWaiting = true + this._client.ping('') + setTimeout(() => { + if (this._pongWaiting) { + this._pongWaiting = false + this._reconnect() + } + }, 10000) + } + } + } +} + +/** + * Parser + * This class provides parser for websocket message. + */ +export class Parser extends EventEmitter { + /** + * @param message Message body of websocket. + * @param channelID Parse only messages which has same channelID. + */ + public parse(data: WS.Data, isBinary: boolean, channelID: string) { + const message = isBinary ? data : data.toString() + if (typeof message !== 'string') { + this.emit('heartbeat', {}) + return + } + + if (message === '') { + this.emit('heartbeat', {}) + return + } + + let obj: { + type: string + body: { + id: string + type: string + body: any + } + } + let body: { + id: string + type: string + body: any + } + + try { + obj = JSON.parse(message) + if (obj.type !== 'channel') { + return + } + if (!obj.body) { + return + } + body = obj.body + if (body.id !== channelID) { + return + } + } catch (err) { + this.emit('error', new Error(`Error parsing websocket reply: ${message}, error message: ${err}`)) + return + } + + switch (body.type) { + case 'note': + this.emit('update', body.body as MisskeyAPI.Entity.Note) + break + case 'notification': + this.emit('notification', body.body as MisskeyAPI.Entity.Notification) + break + case 'mention': { + const note = body.body as MisskeyAPI.Entity.Note + if (note.visibility === 'specified') { + this.emit('conversation', note) + } + break + } + // When renote and followed event, the same notification will be received. + case 'renote': + case 'followed': + case 'follow': + case 'unfollow': + case 'receiveFollowRequest': + case 'meUpdated': + case 'readAllNotifications': + case 'readAllUnreadSpecifiedNotes': + case 'readAllAntennas': + case 'readAllUnreadMentions': + case 'unreadNotification': + // Ignore these events + break + default: + this.emit('error', new Error(`Unknown event has received: ${JSON.stringify(body)}`)) + break + } + } +} diff --git a/packages/megalodon/src/notification.ts b/packages/megalodon/src/notification.ts new file mode 100644 index 000000000..9ea3898c6 --- /dev/null +++ b/packages/megalodon/src/notification.ts @@ -0,0 +1,15 @@ +import Entity from './entity' + +namespace NotificationType { + export const Follow: Entity.NotificationType = 'follow' + export const Favourite: Entity.NotificationType = 'favourite' + export const Reblog: Entity.NotificationType = 'reblog' + export const Mention: Entity.NotificationType = 'mention' + export const EmojiReaction: Entity.NotificationType = 'emoji_reaction' + export const FollowRequest: Entity.NotificationType = 'follow_request' + export const Status: Entity.NotificationType = 'status' + export const PollVote: Entity.NotificationType = 'poll_vote' + export const PollExpired: Entity.NotificationType = 'poll_expired' +} + +export default NotificationType diff --git a/packages/megalodon/src/oauth.ts b/packages/megalodon/src/oauth.ts new file mode 100644 index 000000000..3c3ceb9de --- /dev/null +++ b/packages/megalodon/src/oauth.ts @@ -0,0 +1,109 @@ +/** + * OAuth + * Response data when oauth request. + **/ +namespace OAuth { + export type AppDataFromServer = { + id: string + name: string + website: string | null + redirect_uri: string + client_id: string + client_secret: string + } + + export type TokenDataFromServer = { + access_token: string + token_type: string + scope: string + created_at: number + expires_in: number | null + refresh_token: string | null + } + + export class AppData { + public url: string | null + public session_token: string | null + constructor( + public id: string, + public name: string, + public website: string | null, + public redirect_uri: string, + public client_id: string, + public client_secret: string + ) { + this.url = null + this.session_token = null + } + + /** + * Serialize raw application data from server + * @param raw from server + */ + static from(raw: AppDataFromServer) { + return new this(raw.id, raw.name, raw.website, raw.redirect_uri, raw.client_id, raw.client_secret) + } + + get redirectUri() { + return this.redirect_uri + } + get clientId() { + return this.client_id + } + get clientSecret() { + return this.client_secret + } + } + + export class TokenData { + public _scope: string + constructor( + public access_token: string, + public token_type: string, + scope: string, + public created_at: number, + public expires_in: number | null = null, + public refresh_token: string | null = null + ) { + this._scope = scope + } + + /** + * Serialize raw token data from server + * @param raw from server + */ + static from(raw: TokenDataFromServer) { + return new this(raw.access_token, raw.token_type, raw.scope, raw.created_at, raw.expires_in, raw.refresh_token) + } + + /** + * OAuth Aceess Token + */ + get accessToken() { + return this.access_token + } + get tokenType() { + return this.token_type + } + get scope() { + return this._scope + } + /** + * Application ID + */ + get createdAt() { + return this.created_at + } + get expiresIn() { + return this.expires_in + } + /** + * OAuth Refresh Token + */ + get refreshToken() { + return this.refresh_token + } + } +} + +export default OAuth diff --git a/packages/megalodon/src/parser.ts b/packages/megalodon/src/parser.ts new file mode 100644 index 000000000..67abff797 --- /dev/null +++ b/packages/megalodon/src/parser.ts @@ -0,0 +1,86 @@ +import { EventEmitter } from 'events' +import Entity from './entity' + +/** + * Parser + * Parse response data in streaming. + **/ +export class Parser extends EventEmitter { + private message: string + + constructor() { + super() + this.message = '' + } + + public parse(chunk: string) { + // skip heartbeats + if (chunk === ':thump\n') { + this.emit('heartbeat', {}) + return + } + + this.message += chunk + chunk = this.message + + const size: number = chunk.length + let start: number = 0 + let offset: number = 0 + let curr: string | undefined + let next: string | undefined + + while (offset < size) { + curr = chunk[offset] + next = chunk[offset + 1] + + if (curr === '\n' && next === '\n') { + const piece: string = chunk.slice(start, offset) + + offset += 2 + start = offset + + if (!piece.length) continue // empty object + + const root: Array = piece.split('\n') + + // should never happen, as long as mastodon doesn't change API messages + if (root.length !== 2) continue + + // remove event and data markers + const event: string = root[0].substr(7) + const data: string = root[1].substr(6) + + let jsonObj = {} + try { + jsonObj = JSON.parse(data) + } catch (err) { + // delete event does not have json object + if (event !== 'delete') { + this.emit('error', new Error(`Error parsing API reply: '${piece}', error message: '${err}'`)) + continue + } + } + switch (event) { + case 'update': + this.emit('update', jsonObj as Entity.Status) + break + case 'notification': + this.emit('notification', jsonObj as Entity.Notification) + break + case 'conversation': + this.emit('conversation', jsonObj as Entity.Conversation) + break + case 'delete': + // When delete, data is an ID of the deleted status + this.emit('delete', data) + break + default: + this.emit('error', new Error(`Unknown event has received: ${event}`)) + continue + } + } + offset++ + } + this.message = chunk.slice(start, size) + } +} diff --git a/packages/megalodon/src/proxy_config.ts b/packages/megalodon/src/proxy_config.ts new file mode 100644 index 000000000..7419f664e --- /dev/null +++ b/packages/megalodon/src/proxy_config.ts @@ -0,0 +1,83 @@ +import { HttpsProxyAgent, HttpsProxyAgentOptions } from 'https-proxy-agent' +import { SocksProxyAgent, SocksProxyAgentOptions } from 'socks-proxy-agent' + +export type ProxyConfig = { + host: string + port: number + auth?: { + username: string + password: string + } + protocol: 'http' | 'https' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' | 'socks' +} + +class ProxyProtocolError extends Error {} + +const proxyAgent = (proxyConfig: ProxyConfig): HttpsProxyAgent | SocksProxyAgent => { + switch (proxyConfig.protocol) { + case 'http': { + let options: HttpsProxyAgentOptions = { + host: proxyConfig.host, + port: proxyConfig.port, + secureProxy: false + } + if (proxyConfig.auth) { + options = Object.assign(options, { + auth: `${proxyConfig.auth.username}:${proxyConfig.auth.password}` + }) + } + const httpsAgent = new HttpsProxyAgent(options) + return httpsAgent + } + case 'https': { + let options: HttpsProxyAgentOptions = { + host: proxyConfig.host, + port: proxyConfig.port, + secureProxy: true + } + if (proxyConfig.auth) { + options = Object.assign(options, { + auth: `${proxyConfig.auth.username}:${proxyConfig.auth.password}` + }) + } + const httpsAgent = new HttpsProxyAgent(options) + return httpsAgent + } + case 'socks4': + case 'socks4a': { + let options: SocksProxyAgentOptions = { + type: 4, + hostname: proxyConfig.host, + port: proxyConfig.port + } + if (proxyConfig.auth) { + options = Object.assign(options, { + userId: proxyConfig.auth.username, + password: proxyConfig.auth.password + }) + } + const socksAgent = new SocksProxyAgent(options) + return socksAgent + } + case 'socks5': + case 'socks5h': + case 'socks': { + let options: SocksProxyAgentOptions = { + type: 5, + hostname: proxyConfig.host, + port: proxyConfig.port + } + if (proxyConfig.auth) { + options = Object.assign(options, { + userId: proxyConfig.auth.username, + password: proxyConfig.auth.password + }) + } + const socksAgent = new SocksProxyAgent(options) + return socksAgent + } + default: + throw new ProxyProtocolError('protocol is not accepted') + } +} +export default proxyAgent diff --git a/packages/megalodon/src/response.ts b/packages/megalodon/src/response.ts new file mode 100644 index 000000000..e27596203 --- /dev/null +++ b/packages/megalodon/src/response.ts @@ -0,0 +1,8 @@ +type Response = { + data: T + status: number + statusText: string + headers: any +} + +export default Response diff --git a/packages/megalodon/test/integration/megalodon.spec.ts b/packages/megalodon/test/integration/megalodon.spec.ts new file mode 100644 index 000000000..896453550 --- /dev/null +++ b/packages/megalodon/test/integration/megalodon.spec.ts @@ -0,0 +1,27 @@ +import { detector } from '../../src/index' + +describe('detector', () => { + describe('mastodon', () => { + const url = 'https://fedibird.com' + it('should be mastodon', async () => { + const mastodon = await detector(url) + expect(mastodon).toEqual('mastodon') + }) + }) + + describe('pleroma', () => { + const url = 'https://pleroma.soykaf.com' + it('should be pleroma', async () => { + const pleroma = await detector(url) + expect(pleroma).toEqual('pleroma') + }) + }) + + describe('misskey', () => { + const url = 'https://misskey.io' + it('should be misskey', async () => { + const misskey = await detector(url) + expect(misskey).toEqual('misskey') + }) + }) +}) diff --git a/packages/megalodon/test/integration/misskey.spec.ts b/packages/megalodon/test/integration/misskey.spec.ts new file mode 100644 index 000000000..754f6cc28 --- /dev/null +++ b/packages/megalodon/test/integration/misskey.spec.ts @@ -0,0 +1,204 @@ +import MisskeyEntity from '@/misskey/entity' +import MisskeyNotificationType from '@/misskey/notification' +import Misskey from '@/misskey' +import MegalodonNotificationType from '@/notification' +import axios, { AxiosResponse } from 'axios' + +jest.mock('axios') + +const user: MisskeyEntity.User = { + id: '1', + name: 'test_user', + username: 'TestUser', + host: 'misskey.io', + avatarUrl: 'https://example.com/icon.png', + avatarColor: '#000000', + emojis: [] +} + +const note: MisskeyEntity.Note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: 'hogehoge', + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null +} + +const follow: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Follow +} + +const mention: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Mention, + note: note +} + +const reply: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Reply, + note: note +} + +const renote: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Renote, + note: note +} + +const quote: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Quote, + note: note +} + +const reaction: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.Reaction, + note: note, + reaction: '♥' +} + +const pollVote: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.PollVote, + note: note +} + +const receiveFollowRequest: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.ReceiveFollowRequest +} + +const followRequestAccepted: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.FollowRequestAccepted +} + +const groupInvited: MisskeyEntity.Notification = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: user.id, + user: user, + type: MisskeyNotificationType.GroupInvited +} + +;(axios.CancelToken.source as any).mockImplementation(() => { + return { + token: { + throwIfRequested: () => {}, + promise: { + then: () => {}, + catch: () => {} + } + } + } +}) + +describe('getNotifications', () => { + const client = new Misskey('http://localhost', 'sample token') + const cases: Array<{ event: MisskeyEntity.Notification; expected: Entity.NotificationType; title: string }> = [ + { + event: follow, + expected: MegalodonNotificationType.Follow, + title: 'follow' + }, + { + event: mention, + expected: MegalodonNotificationType.Mention, + title: 'mention' + }, + { + event: reply, + expected: MegalodonNotificationType.Mention, + title: 'reply' + }, + { + event: renote, + expected: MegalodonNotificationType.Reblog, + title: 'renote' + }, + { + event: quote, + expected: MegalodonNotificationType.Reblog, + title: 'quote' + }, + { + event: reaction, + expected: MegalodonNotificationType.EmojiReaction, + title: 'reaction' + }, + { + event: pollVote, + expected: MegalodonNotificationType.PollVote, + title: 'pollVote' + }, + { + event: receiveFollowRequest, + expected: MegalodonNotificationType.FollowRequest, + title: 'receiveFollowRequest' + }, + { + event: followRequestAccepted, + expected: MegalodonNotificationType.Follow, + title: 'followRequestAccepted' + }, + { + event: groupInvited, + expected: MisskeyNotificationType.GroupInvited, + title: 'groupInvited' + } + ] + cases.forEach(c => { + it(`should be ${c.title} event`, async () => { + const mockResponse: AxiosResponse> = { + data: [c.event], + status: 200, + statusText: '200OK', + headers: {}, + config: {} + } + ;(axios.post as any).mockResolvedValue(mockResponse) + const res = await client.getNotifications() + expect(res.data[0].type).toEqual(c.expected) + }) + }) +}) diff --git a/packages/megalodon/test/unit/misskey/api_client.spec.ts b/packages/megalodon/test/unit/misskey/api_client.spec.ts new file mode 100644 index 000000000..acaac39ca --- /dev/null +++ b/packages/megalodon/test/unit/misskey/api_client.spec.ts @@ -0,0 +1,233 @@ +import MisskeyAPI from '@/misskey/api_client' +import MegalodonEntity from '@/entity' +import MisskeyEntity from '@/misskey/entity' +import MegalodonNotificationType from '@/notification' +import MisskeyNotificationType from '@/misskey/notification' + +const user: MisskeyEntity.User = { + id: '1', + name: 'test_user', + username: 'TestUser', + host: 'misskey.io', + avatarUrl: 'https://example.com/icon.png', + avatarColor: '#000000', + emojis: [] +} + +const converter: MisskeyAPI.Converter = new MisskeyAPI.Converter("https://example.com") + +describe('api_client', () => { + describe('notification', () => { + describe('encode', () => { + it('megalodon notification type should be encoded to misskey notification type', () => { + const cases: Array<{ src: MegalodonEntity.NotificationType; dist: MisskeyEntity.NotificationType }> = [ + { + src: MegalodonNotificationType.Follow, + dist: MisskeyNotificationType.Follow + }, + { + src: MegalodonNotificationType.Mention, + dist: MisskeyNotificationType.Reply + }, + { + src: MegalodonNotificationType.Favourite, + dist: MisskeyNotificationType.Reaction + }, + { + src: MegalodonNotificationType.EmojiReaction, + dist: MisskeyNotificationType.Reaction + }, + { + src: MegalodonNotificationType.Reblog, + dist: MisskeyNotificationType.Renote + }, + { + src: MegalodonNotificationType.PollVote, + dist: MisskeyNotificationType.PollVote + }, + { + src: MegalodonNotificationType.FollowRequest, + dist: MisskeyNotificationType.ReceiveFollowRequest + } + ] + cases.forEach(c => { + expect(converter.encodeNotificationType(c.src)).toEqual(c.dist) + }) + }) + }) + describe('decode', () => { + it('misskey notification type should be decoded to megalodon notification type', () => { + const cases: Array<{ src: MisskeyEntity.NotificationType; dist: MegalodonEntity.NotificationType }> = [ + { + src: MisskeyNotificationType.Follow, + dist: MegalodonNotificationType.Follow + }, + { + src: MisskeyNotificationType.Mention, + dist: MegalodonNotificationType.Mention + }, + { + src: MisskeyNotificationType.Reply, + dist: MegalodonNotificationType.Mention + }, + { + src: MisskeyNotificationType.Renote, + dist: MegalodonNotificationType.Reblog + }, + { + src: MisskeyNotificationType.Quote, + dist: MegalodonNotificationType.Reblog + }, + { + src: MisskeyNotificationType.Reaction, + dist: MegalodonNotificationType.EmojiReaction + }, + { + src: MisskeyNotificationType.PollVote, + dist: MegalodonNotificationType.PollVote + }, + { + src: MisskeyNotificationType.ReceiveFollowRequest, + dist: MegalodonNotificationType.FollowRequest + }, + { + src: MisskeyNotificationType.FollowRequestAccepted, + dist: MegalodonNotificationType.Follow + } + ] + cases.forEach(c => { + expect(converter.decodeNotificationType(c.src)).toEqual(c.dist) + }) + }) + }) + }) + describe('reactions', () => { + it('should be mapped', () => { + const misskeyReactions = [ + { + id: '1', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + }, + { + id: '2', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + }, + { + id: '3', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '☺' + }, + { + id: '4', + createdAt: '2020-04-21T13:04:13.968Z', + user: { + id: '81u70uwsja', + name: 'h3poteto', + username: 'h3poteto', + host: null, + avatarUrl: 'https://s3.arkjp.net/misskey/thumbnail-63807d97-20ca-40ba-9493-179aa48065c1.png', + avatarColor: 'rgb(146,189,195)', + emojis: [] + }, + type: '❤' + } + ] + + const reactions = converter.reactions(misskeyReactions) + expect(reactions).toEqual([ + { + count: 3, + me: false, + name: '❤' + }, + { + count: 1, + me: false, + name: '☺' + } + ]) + }) + }) + + describe('status', () => { + describe('plain content', () => { + it('should be exported plain content and html content', () => { + const plainContent = 'hoge\nfuga\nfuga' + const content = 'hoge
fuga
fuga' + const note: MisskeyEntity.Note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: plainContent, + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null + } + const megalodonStatus = converter.note(note, user.host || 'misskey.io') + expect(megalodonStatus.plain_content).toEqual(plainContent) + expect(megalodonStatus.content).toEqual(content) + }) + it('html tags should be escaped', () => { + const plainContent = '

hoge\nfuga\nfuga

' + const content = '<p>hoge
fuga
fuga<p>' + const note: MisskeyEntity.Note = { + id: '1', + createdAt: '2021-02-01T01:49:29', + userId: '1', + user: user, + text: plainContent, + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + emojis: [], + fileIds: [], + files: [], + replyId: null, + renoteId: null + } + const megalodonStatus = converter.note(note, user.host || 'misskey.io') + expect(megalodonStatus.plain_content).toEqual(plainContent) + expect(megalodonStatus.content).toEqual(content) + }) + }) + }) +}) diff --git a/packages/megalodon/test/unit/parser.spec.ts b/packages/megalodon/test/unit/parser.spec.ts new file mode 100644 index 000000000..585210773 --- /dev/null +++ b/packages/megalodon/test/unit/parser.spec.ts @@ -0,0 +1,152 @@ +import { Parser } from '@/parser' +import Entity from '@/entity' + +const account: Entity.Account = { + id: '1', + username: 'h3poteto', + acct: 'h3poteto@pleroma.io', + display_name: 'h3poteto', + locked: false, + created_at: '2019-03-26T21:30:32', + followers_count: 10, + following_count: 10, + statuses_count: 100, + note: 'engineer', + url: 'https://pleroma.io', + avatar: '', + avatar_static: '', + header: '', + header_static: '', + emojis: [], + moved: null, + fields: [], + bot: false +} + +const status: Entity.Status = { + id: '1', + uri: 'http://example.com', + url: 'http://example.com', + account: account, + in_reply_to_id: null, + in_reply_to_account_id: null, + reblog: null, + content: 'hoge', + plain_content: 'hoge', + created_at: '2019-03-26T21:40:32', + emojis: [], + replies_count: 0, + reblogs_count: 0, + favourites_count: 0, + reblogged: null, + favourited: null, + muted: null, + sensitive: false, + spoiler_text: '', + visibility: 'public', + media_attachments: [], + mentions: [], + tags: [], + card: null, + poll: null, + application: { + name: 'Web' + } as Entity.Application, + language: null, + pinned: null, + emoji_reactions: [], + bookmarked: false, + quote: null +} + +const notification: Entity.Notification = { + id: '1', + account: account, + status: status, + type: 'favourite', + created_at: '2019-04-01T17:01:32' +} + +const conversation: Entity.Conversation = { + id: '1', + accounts: [account], + last_status: status, + unread: true +} + +describe('Parser', () => { + let parser: Parser + + beforeEach(() => { + parser = new Parser() + }) + + describe('parse', () => { + describe('message is heartbeat', () => { + const message: string = ':thump\n' + it('should be called', () => { + const spy = jest.fn() + parser.on('heartbeat', spy) + parser.parse(message) + expect(spy).toHaveBeenLastCalledWith({}) + }) + }) + + describe('message is not json', () => { + describe('event is delete', () => { + const message = `event: delete\ndata: 12asdf34\n\n` + it('should be called', () => { + const spy = jest.fn() + parser.once('delete', spy) + parser.parse(message) + expect(spy).toHaveBeenCalledWith('12asdf34') + }) + }) + + describe('event is not delete', () => { + const message = `event: event\ndata: 12asdf34\n\n` + it('should be error', () => { + const error = jest.fn() + const deleted = jest.fn() + parser.once('error', error) + parser.once('delete', deleted) + parser.parse(message) + expect(error).toHaveBeenCalled() + expect(deleted).not.toHaveBeenCalled() + }) + }) + }) + + describe('message is json', () => { + describe('event is update', () => { + const message = `event: update\ndata: ${JSON.stringify(status)}\n\n` + it('should be called', () => { + const spy = jest.fn() + parser.once('update', spy) + parser.parse(message) + expect(spy).toHaveBeenCalledWith(status) + }) + }) + + describe('event is notification', () => { + const message = `event: notification\ndata: ${JSON.stringify(notification)}\n\n` + it('should be called', () => { + const spy = jest.fn() + parser.once('notification', spy) + parser.parse(message) + expect(spy).toHaveBeenCalledWith(notification) + }) + }) + + describe('event is conversation', () => { + const message = `event: conversation\ndata: ${JSON.stringify(conversation)}\n\n` + it('should be called', () => { + const spy = jest.fn() + parser.once('conversation', spy) + parser.parse(message) + expect(spy).toHaveBeenCalledWith(conversation) + }) + }) + }) + }) +}) diff --git a/packages/megalodon/tsconfig.json b/packages/megalodon/tsconfig.json new file mode 100644 index 000000000..45efcd8a2 --- /dev/null +++ b/packages/megalodon/tsconfig.json @@ -0,0 +1,64 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["es6", "dom"], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./lib", /* Redirect output structure to the directory. */ + "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* Enable strict null checks. */ + "strictFunctionTypes": true, /* Enable strict checking of function types. */ + "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + "noUnusedLocals": false, /* Report errors on unused locals. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + "paths": { + "@*": ["src*"], + "~*": ["./*"] + }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": ["./src", "./test"], + "exclude": ["node_modules", "example"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53a12bae8..a27cb847f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,6 +36,9 @@ importers: '@types/gulp-rename': specifier: 2.0.1 version: 2.0.1 + '@types/node': + specifier: 18.11.18 + version: 18.11.18 chalk: specifier: 4.1.2 version: 4.1.2 @@ -88,8 +91,8 @@ importers: specifier: 5.2.0 version: 5.2.0 '@calckey/megalodon': - specifier: 5.2.0 - version: 5.2.0 + specifier: workspace:* + version: link:../megalodon '@discordapp/twemoji': specifier: 14.1.2 version: 14.1.2 @@ -903,7 +906,7 @@ importers: version: 1.8.0 vite: specifier: 4.3.9 - version: 4.3.9(sass@1.62.1) + version: 4.3.9(@types/node@18.11.18)(sass@1.62.1) vite-plugin-compression: specifier: ^0.5.1 version: 0.5.1(vite@4.3.9) @@ -923,6 +926,121 @@ importers: specifier: 4.1.0 version: 4.1.0(vue@3.3.4) + packages/megalodon: + dependencies: + '@types/oauth': + specifier: ^0.9.0 + version: 0.9.1 + '@types/ws': + specifier: ^8.5.4 + version: 8.5.4 + async-lock: + specifier: 1.4.0 + version: 1.4.0 + axios: + specifier: 1.2.2 + version: 1.2.2 + dayjs: + specifier: ^1.11.7 + version: 1.11.8 + form-data: + specifier: ^4.0.0 + version: 4.0.0 + https-proxy-agent: + specifier: ^5.0.1 + version: 5.0.1 + oauth: + specifier: ^0.10.0 + version: 0.10.0 + object-assign-deep: + specifier: ^0.4.0 + version: 0.4.0 + parse-link-header: + specifier: ^2.0.0 + version: 2.0.0 + socks-proxy-agent: + specifier: ^7.0.0 + version: 7.0.0 + typescript: + specifier: 4.9.4 + version: 4.9.4 + uuid: + specifier: ^9.0.0 + version: 9.0.0 + ws: + specifier: 8.12.0 + version: 8.12.0 + devDependencies: + '@types/async-lock': + specifier: 1.4.0 + version: 1.4.0 + '@types/core-js': + specifier: ^2.5.0 + version: 2.5.0 + '@types/form-data': + specifier: ^2.5.0 + version: 2.5.0 + '@types/jest': + specifier: ^29.4.0 + version: 29.4.0 + '@types/object-assign-deep': + specifier: ^0.4.0 + version: 0.4.0 + '@types/parse-link-header': + specifier: ^2.0.0 + version: 2.0.0 + '@types/uuid': + specifier: ^9.0.0 + version: 9.0.0 + '@typescript-eslint/eslint-plugin': + specifier: ^5.49.0 + version: 5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.42.0)(typescript@4.9.4) + '@typescript-eslint/parser': + specifier: ^5.49.0 + version: 5.49.0(eslint@8.42.0)(typescript@4.9.4) + eslint: + specifier: ^8.32.0 + version: 8.42.0 + eslint-config-prettier: + specifier: ^8.6.0 + version: 8.6.0(eslint@8.42.0) + eslint-config-standard: + specifier: ^16.0.3 + version: 16.0.3(eslint-plugin-import@2.27.5)(eslint-plugin-node@11.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.42.0) + eslint-plugin-node: + specifier: ^11.0.0 + version: 11.0.0(eslint@8.42.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.42.0)(prettier@2.8.8) + eslint-plugin-promise: + specifier: ^6.1.1 + version: 6.1.1(eslint@8.42.0) + eslint-plugin-standard: + specifier: ^5.0.0 + version: 5.0.0(eslint@8.42.0) + jest: + specifier: ^29.4.0 + version: 29.4.0(@types/node@18.11.18) + jest-worker: + specifier: ^29.4.0 + version: 29.4.0 + lodash: + specifier: ^4.17.14 + version: 4.17.21 + prettier: + specifier: ^2.8.3 + version: 2.8.8 + ts-jest: + specifier: ^29.0.5 + version: 29.0.5(@babel/core@7.22.5)(jest@29.4.0)(typescript@4.9.4) + typedoc: + specifier: ^0.23.24 + version: 0.23.24(typescript@4.9.4) + packages/sw: devDependencies: '@swc/cli': @@ -1173,6 +1291,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.5): + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.5): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: @@ -1394,30 +1522,6 @@ packages: '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) dev: false - /@calckey/megalodon@5.2.0: - resolution: {integrity: sha512-9MEjzKJPyd7o5bHGGlNq4oE1tMt22GUJ8o8tZXcXSpXlrSDb2rSwumirM1KXUWTW8G6NGi1leCM59gOBGLko3w==} - engines: {node: '>=15.0.0'} - dependencies: - '@types/oauth': 0.9.1 - '@types/ws': 8.5.4 - axios: 1.2.2 - dayjs: 1.11.8 - form-data: 4.0.0 - https-proxy-agent: 5.0.1 - oauth: 0.10.0 - object-assign-deep: 0.4.0 - parse-link-header: 2.0.0 - socks-proxy-agent: 7.0.0 - typescript: 4.9.4 - uuid: 9.0.0 - ws: 8.12.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: false - /@colors/colors@1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -1901,6 +2005,18 @@ packages: slash: 3.0.0 dev: true + /@jest/console@29.6.0: + resolution: {integrity: sha512-anb6L1yg7uPQpytNVA5skRaXy3BmrsU8icRhTVNbWdjYWDDfy8M1Kq5HIVRpYoABdbpqsc5Dr+jtu4+qWRQBiQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + chalk: 4.1.2 + jest-message-util: 29.6.0 + jest-util: 29.6.0 + slash: 3.0.0 + dev: true + /@jest/core@27.5.1(ts-node@10.4.0): resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1946,6 +2062,48 @@ packages: - utf-8-validate dev: true + /@jest/core@29.6.0: + resolution: {integrity: sha512-5dbMHfY/5R9m8NbgmB3JlxQqooZ/ooPSOiwEQZZ+HODwJTbIu37seVcZNBK29aMdXtjvTRB3f6LCvkKq+r8uQA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.6.0 + '@jest/reporters': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/transform': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.5.0 + jest-config: 29.6.0(@types/node@20.3.1) + jest-haste-map: 29.6.0 + jest-message-util: 29.6.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.0 + jest-resolve-dependencies: 29.6.0 + jest-runner: 29.6.0 + jest-runtime: 29.6.0 + jest-snapshot: 29.6.0 + jest-util: 29.6.0 + jest-validate: 29.6.0 + jest-watcher: 29.6.0 + micromatch: 4.0.5 + pretty-format: 29.6.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true + /@jest/environment@27.5.1: resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1956,6 +2114,33 @@ packages: jest-mock: 27.5.1 dev: true + /@jest/environment@29.6.0: + resolution: {integrity: sha512-bUZLYUxYlUIsslBbxII0fq0kr1+friI3Gty+cRLmocGB1jdcAHs7FS8QdCDqedE8q4DZE1g/AJHH6OJZBLGGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + jest-mock: 29.6.0 + dev: true + + /@jest/expect-utils@29.6.0: + resolution: {integrity: sha512-LLSQQN7oypMSETKoPWpsWYVKJd9LQWmSDDAc4hUQ4JocVC7LAMy9R3ZMhlnLwbcFvQORZnZR7HM893Px6cJhvA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + dev: true + + /@jest/expect@29.6.0: + resolution: {integrity: sha512-a7pISPW28Q3c0/pLwz4mQ6tbAI+hc8/0CJp9ix6e9U4dQ6TiHQX82CT5DV5BMWaw8bFH4E6zsfZxXdn6Ka23Bw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.6.0 + jest-snapshot: 29.6.0 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/fake-timers@27.5.1: resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1968,6 +2153,18 @@ packages: jest-util: 27.5.1 dev: true + /@jest/fake-timers@29.6.0: + resolution: {integrity: sha512-nuCU46AsZoskthWSDS2Aj6LARgyNcp5Fjx2qxsO/fPl1Wp1CJ+dBDqs0OkEcJK8FBeV/MbjH5efe79M2sHcV+A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 20.3.1 + jest-message-util: 29.6.0 + jest-mock: 29.6.0 + jest-util: 29.6.0 + dev: true + /@jest/globals@27.5.1: resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1977,6 +2174,18 @@ packages: expect: 27.5.1 dev: true + /@jest/globals@29.6.0: + resolution: {integrity: sha512-IQQ3hZ2D/hwEwXSMv5GbfhzdH0nTQR3KPYxnuW6gYWbd6+7/zgMz7Okn6EgBbNtJNONq03k5EKA6HqGyzRbpeg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.0 + '@jest/expect': 29.6.0 + '@jest/types': 29.6.0 + jest-mock: 29.6.0 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/reporters@27.5.1: resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2015,6 +2224,43 @@ packages: - supports-color dev: true + /@jest/reporters@29.6.0: + resolution: {integrity: sha512-dWEq4HI0VvHcAD6XTtyBKKARLytyyWPIy1SvGOcU91106MfvHPdxZgupFwVHd8TFpZPpA3SebYjtwS5BUS76Rw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/transform': 29.6.0 + '@jest/types': 29.6.0 + '@jridgewell/trace-mapping': 0.3.18 + '@types/node': 20.3.1 + chalk: 4.1.2 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + jest-message-util: 29.6.0 + jest-util: 29.6.0 + jest-worker: 29.6.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.1.0 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/schemas@29.4.3: resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2022,6 +2268,13 @@ packages: '@sinclair/typebox': 0.25.24 dev: true + /@jest/schemas@29.6.0: + resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + /@jest/source-map@27.5.1: resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2031,6 +2284,15 @@ packages: source-map: 0.6.1 dev: true + /@jest/source-map@29.6.0: + resolution: {integrity: sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + /@jest/test-result@27.5.1: resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2041,6 +2303,16 @@ packages: collect-v8-coverage: 1.0.1 dev: true + /@jest/test-result@29.6.0: + resolution: {integrity: sha512-9qLb7xITeyWhM4yatn2muqfomuoCTOhv0QV9i7XiIyYi3QLfnvPv5NeJp5u0PZeutAOROMLKakOkmoAisOr3YQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.6.0 + '@jest/types': 29.6.0 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.1 + dev: true + /@jest/test-sequencer@27.5.1: resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2053,6 +2325,16 @@ packages: - supports-color dev: true + /@jest/test-sequencer@29.6.0: + resolution: {integrity: sha512-HYCS3LKRQotKWj2mnA3AN13PPevYZu8MJKm12lzYojpJNnn6kI/3PWmr1At/e3tUu+FHQDiOyaDVuR4EV3ezBw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.6.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.0 + slash: 3.0.0 + dev: true + /@jest/transform@27.5.1: resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2076,6 +2358,29 @@ packages: - supports-color dev: true + /@jest/transform@29.6.0: + resolution: {integrity: sha512-bhP/KxPo3e322FJ0nKAcb6WVK76ZYyQd1lWygJzoSqP8SYMSLdxHqP4wnPTI4WvbB8PKPDV30y5y7Tya4RHOBA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.22.5 + '@jest/types': 29.6.0 + '@jridgewell/trace-mapping': 0.3.18 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.0 + jest-regex-util: 29.4.3 + jest-util: 29.6.0 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + /@jest/types@27.5.1: resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2087,6 +2392,18 @@ packages: chalk: 4.1.2 dev: true + /@jest/types@29.6.0: + resolution: {integrity: sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.0 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.3.1 + '@types/yargs': 17.0.24 + chalk: 4.1.2 + dev: true + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -2618,6 +2935,10 @@ packages: resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==} dev: true + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + /@sindresorhus/is@4.6.0: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -2632,6 +2953,18 @@ packages: dependencies: type-detect: 4.0.8 + /@sinonjs/commons@3.0.0: + resolution: {integrity: sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.0 + dev: true + /@sinonjs/fake-timers@8.1.0: resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} dependencies: @@ -3054,6 +3387,10 @@ packages: resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} dev: true + /@types/async-lock@1.4.0: + resolution: {integrity: sha512-2+rYSaWrpdbQG3SA0LmMT6YxWLrI81AqpMlSkw3QtFc2HGDufkweQSn30Eiev7x9LL0oyFrBqk1PXOnB9IEgKg==} + dev: true + /@types/babel__core@7.20.1: resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} dependencies: @@ -3140,6 +3477,10 @@ packages: '@types/keygrip': 1.0.2 '@types/node': 20.3.1 + /@types/core-js@2.5.0: + resolution: {integrity: sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==} + dev: true + /@types/disposable-email-domains@1.0.4: resolution: {integrity: sha512-AmKPD8vBZzvey/jeg+YAIH/xJE3D6edOXz+YUooSCcHesGzFyzke83kj1j4d0LUR9nkSHIRklUVdcAMleuWLpg==} dev: false @@ -3203,6 +3544,13 @@ packages: '@types/node': 20.3.1 dev: true + /@types/form-data@2.5.0: + resolution: {integrity: sha512-23/wYiuckYYtFpL+4RPWiWmRQH2BjFuqCUi2+N3amB1a1Drv+i/byTrGvlLwRVLFNAZbwpbQ7JvTK+VCAPMbcg==} + deprecated: This is a stub types definition. form-data provides its own type definitions, so you do not need this installed. + dependencies: + form-data: 4.0.0 + dev: true + /@types/formidable@2.0.6: resolution: {integrity: sha512-L4HcrA05IgQyNYJj6kItuIkXrInJvsXTPC5B1i64FggWKKqSL+4hgt7asiSNva75AoLQjq29oPxFfU4GAQ6Z2w==} dependencies: @@ -3301,6 +3649,13 @@ packages: pretty-format: 27.5.1 dev: true + /@types/jest@29.4.0: + resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==} + dependencies: + expect: 29.6.0 + pretty-format: 29.5.0 + dev: true + /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true @@ -3317,6 +3672,10 @@ packages: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} dev: true + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + /@types/jsonld@1.5.8: resolution: {integrity: sha512-4l5t/jDnJpqZ+i7CLTTgPcT5BYXnAnwJupb07aAokPufCV0SjDHcwctUkSTuhIuSU9yHok+WOOngIGCtpL96gw==} dev: true @@ -3541,6 +3900,10 @@ packages: dependencies: '@types/node': 20.3.1 + /@types/object-assign-deep@0.4.0: + resolution: {integrity: sha512-3D0F3rHRNDc8cQSXNzwF1jBrJi28Mdrhc10ZLlqbJWDPYRWTTWB9Tc8JoKrgBvLKioXoPoHT6Uzf3s2F7akCUg==} + dev: true + /@types/offscreencanvas@2019.3.0: resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==} dev: false @@ -3549,6 +3912,10 @@ packages: resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==} dev: false + /@types/parse-link-header@2.0.0: + resolution: {integrity: sha512-KbqcQLdRaawDOfXnwqr6nvhe1MV+Uv/Ww+ViSx7Ujgw9X5qCgObLP52B1ZSJqZD8FK1y/4o+bJQTUrZOynegcg==} + dev: true + /@types/picomatch@2.3.0: resolution: {integrity: sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==} dev: true @@ -3705,6 +4072,10 @@ packages: resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} dev: true + /@types/uuid@9.0.0: + resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} + dev: true + /@types/vinyl-fs@3.0.2: resolution: {integrity: sha512-ctNcmmzbMIKooXjRkyyUCOu2Z4AyqibL+RhXoF3pb7K7j+ezItnakmpm31LymkYHSIM5ey0tjIFzTvFOTSBCGw==} dependencies: @@ -3755,6 +4126,12 @@ packages: '@types/yargs-parser': 21.0.0 dev: true + /@types/yargs@17.0.24: + resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==} + dependencies: + '@types/yargs-parser': 21.0.0 + dev: true + /@types/yauzl@2.10.0: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true @@ -3763,6 +4140,135 @@ packages: dev: true optional: true + /@typescript-eslint/eslint-plugin@5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.42.0)(typescript@4.9.4): + resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@typescript-eslint/scope-manager': 5.49.0 + '@typescript-eslint/type-utils': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@typescript-eslint/utils': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.42.0 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + regexpp: 3.2.0 + semver: 7.5.1 + tsutils: 3.21.0(typescript@4.9.4) + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.49.0(eslint@8.42.0)(typescript@4.9.4): + resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.49.0 + '@typescript-eslint/types': 5.49.0 + '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.42.0 + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.49.0: + resolution: {integrity: sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.49.0 + '@typescript-eslint/visitor-keys': 5.49.0 + dev: true + + /@typescript-eslint/type-utils@5.49.0(eslint@8.42.0)(typescript@4.9.4): + resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) + '@typescript-eslint/utils': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.42.0 + tsutils: 3.21.0(typescript@4.9.4) + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.49.0: + resolution: {integrity: sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.49.0(typescript@4.9.4): + resolution: {integrity: sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.49.0 + '@typescript-eslint/visitor-keys': 5.49.0 + debug: 4.3.4(supports-color@8.1.1) + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.1 + tsutils: 3.21.0(typescript@4.9.4) + typescript: 4.9.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.49.0(eslint@8.42.0)(typescript@4.9.4): + resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.0 + '@typescript-eslint/scope-manager': 5.49.0 + '@typescript-eslint/types': 5.49.0 + '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) + eslint: 8.42.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0(eslint@8.42.0) + semver: 7.5.1 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.49.0: + resolution: {integrity: sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.49.0 + eslint-visitor-keys: 3.4.1 + dev: true + /@vitejs/plugin-vue@4.2.3(vite@4.3.9)(vue@3.3.4): resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3770,7 +4276,7 @@ packages: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 4.3.9(sass@1.62.1) + vite: 4.3.9(@types/node@18.11.18)(sass@1.62.1) vue: 3.3.4 dev: true @@ -4393,6 +4899,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + /array-each@1.0.1: resolution: {integrity: sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==} engines: {node: '>=0.10.0'} @@ -4403,6 +4916,17 @@ packages: engines: {node: '>=0.10.0'} dev: true + /array-includes@3.1.6: + resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + get-intrinsic: 1.2.1 + is-string: 1.0.7 + dev: true + /array-initial@1.1.0: resolution: {integrity: sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==} engines: {node: '>=0.10.0'} @@ -4442,6 +4966,26 @@ packages: engines: {node: '>=0.10.0'} dev: true + /array.prototype.flat@1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + es-shim-unscopables: 1.0.0 + dev: true + + /array.prototype.flatmap@1.3.1: + resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + es-shim-unscopables: 1.0.0 + dev: true + /arrgv@1.0.2: resolution: {integrity: sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==} engines: {node: '>=8.0.0'} @@ -4501,6 +5045,10 @@ packages: stream-exhaust: 1.0.2 dev: true + /async-lock@1.4.0: + resolution: {integrity: sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==} + dev: false + /async-settle@1.0.0: resolution: {integrity: sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==} engines: {node: '>= 0.10'} @@ -4618,7 +5166,6 @@ packages: /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - dev: false /aws-sdk@2.1277.0: resolution: {integrity: sha512-cEZ0rg0j3STtLX6rba5tHMrV/KrhXKLtSleleF2IdTFzUjqRvxI54Pqc51w2D7tgAPUgEhMB4Q/ruKPqB8w+2Q==} @@ -4715,6 +5262,24 @@ packages: - supports-color dev: true + /babel-jest@29.6.0(@babel/core@7.22.5): + resolution: {integrity: sha512-Jj8Bq2yKsk11XLk06Nm8SdvYkAcecH+GuhxB8DnK5SncjHnJ88TQjSnGgE7jpajpnSvz9DZ6X8hXrDkD/6/TPQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.22.5 + '@jest/transform': 29.6.0 + '@types/babel__core': 7.20.1 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.5.0(@babel/core@7.22.5) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} @@ -4738,6 +5303,16 @@ packages: '@types/babel__traverse': 7.20.1 dev: true + /babel-plugin-jest-hoist@29.5.0: + resolution: {integrity: sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.22.5 + '@babel/types': 7.22.5 + '@types/babel__core': 7.20.1 + '@types/babel__traverse': 7.20.1 + dev: true + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.22.5): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: @@ -4769,6 +5344,17 @@ packages: babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) dev: true + /babel-preset-jest@29.5.0(@babel/core@7.22.5): + resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.5 + babel-plugin-jest-hoist: 29.5.0 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + dev: true + /babel-walk@3.0.0-canary-5: resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} engines: {node: '>= 10.0.0'} @@ -5967,6 +6553,10 @@ packages: /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + /convert-to-spaces@2.0.1: resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6534,6 +7124,13 @@ packages: resolution: {integrity: sha512-LBQvhRw7mznQTPoyZbsmYeNOZt1pN5aCsx4BAU/3siVFuiM9f2oyKzUaB8v1jbxFjE3aYqYiMo63kAL4pHgfWQ==} dev: false + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -6674,6 +7271,11 @@ packages: /electron-to-chromium@1.4.442: resolution: {integrity: sha512-RkrZF//Ya+0aJq2NM3OdisNh5ZodZq1rdXOS96G8DdDgpDKqKE81yTbbQ3F/4CKm1JBPsGu1Lp/akkna2xO06Q==} + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + /emittery@0.8.1: resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==} engines: {node: '>=10'} @@ -6765,10 +7367,74 @@ packages: is-arrayish: 0.2.1 dev: true + /es-abstract@1.21.2: + resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.10 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.9 + dev: true + /es-module-lexer@1.3.0: resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==} dev: true + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + /es5-ext@0.10.62: resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} engines: {node: '>=0.10'} @@ -6883,6 +7549,29 @@ packages: optionalDependencies: source-map: 0.6.1 + /eslint-config-prettier@8.6.0(eslint@8.42.0): + resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.42.0 + dev: true + + /eslint-config-standard@16.0.3(eslint-plugin-import@2.27.5)(eslint-plugin-node@11.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0): + resolution: {integrity: sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==} + peerDependencies: + eslint: ^7.12.1 + eslint-plugin-import: ^2.22.1 + eslint-plugin-node: ^11.1.0 + eslint-plugin-promise: ^4.2.1 || ^5.0.0 + dependencies: + eslint: 8.42.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.42.0) + eslint-plugin-node: 11.0.0(eslint@8.42.0) + eslint-plugin-promise: 6.1.1(eslint@8.42.0) + dev: true + /eslint-formatter-pretty@4.1.0: resolution: {integrity: sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==} engines: {node: '>=10'} @@ -6897,6 +7586,139 @@ packages: supports-hyperlinks: 2.3.0 dev: true + /eslint-import-resolver-node@0.3.7: + resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} + dependencies: + debug: 3.2.7(supports-color@8.1.1) + is-core-module: 2.12.1 + resolve: 1.22.2 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + debug: 3.2.7(supports-color@8.1.1) + eslint: 8.42.0 + eslint-import-resolver-node: 0.3.7 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es@3.0.1(eslint@8.42.0): + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.42.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.42.0): + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + array-includes: 3.1.6 + array.prototype.flat: 1.3.1 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7(supports-color@8.1.1) + doctrine: 2.1.0 + eslint: 8.42.0 + eslint-import-resolver-node: 0.3.7 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0) + has: 1.0.3 + is-core-module: 2.12.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.6 + resolve: 1.22.2 + semver: 6.3.0 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-node@11.0.0(eslint@8.42.0): + resolution: {integrity: sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.42.0 + eslint-plugin-es: 3.0.1(eslint@8.42.0) + eslint-utils: 2.1.0 + ignore: 5.2.4 + minimatch: 3.1.2 + resolve: 1.22.2 + semver: 6.3.0 + dev: true + + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.42.0)(prettier@2.8.8): + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.42.0 + eslint-config-prettier: 8.6.0(eslint@8.42.0) + prettier: 2.8.8 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-promise@6.1.1(eslint@8.42.0): + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.42.0 + dev: true + + /eslint-plugin-standard@5.0.0(eslint@8.42.0): + resolution: {integrity: sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg==} + deprecated: 'standard 16.0.0 and eslint-config-standard 16.0.0 no longer require the eslint-plugin-standard package. You can remove it from your dependencies with ''npm rm eslint-plugin-standard''. More info here: https://github.com/standard/standard/issues/1316' + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 8.42.0 + dev: true + /eslint-rule-docs@1.1.235: resolution: {integrity: sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==} dev: true @@ -6916,10 +7738,31 @@ packages: esrecurse: 4.3.0 estraverse: 5.3.0 + /eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-utils@3.0.0(eslint@8.42.0): + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.42.0 + eslint-visitor-keys: 2.1.0 + dev: true + /eslint-visitor-keys@1.3.0: resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} engines: {node: '>=4'} - dev: false + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true /eslint-visitor-keys@3.4.1: resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} @@ -7171,6 +8014,18 @@ packages: jest-message-util: 27.5.1 dev: true + /expect@29.6.0: + resolution: {integrity: sha512-AV+HaBtnDJ2YEUhPPo25HyUHBLaetM+y/Dq6pEC8VPQyt1dK+k8MfGkMy46djy2bddcqESc1kl4/K1uLWSfk9g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.6.0 + '@types/node': 20.3.1 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.6.0 + jest-message-util: 29.6.0 + jest-util: 29.6.0 + dev: true + /exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} dev: false @@ -7549,7 +8404,6 @@ packages: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 - dev: false /for-in@1.0.2: resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} @@ -7602,7 +8456,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: false /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -7731,6 +8584,20 @@ packages: /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + /gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'} @@ -7832,6 +8699,14 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + /get-value@2.0.6: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} engines: {node: '>=0.10.0'} @@ -7993,6 +8868,13 @@ packages: dependencies: type-fest: 0.20.2 + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -8032,7 +8914,6 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.1 - dev: false /got@11.8.5: resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==} @@ -8191,6 +9072,10 @@ packages: ansi-regex: 2.1.1 dev: true + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + /has-flag@1.0.0: resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} engines: {node: '>=0.10.0'} @@ -8614,6 +9499,15 @@ packages: executioner: 2.0.1 dev: true + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + /interpret@1.4.0: resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} engines: {node: '>= 0.10'} @@ -8719,6 +9613,14 @@ packages: has-tostringtag: 1.0.0 dev: false + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.10 + dev: true + /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true @@ -8727,19 +9629,32 @@ packages: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} dev: false + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + /is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - dev: false /is-ci@3.0.1: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} @@ -8767,6 +9682,13 @@ packages: kind-of: 6.0.3 dev: true + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-descriptor@0.1.6: resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} engines: {node: '>=0.10.0'} @@ -8879,6 +9801,18 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-number@3.0.0: resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} engines: {node: '>=0.10.0'} @@ -8954,6 +9888,12 @@ packages: is-unc-path: 1.0.0 dev: true + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + /is-stream@1.1.0: resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} engines: {node: '>=0.10.0'} @@ -8969,6 +9909,13 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-svg@2.1.0: resolution: {integrity: sha512-Ya1giYJUkcL/94quj0+XGcmts6cETPBW1MiFz1ReJrnDJ680F52qpAEGAEGU0nq96FRGIGPx6Yo1CyPXcOoyGw==} engines: {node: '>=0.10.0'} @@ -8983,6 +9930,13 @@ packages: fast-xml-parser: 3.21.1 dev: false + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + /is-typed-array@1.1.10: resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} engines: {node: '>= 0.4'} @@ -8992,7 +9946,6 @@ packages: for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 - dev: false /is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} @@ -9027,6 +9980,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + /is-whitespace@0.3.0: resolution: {integrity: sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==} engines: {node: '>=0.10.0'} @@ -9143,6 +10102,14 @@ packages: throat: 6.0.2 dev: true + /jest-changed-files@29.5.0: + resolution: {integrity: sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + p-limit: 3.1.0 + dev: true + /jest-circus@27.5.1: resolution: {integrity: sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9170,6 +10137,34 @@ packages: - supports-color dev: true + /jest-circus@29.6.0: + resolution: {integrity: sha512-LtG45qEKhse2Ws5zNR4DnZATReLGQXzBZGZnJ0DU37p6d4wDhu41vvczCQ3Ou+llR6CRYDBshsubV7H4jZvIkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.0 + '@jest/expect': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + is-generator-fn: 2.1.0 + jest-each: 29.6.0 + jest-matcher-utils: 29.6.0 + jest-message-util: 29.6.0 + jest-runtime: 29.6.0 + jest-snapshot: 29.6.0 + jest-util: 29.6.0 + p-limit: 3.1.0 + pretty-format: 29.6.0 + pure-rand: 6.0.2 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - supports-color + dev: true + /jest-cli@27.5.1(ts-node@10.4.0): resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9200,6 +10195,34 @@ packages: - utf-8-validate dev: true + /jest-cli@29.6.0(@types/node@18.11.18): + resolution: {integrity: sha512-WvZIaanK/abkw6s01924DQ2QLwM5Q4Y4iPbSDb9Zg6smyXGqqcPQ7ft9X8D7B0jICz312eSzM6UlQNxuZJBrMw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/types': 29.6.0 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.1.0 + jest-config: 29.6.0(@types/node@18.11.18) + jest-util: 29.6.0 + jest-validate: 29.6.0 + prompts: 2.4.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /jest-config@27.5.1(ts-node@10.4.0): resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9241,6 +10264,84 @@ packages: - utf-8-validate dev: true + /jest-config@29.6.0(@types/node@18.11.18): + resolution: {integrity: sha512-fKA4jM91PDqWVkMpb1FVKxIuhg3hC6hgaen57cr1rRZkR96dCatvJZsk3ik7/GNu9ERj9wgAspOmyvkFoGsZhA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.22.5 + '@jest/test-sequencer': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 18.11.18 + babel-jest: 29.6.0(@babel/core@7.22.5) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.6.0 + jest-environment-node: 29.6.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.0 + jest-runner: 29.6.0 + jest-util: 29.6.0 + jest-validate: 29.6.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.6.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config@29.6.0(@types/node@20.3.1): + resolution: {integrity: sha512-fKA4jM91PDqWVkMpb1FVKxIuhg3hC6hgaen57cr1rRZkR96dCatvJZsk3ik7/GNu9ERj9wgAspOmyvkFoGsZhA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.22.5 + '@jest/test-sequencer': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + babel-jest: 29.6.0(@babel/core@7.22.5) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.6.0 + jest-environment-node: 29.6.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.0 + jest-runner: 29.6.0 + jest-util: 29.6.0 + jest-validate: 29.6.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.6.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /jest-diff@27.5.1: resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9261,6 +10362,16 @@ packages: pretty-format: 29.5.0 dev: true + /jest-diff@29.6.0: + resolution: {integrity: sha512-ZRm7cd2m9YyZ0N3iMyuo1iUiprxQ/MFpYWXzEEj7hjzL3WnDffKW8192XBDcrAI8j7hnrM1wed3bL/oEnYF/8w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.4.3 + jest-get-type: 29.4.3 + pretty-format: 29.6.0 + dev: true + /jest-docblock@27.5.1: resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9268,6 +10379,13 @@ packages: detect-newline: 3.1.0 dev: true + /jest-docblock@29.4.3: + resolution: {integrity: sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + /jest-each@27.5.1: resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9279,6 +10397,17 @@ packages: pretty-format: 27.5.1 dev: true + /jest-each@29.6.0: + resolution: {integrity: sha512-d0Jem4RBAlFUyV6JSXPSHVUpNo5RleSj+iJEy1G3+ZCrzHDjWs/1jUfrbnJKHdJdAx5BCEce/Ju379WqHhQk4w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + chalk: 4.1.2 + jest-get-type: 29.4.3 + jest-util: 29.6.0 + pretty-format: 29.6.0 + dev: true + /jest-environment-jsdom@27.5.1: resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9309,6 +10438,18 @@ packages: jest-util: 27.5.1 dev: true + /jest-environment-node@29.6.0: + resolution: {integrity: sha512-BOf5Q2/nFCdBOnyBM5c5/6DbdQYgc+0gyUQ8l8qhUAB8O7pM+4QJXIXJsRZJaxd5SHV6y5VArTVhOfogoqcP8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.0 + '@jest/fake-timers': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + jest-mock: 29.6.0 + jest-util: 29.6.0 + dev: true + /jest-fetch-mock@3.0.3: resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} dependencies: @@ -9348,6 +10489,25 @@ packages: fsevents: 2.3.2 dev: true + /jest-haste-map@29.6.0: + resolution: {integrity: sha512-dY1DKufptj7hcJSuhpqlYPGcnN3XjlOy/g0jinpRTMsbb40ivZHiuIPzeminOZkrek8C+oDxC54ILGO3vMLojg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + '@types/graceful-fs': 4.1.6 + '@types/node': 20.3.1 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.4.3 + jest-util: 29.6.0 + jest-worker: 29.6.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /jest-jasmine2@27.5.1: resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9381,6 +10541,14 @@ packages: pretty-format: 27.5.1 dev: true + /jest-leak-detector@29.6.0: + resolution: {integrity: sha512-JdV6EZOPxHR1gd6ccxjNowuROkT2jtGU5G/g58RcJX1xe5mrtLj0g6/ZkyMoXF4cs+tTkHMFX6pcIrB1QPQwCw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.4.3 + pretty-format: 29.6.0 + dev: true + /jest-matcher-utils@27.5.1: resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9391,6 +10559,16 @@ packages: pretty-format: 27.5.1 dev: true + /jest-matcher-utils@29.6.0: + resolution: {integrity: sha512-oSlqfGN+sbkB2Q5um/zL7z80w84FEAcLKzXBZIPyRk2F2Srg1ubhrHVKW68JCvb2+xKzAeGw35b+6gciS24PHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.6.0 + jest-get-type: 29.4.3 + pretty-format: 29.6.0 + dev: true + /jest-message-util@27.5.1: resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9406,6 +10584,21 @@ packages: stack-utils: 2.0.6 dev: true + /jest-message-util@29.6.0: + resolution: {integrity: sha512-mkCp56cETbpoNtsaeWVy6SKzk228mMi9FPHSObaRIhbR2Ujw9PqjW/yqVHD2tN1bHbC8ol6h3UEo7dOPmIYwIA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.22.5 + '@jest/types': 29.6.0 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 29.6.0 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true + /jest-mock@27.5.1: resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9414,6 +10607,15 @@ packages: '@types/node': 20.3.1 dev: true + /jest-mock@29.6.0: + resolution: {integrity: sha512-2Pb7R2w24Q0aUVn+2/vdRDL6CqGqpheDZy7zrXav8FotOpSGw/4bS2hyVoKHMEx4xzOn6EyCAGwc5czWxXeN7w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + jest-util: 29.6.0 + dev: true + /jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -9426,11 +10628,28 @@ packages: jest-resolve: 27.5.1 dev: true + /jest-pnp-resolver@1.2.3(jest-resolve@29.6.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.6.0 + dev: true + /jest-regex-util@27.5.1: resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dev: true + /jest-regex-util@29.4.3: + resolution: {integrity: sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + /jest-resolve-dependencies@27.5.1: resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9442,6 +10661,16 @@ packages: - supports-color dev: true + /jest-resolve-dependencies@29.6.0: + resolution: {integrity: sha512-eOfPog9K3hJdJk/3i6O6bQhXS+3uXhMDkLJGX+xmMPp7T1d/zdcFofbDnHgNoEkhD/mSimC5IagLEP7lpLLu/A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.4.3 + jest-snapshot: 29.6.0 + transitivePeerDependencies: + - supports-color + dev: true + /jest-resolve@27.5.1: resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9458,6 +10687,21 @@ packages: slash: 3.0.0 dev: true + /jest-resolve@29.6.0: + resolution: {integrity: sha512-+hrpY4LzAONoZA/rvB6rnZLkOSA6UgJLpdCWrOZNSgGxWMumzRLu7dLUSCabAHzoHIDQ9qXfr3th1zYNJ0E8sQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.6.0) + jest-util: 29.6.0 + jest-validate: 29.6.0 + resolve: 1.22.2 + resolve.exports: 2.0.2 + slash: 3.0.0 + dev: true + /jest-runner@27.5.1: resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9490,6 +10734,35 @@ packages: - utf-8-validate dev: true + /jest-runner@29.6.0: + resolution: {integrity: sha512-4fZuGV2lOxS2BiqEG9/AI8E6O+jo+QZjMVcgi1x5E6aDql0Gd/EFIbUQ0pSS09y8cya1vJB/qC2xsE468jqtSg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.6.0 + '@jest/environment': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/transform': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.4.3 + jest-environment-node: 29.6.0 + jest-haste-map: 29.6.0 + jest-leak-detector: 29.6.0 + jest-message-util: 29.6.0 + jest-resolve: 29.6.0 + jest-runtime: 29.6.0 + jest-util: 29.6.0 + jest-watcher: 29.6.0 + jest-worker: 29.6.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + /jest-runtime@27.5.1: resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9520,6 +10793,36 @@ packages: - supports-color dev: true + /jest-runtime@29.6.0: + resolution: {integrity: sha512-5FavYo3EeXLHIvnJf+r7Cj0buePAbe4mzRB9oeVxDS0uVmouSBjWeGgyRjZkw7ArxOoZI8gO6f8SGMJ2HFlwwg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.6.0 + '@jest/fake-timers': 29.6.0 + '@jest/globals': 29.6.0 + '@jest/source-map': 29.6.0 + '@jest/test-result': 29.6.0 + '@jest/transform': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.6.0 + jest-message-util: 29.6.0 + jest-mock: 29.6.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.0 + jest-snapshot: 29.6.0 + jest-util: 29.6.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /jest-serializer@27.5.1: resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9558,6 +10861,35 @@ packages: - supports-color dev: true + /jest-snapshot@29.6.0: + resolution: {integrity: sha512-H3kUE9NwWDEDoutcOSS921IqdlkdjgnMdj1oMyxAHNflscdLc9dB8OudZHV6kj4OHJxbMxL8CdI5DlwYrs4wQg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.22.5 + '@babel/generator': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.5) + '@babel/types': 7.22.5 + '@jest/expect-utils': 29.6.0 + '@jest/transform': 29.6.0 + '@jest/types': 29.6.0 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + chalk: 4.1.2 + expect: 29.6.0 + graceful-fs: 4.2.11 + jest-diff: 29.6.0 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.6.0 + jest-message-util: 29.6.0 + jest-util: 29.6.0 + natural-compare: 1.4.0 + pretty-format: 29.6.0 + semver: 7.5.3 + transitivePeerDependencies: + - supports-color + dev: true + /jest-util@27.5.1: resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9570,6 +10902,18 @@ packages: picomatch: 2.3.1 dev: true + /jest-util@29.6.0: + resolution: {integrity: sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + chalk: 4.1.2 + ci-info: 3.8.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: true + /jest-validate@27.5.1: resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9582,6 +10926,18 @@ packages: pretty-format: 27.5.1 dev: true + /jest-validate@29.6.0: + resolution: {integrity: sha512-MLTrAJsb1+W7svbeZ+A7pAnyXMaQrjvPDKCy7OlfsfB6TMVc69v7WjUWfiR6r3snULFWZASiKgvNVDuATta1dg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.0 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.4.3 + leven: 3.1.0 + pretty-format: 29.6.0 + dev: true + /jest-watcher@27.5.1: resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9595,6 +10951,20 @@ packages: string-length: 4.0.2 dev: true + /jest-watcher@29.6.0: + resolution: {integrity: sha512-LdsQqFNX60mRdRRe+zsELnYRH1yX6KL+ukbh+u6WSQeTheZZe1TlLJNKRQiZ7e0VbvMkywmMWL/KV35noOJCcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.6.0 + '@jest/types': 29.6.0 + '@types/node': 20.3.1 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.6.0 + string-length: 4.0.2 + dev: true + /jest-websocket-mock@2.2.1(mock-socket@9.0.8): resolution: {integrity: sha512-fhsGLXrPfs06PhHoxqOSA9yZ6Rb4qYrf4Wcm7/nfRzjlrf1gIeuhYUkzMRjjE0TMQ37SwkmeLanwrZY4ZaNp8g==} peerDependencies: @@ -9613,6 +10983,26 @@ packages: supports-color: 8.1.1 dev: true + /jest-worker@29.4.0: + resolution: {integrity: sha512-dICMQ+Q4W0QVMsaQzWlA1FVQhKNz7QcDCOGtbk1GCAd0Lai+wdkQvfmQwL4MjGumineh1xz+6M5oMj3rfWS02A==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.3.1 + jest-util: 29.6.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest-worker@29.6.0: + resolution: {integrity: sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.3.1 + jest-util: 29.6.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + /jest@27.4.5(ts-node@10.4.0): resolution: {integrity: sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9634,6 +11024,26 @@ packages: - utf-8-validate dev: true + /jest@29.4.0(@types/node@18.11.18): + resolution: {integrity: sha512-Zfd4UzNxPkSoHRBkg225rBjQNa6pVqbh20MGniAzwaOzYLd+pQUcAwH+WPxSXxKFs+QWYfPYIq9hIVSmdVQmPA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.6.0 + '@jest/types': 29.6.0 + import-local: 3.1.0 + jest-cli: 29.6.0(@types/node@18.11.18) + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + /jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true @@ -9856,11 +11266,22 @@ packages: webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) dev: true + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: @@ -10516,6 +11937,10 @@ packages: engines: {node: '>=12'} dev: false + /lunr@2.3.9: + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + dev: true + /luxon@3.3.0: resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==} engines: {node: '>=12'} @@ -10610,6 +12035,12 @@ packages: object-visit: 1.0.1 dev: true + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + dev: true + /matchdep@2.0.0: resolution: {integrity: sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==} engines: {node: '>= 0.10.0'} @@ -11055,6 +12486,10 @@ packages: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} dev: false + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -11439,6 +12874,15 @@ packages: make-iterator: 1.0.1 dev: true + /object.values@1.1.6: + resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + /oblivious-set@1.1.1: resolution: {integrity: sha512-Oh+8fK09mgGmAshFdH6hSVco6KZmd1tTwNFWj35OvzdmJTMZtAkbn05zar2iG3v6sDs1JLEtOiBGNb6BHwkb2w==} dev: true @@ -12284,6 +13728,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + /prettier-plugin-vue@1.1.6: resolution: {integrity: sha512-trQ/oY+6hSsGe2zPIFThXMIM0TbxMEbk2VOrKjwHWuSz7OEo0rnumbz9a47OxVPCaAnGY9vZG8qDTiTmk9bq0A==} dependencies: @@ -12325,6 +13776,15 @@ packages: react-is: 18.2.0 dev: true + /pretty-format@29.6.0: + resolution: {integrity: sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.0 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + /pretty-hrtime@1.0.3: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} engines: {node: '>= 0.8'} @@ -12554,6 +14014,10 @@ packages: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} + /pure-rand@6.0.2: + resolution: {integrity: sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==} + dev: true + /pureimage@0.3.15: resolution: {integrity: sha512-QpQYEV8nxVb84en7D0nKXwG0bdmwmlsSg9QnqxpEOExvUXdbmo6Lw/UoxSXD9z+ryvWDkgWqZsIM3iPCAh4dXg==} engines: {node: '>=0.8'} @@ -12893,6 +14357,20 @@ packages: safe-regex: 1.1.0 dev: true + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + /remove-bom-buffer@3.0.0: resolution: {integrity: sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==} engines: {node: '>=0.10.0'} @@ -13062,6 +14540,11 @@ packages: engines: {node: '>=10'} dev: true + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + /resolve@1.19.0: resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} dependencies: @@ -13185,6 +14668,14 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + /safe-regex@1.1.0: resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} dependencies: @@ -13406,6 +14897,14 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + /shiki@0.12.1: + resolution: {integrity: sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==} + dependencies: + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + dev: true + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -13575,6 +15074,13 @@ packages: urix: 0.1.0 dev: true + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -13801,6 +15307,31 @@ packages: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.2 + dev: true + /string_decoder@0.10.31: resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} dev: false @@ -14411,6 +15942,40 @@ packages: yargs-parser: 20.2.9 dev: true + /ts-jest@29.0.5(@babel/core@7.22.5)(jest@29.4.0)(typescript@4.9.4): + resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + '@babel/core': 7.22.5 + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.4.0(@types/node@18.11.18) + jest-util: 29.6.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.5.1 + typescript: 4.9.4 + yargs-parser: 21.1.1 + dev: true + /ts-loader@9.4.3(typescript@5.1.3)(webpack@5.85.1): resolution: {integrity: sha512-n3hBnm6ozJYzwiwt5YRiJZkzktftRpMiBApHaJPoWLA+qetQBAXkHqCLM6nwSdRDimqVtA5ocIkcTRLMTt7yzA==} engines: {node: '>=12.0.0'} @@ -14500,6 +16065,15 @@ packages: plimit-lit: 1.5.0 dev: true + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + /tsconfig-paths@4.2.0: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} @@ -14523,6 +16097,10 @@ packages: read-pkg-up: 7.0.1 dev: true + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + /tslib@2.6.0: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} @@ -14531,6 +16109,16 @@ packages: engines: {node: '>=0.6.x'} dev: false + /tsutils@3.21.0(typescript@4.9.4): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.9.4 + dev: true + /tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} dependencies: @@ -14601,6 +16189,14 @@ packages: /type@2.7.2: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + dev: true + /typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} dependencies: @@ -14609,6 +16205,20 @@ packages: /typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + /typedoc@0.23.24(typescript@4.9.4): + resolution: {integrity: sha512-bfmy8lNQh+WrPYcJbtjQ6JEEsVl/ce1ZIXyXhyW+a1vFrjO39t6J8sL/d6FfAGrJTc7McCXgk9AanYBSNvLdIA==} + engines: {node: '>= 14.14'} + hasBin: true + peerDependencies: + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x + dependencies: + lunr: 2.3.9 + marked: 4.3.0 + minimatch: 5.1.6 + shiki: 0.12.1 + typescript: 4.9.4 + dev: true + /typeorm@0.3.11(ioredis@5.3.2)(pg@8.11.0)(ts-node@10.9.1): resolution: {integrity: sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==} engines: {node: '>= 12.9.0'} @@ -14712,6 +16322,15 @@ packages: hasBin: true dev: false + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + /unc-path-regex@0.1.2: resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} engines: {node: '>=0.10.0'} @@ -14924,6 +16543,15 @@ packages: source-map: 0.7.4 dev: true + /v8-to-istanbul@9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + dev: true + /v8flags@3.2.0: resolution: {integrity: sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==} engines: {node: '>= 0.10'} @@ -15031,12 +16659,12 @@ packages: chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 10.1.0 - vite: 4.3.9(sass@1.62.1) + vite: 4.3.9(@types/node@18.11.18)(sass@1.62.1) transitivePeerDependencies: - supports-color dev: true - /vite@4.3.9(sass@1.62.1): + /vite@4.3.9(@types/node@18.11.18)(sass@1.62.1): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -15061,6 +16689,7 @@ packages: terser: optional: true dependencies: + '@types/node': 18.11.18 esbuild: 0.17.19 postcss: 8.4.24 rollup: 3.23.1 @@ -15073,6 +16702,14 @@ packages: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} engines: {node: '>=0.10.0'} + /vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + dev: true + + /vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + dev: true + /vue-isyourpasswordsafe@2.0.0: resolution: {integrity: sha512-j3ORj18R9AgFiP2UOM35KuZbSeJAUiwCSyeRBFN3CGFYTJSKsxqU9qGqOHOz6OhLAYKMTin8JOmqugAbF9O+Bg==} dependencies: @@ -15367,6 +17004,16 @@ packages: engines: {node: '>=0.6.0'} dev: true + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + /which-module@1.0.0: resolution: {integrity: sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==} dev: true @@ -15385,7 +17032,6 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 is-typed-array: 1.1.10 - dev: false /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} @@ -15472,6 +17118,14 @@ packages: typedarray-to-buffer: 3.1.5 dev: true + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + /write-file-atomic@5.0.1: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2bf4474f0..b449f9f23 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,3 +4,4 @@ packages: - 'packages/client' - 'packages/sw' - 'packages/calckey-js' + - 'packages/megalodon'