diff --git a/.gitignore b/.gitignore index 3c55ec0d78..0a1a09c90d 100644 --- a/.gitignore +++ b/.gitignore @@ -57,9 +57,6 @@ packages/backend/assets/LICENSE !/packages/backend/src/db !/packages/backend/src/server/api/endpoints/drive/files -packages/megalodon/lib -packages/megalodon/.idea - # blender backups *.blend1 *.blend2 diff --git a/Dockerfile b/Dockerfile index c7d9a95d86..7ba32ba832 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,6 @@ COPY packages/backend/package.json packages/backend/package.json COPY packages/client/package.json packages/client/package.json COPY packages/sw/package.json packages/sw/package.json COPY packages/firefish-js/package.json packages/firefish-js/package.json -COPY packages/megalodon/package.json packages/megalodon/package.json COPY packages/backend/native-utils/package.json packages/backend/native-utils/package.json COPY packages/backend/native-utils/npm/linux-x64-musl/package.json packages/backend/native-utils/npm/linux-x64-musl/package.json COPY packages/backend/native-utils/npm/linux-arm64-musl/package.json packages/backend/native-utils/npm/linux-arm64-musl/package.json @@ -56,8 +55,6 @@ RUN apt-get update && apt-get install -y libvips-dev zip unzip tini ffmpeg COPY . ./ -COPY --from=build /firefish/packages/megalodon /firefish/packages/megalodon - # Copy node modules COPY --from=build /firefish/node_modules /firefish/node_modules COPY --from=build /firefish/packages/backend/node_modules /firefish/packages/backend/node_modules diff --git a/packages/README.md b/packages/README.md index ea04817f06..75e38a4940 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,4 +7,3 @@ This directory contains all of the packages Firefish uses. - `client`: Web interface written in Vue3 and TypeScript - `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript - `firefish-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/firefish-js) for public use -- `megalodon`: TypeScript library used for partial Mastodon API compatibility diff --git a/packages/backend/package.json b/packages/backend/package.json index 83c49459b5..26920a1514 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -87,7 +87,7 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", - "megalodon": "workspace:*", + "megalodon": "8.1.1", "meilisearch": "0.34.1", "mfm-js": "0.23.3", "mime-types": "2.1.35", diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index 8a48175579..5bd24ca89b 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -1,8 +1,7 @@ -import megalodon, { MegalodonInterface } from "megalodon"; import Router from "@koa/router"; import { getClient } from "../ApiMastodonCompatibleService.js"; import axios from "axios"; -import { Converter } from "megalodon"; +import Converter from "megalodon"; import { convertTimelinesArgsId, limitToInt } from "./timeline.js"; import { convertAccount, convertStatus } from "../converters.js"; diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index bc95d77769..2c35843dd3 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -380,7 +380,7 @@ export function apiStatusMastodon(router: Router): void { const accessTokens = ctx.headers.authorization; const client = getClient(BASE_URL, accessTokens); try { - const data = await client.reactStatus( + const data = await client.createEmojiReaction( convertId(ctx.params.id, IdType.FirefishId), ctx.params.name, ); @@ -400,7 +400,7 @@ export function apiStatusMastodon(router: Router): void { const accessTokens = ctx.headers.authorization; const client = getClient(BASE_URL, accessTokens); try { - const data = await client.unreactStatus( + const data = await client.deleteEmojiReaction( convertId(ctx.params.id, IdType.FirefishId), ctx.params.name, ); diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index e483683151..5a47f2cba7 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -25,7 +25,7 @@ import { readNotification } from "../common/read-notification.js"; import channels from "./channels/index.js"; import type Channel from "./channel.js"; import type { StreamEventEmitter, StreamMessages } from "./types.js"; -import { Converter } from "megalodon"; +import Converter from "megalodon"; import { getClient } from "../mastodon/ApiMastodonCompatibleService.js"; /** diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index 92961d33d2..779e65ea59 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -163,11 +163,9 @@ mastoRouter.post("/oauth/token", async (ctx) => { ctx.body = ret; return; } - let client_id: any = body.client_id; + let client_id: Array | string | null = body.client_id; const BASE_URL = `${ctx.request.protocol}://${ctx.request.hostname}`; - const generator = (megalodon as any).default; - const client = generator(BASE_URL, null) as MegalodonInterface; - let m = null; + const client = megalodon("firefish", BASE_URL) as MegalodonInterface; let token = null; if (body.code) { //m = body.code.match(/^([a-zA-Z0-9]{8})([a-zA-Z0-9]{4})([a-zA-Z0-9]{4})([a-zA-Z0-9]{4})([a-zA-Z0-9]{12})/); @@ -191,7 +189,7 @@ mastoRouter.post("/oauth/token", async (ctx) => { token ? token : "", ); const ret = { - access_token: atData.accessToken, + access_token: atData.access_token, token_type: "Bearer", scope: body.scope || "read write follow push", created_at: Math.floor(new Date().getTime() / 1000), diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index 90f75b66cf..ad9dc2c233 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -60,7 +60,7 @@ export default defineConfig(({ command, mode }) => { ), _ENV_: JSON.stringify(process.env.NODE_ENV), _DEV_: process.env.NODE_ENV !== "production", - _PERF_PREFIX_: JSON.stringify("Misskey:"), + _PERF_PREFIX_: JSON.stringify("Firefish:"), _DATA_TRANSFER_DRIVE_FILE_: JSON.stringify("mk_drive_file"), _DATA_TRANSFER_DRIVE_FOLDER_: JSON.stringify("mk_drive_folder"), _DATA_TRANSFER_DECK_COLUMN_: JSON.stringify("mk_deck_column"), diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json deleted file mode 100644 index 3403b94b47..0000000000 --- a/packages/megalodon/package.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "megalodon", - "private": true, - "main": "./lib/src/index.js", - "typings": "./lib/src/index.d.ts", - "scripts": { - "build": "tsc -p ./", - "build:debug": "pnpm run build", - "lint": "pnpm biome check **/*.ts --apply", - "format": "pnpm biome format --write src/**/*.ts", - "doc": "typedoc --out ../docs ./src", - "test": "NODE_ENV=test jest -u --maxWorkers=3" - }, - "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" - }, - "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", - "@types/node": "18.11.18", - "@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 deleted file mode 100644 index f19fe38a2b..0000000000 --- a/packages/megalodon/src/axios.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "axios/lib/adapters/http"; diff --git a/packages/megalodon/src/cancel.ts b/packages/megalodon/src/cancel.ts deleted file mode 100644 index f8e4729b8e..0000000000 --- a/packages/megalodon/src/cancel.ts +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 93d669fa7d..0000000000 --- a/packages/megalodon/src/converter.ts +++ /dev/null @@ -1,3 +0,0 @@ -import MisskeyAPI from "./misskey/api_client"; - -export default MisskeyAPI.Converter; diff --git a/packages/megalodon/src/default.ts b/packages/megalodon/src/default.ts deleted file mode 100644 index 45bce13e21..0000000000 --- a/packages/megalodon/src/default.ts +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 06a85eb98e..0000000000 --- a/packages/megalodon/src/entities/account.ts +++ /dev/null @@ -1,27 +0,0 @@ -/// -/// -/// -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 deleted file mode 100644 index 6bc0b6d80e..0000000000 --- a/packages/megalodon/src/entities/activity.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 7c79831634..0000000000 --- a/packages/megalodon/src/entities/announcement.ts +++ /dev/null @@ -1,34 +0,0 @@ -/// -/// -/// - -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 deleted file mode 100644 index 9b98b12772..0000000000 --- a/packages/megalodon/src/entities/application.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 9cc17acc5c..0000000000 --- a/packages/megalodon/src/entities/async_attachment.ts +++ /dev/null @@ -1,14 +0,0 @@ -/// -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 deleted file mode 100644 index 082c79eddb..0000000000 --- a/packages/megalodon/src/entities/attachment.ts +++ /dev/null @@ -1,49 +0,0 @@ -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 deleted file mode 100644 index 356d99aee4..0000000000 --- a/packages/megalodon/src/entities/card.ts +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index a794a7c5a8..0000000000 --- a/packages/megalodon/src/entities/context.ts +++ /dev/null @@ -1,8 +0,0 @@ -/// - -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 deleted file mode 100644 index 2bdc196661..0000000000 --- a/packages/megalodon/src/entities/conversation.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// -/// - -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 deleted file mode 100644 index 10c32ab0bd..0000000000 --- a/packages/megalodon/src/entities/emoji.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index fc9f8c69cc..0000000000 --- a/packages/megalodon/src/entities/featured_tag.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index de4b6b2b72..0000000000 --- a/packages/megalodon/src/entities/field.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 55b7305cc3..0000000000 --- a/packages/megalodon/src/entities/filter.ts +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 4676357d69..0000000000 --- a/packages/megalodon/src/entities/history.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 3b42e6f412..0000000000 --- a/packages/megalodon/src/entities/identity_proof.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 9c0f572db4..0000000000 --- a/packages/megalodon/src/entities/instance.ts +++ /dev/null @@ -1,41 +0,0 @@ -/// -/// -/// - -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 deleted file mode 100644 index 97e75286b2..0000000000 --- a/packages/megalodon/src/entities/list.ts +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 7ee99282ca..0000000000 --- a/packages/megalodon/src/entities/marker.ts +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index 4fe36a6553..0000000000 --- a/packages/megalodon/src/entities/mention.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 68eff3347e..0000000000 --- a/packages/megalodon/src/entities/notification.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// -/// - -namespace Entity { - export type Notification = { - account: Account; - created_at: string; - id: string; - status?: Status; - reaction?: Reaction; - type: NotificationType; - }; - - export type NotificationType = string; -} diff --git a/packages/megalodon/src/entities/poll.ts b/packages/megalodon/src/entities/poll.ts deleted file mode 100644 index 2539d68b20..0000000000 --- a/packages/megalodon/src/entities/poll.ts +++ /dev/null @@ -1,14 +0,0 @@ -/// - -namespace Entity { - export type Poll = { - id: string; - expires_at: string | null; - expired: boolean; - multiple: boolean; - votes_count: number; - options: Array; - voted: boolean; - own_votes: Array; - }; -} diff --git a/packages/megalodon/src/entities/poll_option.ts b/packages/megalodon/src/entities/poll_option.ts deleted file mode 100644 index e818a8607b..0000000000 --- a/packages/megalodon/src/entities/poll_option.ts +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 7994dc568e..0000000000 --- a/packages/megalodon/src/entities/preferences.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index ad1146a242..0000000000 --- a/packages/megalodon/src/entities/push_subscription.ts +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index 4edbec6a7d..0000000000 --- a/packages/megalodon/src/entities/reaction.ts +++ /dev/null @@ -1,12 +0,0 @@ -/// - -namespace Entity { - export type Reaction = { - count: number; - me: boolean; - name: string; - url?: string; - static_url?: string; - accounts?: Array; - }; -} diff --git a/packages/megalodon/src/entities/relationship.ts b/packages/megalodon/src/entities/relationship.ts deleted file mode 100644 index 91802d5c88..0000000000 --- a/packages/megalodon/src/entities/relationship.ts +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 6862a5fabe..0000000000 --- a/packages/megalodon/src/entities/report.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 4448e53350..0000000000 --- a/packages/megalodon/src/entities/results.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// -/// -/// - -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 deleted file mode 100644 index 78dfb8ed26..0000000000 --- a/packages/megalodon/src/entities/scheduled_status.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// -/// -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 deleted file mode 100644 index 913b02fda7..0000000000 --- a/packages/megalodon/src/entities/source.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// -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 deleted file mode 100644 index 6471df039a..0000000000 --- a/packages/megalodon/src/entities/stats.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index f27f728b54..0000000000 --- a/packages/megalodon/src/entities/status.ts +++ /dev/null @@ -1,45 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// - -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; - 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 deleted file mode 100644 index 4040b4ff90..0000000000 --- a/packages/megalodon/src/entities/status_edit.ts +++ /dev/null @@ -1,23 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// - -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 deleted file mode 100644 index 18908c01c1..0000000000 --- a/packages/megalodon/src/entities/status_params.ts +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index ccc88aece6..0000000000 --- a/packages/megalodon/src/entities/tag.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -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 deleted file mode 100644 index 1583edafb1..0000000000 --- a/packages/megalodon/src/entities/token.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 1ee9ed67c9..0000000000 --- a/packages/megalodon/src/entities/urls.ts +++ /dev/null @@ -1,5 +0,0 @@ -namespace Entity { - export type URLs = { - streaming_api: string; - }; -} diff --git a/packages/megalodon/src/entity.ts b/packages/megalodon/src/entity.ts deleted file mode 100644 index b73d2b359b..0000000000 --- a/packages/megalodon/src/entity.ts +++ /dev/null @@ -1,38 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// - -export default Entity; diff --git a/packages/megalodon/src/filter_context.ts b/packages/megalodon/src/filter_context.ts deleted file mode 100644 index 4c83cb15f2..0000000000 --- a/packages/megalodon/src/filter_context.ts +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index 758d3a46ad..0000000000 --- a/packages/megalodon/src/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -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 deleted file mode 100644 index 33a5790f67..0000000000 --- a/packages/megalodon/src/megalodon.ts +++ /dev/null @@ -1,1532 +0,0 @@ -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>; - /** - * POST /api/v1/statuses/:id/react/:name - * @param id The target status id. - * @param name The name of the emoji reaction to add. - * @return Status - */ - reactStatus(id: string, name: string): Promise>; - /** - * POST /api/v1/statuses/:id/unreact/:name - * - * @param id The target status id. - * @param name The name of the emoji reaction to remove. - * @return Status - */ - unreactStatus(id: string, name: 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): 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< - Response> - >; - // ====================================== - // 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 deleted file mode 100644 index 25922a2ffc..0000000000 --- a/packages/megalodon/src/misskey.ts +++ /dev/null @@ -1,3436 +0,0 @@ -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"; -import MisskeyNotificationType from "./misskey/notification"; - -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 = ""; - 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.noteWithDetails( - 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.noteWithDetails( - 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 <= 100 ? options.limit : 100, - }); - } - 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.noteWithDetails( - 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 <= 100 ? options.limit : 100, - }); - } else { - params = Object.assign(params, { - limit: 40, - }); - } - } else { - params = Object.assign(params, { - limit: 40, - }); - } - return this.client - .post>("/api/users/followers", params) - .then(async (res) => { - return Object.assign(res, { - data: await Promise.all( - res.data.map(async (f) => - this.getAccount(f.followerId).then((p) => p.data), - ), - ), - }); - }); - } - - /** - * 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 <= 100 ? options.limit : 100, - }); - } - } - return this.client - .post>("/api/users/following", params) - .then(async (res) => { - return Object.assign(res, { - data: await Promise.all( - res.data.map(async (f) => - this.getAccount(f.followeeId).then((p) => p.data), - ), - ), - }); - }); - } - - 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 <= 100 ? options.limit : 100, - }); - } 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.noteWithDetails( - 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< - Response> - > { - 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(async (res) => { - return Object.assign(res, { - data: this.converter.userPreferences( - res.data, - await this.getDefaultPostPrivacy(), - ), - }); - }); - } - - // ====================================== - // 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 * 1000, - }; - 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.noteWithDetails( - 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.noteWithDetails( - res.data, - this.baseUrlToHost(this.baseUrl), - this.getFreshAccountCache(), - ), - })); - } - - private getFreshAccountCache(): AccountCache { - return { - locks: new AsyncLock(), - accounts: [], - }; - } - - public async notificationWithDetails( - n: MisskeyAPI.Entity.Notification, - host: string, - cache: AccountCache, - ): Promise { - const notification = this.converter.notification(n, host); - if (n.note) - notification.status = await this.noteWithDetails(n.note, host, cache); - if (notification.account) - notification.account = ( - await this.getAccount(notification.account.id) - ).data; - return notification; - } - - public async noteWithDetails( - n: MisskeyAPI.Entity.Note, - host: string, - cache: AccountCache, - ): Promise { - const status = await this.addUserDetailsToStatus( - this.converter.note(n, host), - cache, - ); - status.bookmarked = await this.isStatusBookmarked(n.id); - return this.addMentionsToStatus(status, cache); - } - - public async isStatusBookmarked(id: string): Promise { - return this.client - .post("/api/notes/state", { - noteId: id, - }) - .then((p) => p.data.isFavorited ?? false); - } - - public async addUserDetailsToStatus( - status: Entity.Status, - cache: AccountCache, - ): Promise { - if ( - status.account.followers_count === 0 && - status.account.followers_count === 0 && - status.account.statuses_count === 0 - ) - status.account = - (await this.getAccountCached( - status.account.id, - status.account.acct, - cache, - )) ?? status.account; - - if (status.reblog != null) - status.reblog = await this.addUserDetailsToStatus(status.reblog, cache); - - if (status.quote != null) - status.quote = await this.addUserDetailsToStatus(status.quote, cache); - - return status; - } - - public async addMentionsToStatus( - status: Entity.Status, - cache: AccountCache, - ): Promise { - if (status.mentions.length > 0) return status; - - if (status.reblog != null) - status.reblog = await this.addMentionsToStatus(status.reblog, cache); - - if (status.quote != null) - status.quote = await this.addMentionsToStatus(status.quote, cache); - - const idx = status.account.acct.indexOf("@"); - const origin = idx < 0 ? null : status.account.acct.substring(idx + 1); - - status.mentions = ( - await this.getMentions(status.plain_content!, origin, cache) - ).filter((p) => p != null); - for (const m of status.mentions.filter( - (value, index, array) => array.indexOf(value) === index, - )) { - const regexFull = new RegExp( - `(?<=^|\\s|>)@${m.acct}(?=[^a-zA-Z0-9]|$)`, - "gi", - ); - const regexLocalUser = new RegExp( - `(?<=^|\\s|>)@${m.acct}@${this.baseUrlToHost( - this.baseUrl, - )}(?=[^a-zA-Z0-9]|$)`, - "gi", - ); - const regexRemoteUser = new RegExp( - `(?<=^|\\s|>)@${m.username}(?=[^a-zA-Z0-9@]|$)`, - "gi", - ); - - if (m.acct == m.username) { - status.content = status.content.replace(regexLocalUser, `@${m.acct}`); - } else if (!status.content.match(regexFull)) { - status.content = status.content.replace(regexRemoteUser, `@${m.acct}`); - } - - status.content = status.content.replace( - regexFull, - `@${m.acct}`, - ); - } - return status; - } - - public async getMentions( - text: string, - origin: string | null, - cache: AccountCache, - ): Promise { - const mentions: Entity.Mention[] = []; - - if (text == undefined) return mentions; - - const mentionMatch = text.matchAll( - /(?<=^|\s)@(?[a-zA-Z0-9_]+)(?:@(?[a-zA-Z0-9-.]+\.[a-zA-Z0-9-]+)|)(?=[^a-zA-Z0-9]|$)/g, - ); - - for (const m of mentionMatch) { - try { - if (m.groups == null) continue; - - const account = await this.getAccountByNameCached( - m.groups.user, - m.groups.host ?? origin, - cache, - ); - - if (account == null) continue; - - mentions.push({ - id: account.id, - url: account.url, - username: account.username, - acct: account.acct, - }); - } catch {} - } - - 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 getAccountCached( - id: string, - acct: string, - cache: AccountCache, - ): Promise { - return await cache.locks.acquire(acct, async () => { - const cacheHit = cache.accounts.find((p) => p.id === id); - const account = cacheHit ?? (await this.getAccount(id)).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< - Array - >("/api/notes/conversation", params); - const parents = await Promise.all( - conversation.data.map((n) => - this.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ); - - const context: Entity.Context = { - ancestors: parents.reverse(), - descendants: this.dfs( - await Promise.all( - res.data.map((n) => - this.noteWithDetails( - 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(async (res) => ({ - ...res, - data: ( - await Promise.all(res.data.map((n) => this.getAccount(n.user.id))) - ).map((p) => p.data), - })); - } - - public async getStatusFavouritedBy( - id: string, - ): Promise>> { - return this.client - .post>("/api/notes/reactions", { - noteId: id, - }) - .then(async (res) => ({ - ...res, - data: ( - await Promise.all(res.data.map((n) => this.getAccount(n.user.id))) - ).map((p) => p.data), - })); - } - - 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] ?? "⭐"); - } - - private async getDefaultPostPrivacy(): Promise< - "public" | "unlisted" | "private" | "direct" - > { - // 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 this.client - .post("/api/i/registry/get-unsecure", { - key: "defaultNoteVisibility", - scope: ["client", "base"], - }) - .then((res) => { - if ( - !res.data || - (res.data != "public" && - res.data != "home" && - res.data != "followers" && - res.data != "specified") - ) - return "public"; - return this.converter.visibility(res.data); - }) - .catch((_) => "public"); - } - - 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.noteWithDetails( - 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.noteWithDetails( - 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.noteWithDetails( - 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.noteWithDetails( - 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.noteWithDetails( - 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.noteWithDetails( - res.data, - this.baseUrlToHost(this.baseUrl), - this.getFreshAccountCache(), - ), - })); - } - - /** - * Convert a Unicode emoji or custom emoji name to a Misskey reaction. - * @see Misskey's reaction-lib.ts - */ - private reactionName(name: string): string { - // See: https://github.com/tc39/proposal-regexp-unicode-property-escapes#matching-emoji - const isUnicodeEmoji = - /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu.test( - name, - ); - if (isUnicodeEmoji) { - return name; - } - return `:${name}:`; - } - - /** - * POST /api/notes/reactions/create - */ - public async reactStatus( - id: string, - name: string, - ): Promise> { - await this.client.post<{}>("/api/notes/reactions/create", { - noteId: id, - reaction: this.reactionName(name), - }); - return this.client - .post("/api/notes/show", { - noteId: id, - }) - .then(async (res) => ({ - ...res, - data: await this.noteWithDetails( - res.data, - this.baseUrlToHost(this.baseUrl), - this.getFreshAccountCache(), - ), - })); - } - - /** - * POST /api/notes/reactions/delete - */ - public async unreactStatus( - id: string, - name: string, - ): Promise> { - await this.client.post<{}>("/api/notes/reactions/delete", { - noteId: id, - reaction: this.reactionName(name), - }); - return this.client - .post("/api/notes/show", { - noteId: id, - }) - .then(async (res) => ({ - ...res, - data: await this.noteWithDetails( - 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, - }); - - if (file.originalname != null && file.originalname !== "file") - formData.append("name", file.originalname); - - if (options?.description != null) - formData.append("comment", options.description); - - 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, - }); - } - - if (options.description !== undefined) { - params = Object.assign(params, { - comment: options.description, - }); - } - } - 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> { - const res = await this.getStatus(id); - if (res.data.poll == null) throw new Error("poll not found"); - return { ...res, data: res.data.poll }; - } - - /** - * POST /api/notes/polls/vote - */ - public async votePoll( - id: string, - choices: Array, - ): Promise> { - if (!id) { - return new Promise((_, reject) => { - const err = new ArgumentError("id is required"); - reject(err); - }); - } - - for (const c of choices) { - const params = { - noteId: id, - choice: +c, - }; - await this.client.post<{}>("/api/notes/polls/vote", params); - } - - const res = await this.client - .post("/api/notes/show", { - noteId: id, - }) - .then(async (res) => { - const note = await this.noteWithDetails( - 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.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ) - ).sort(this.sortByIdDesc), - })); - } - - /** - * 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.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ) - ).sort(this.sortByIdDesc), - })); - } - - /** - * 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.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ) - ).sort(this.sortByIdDesc), - })); - } - - /** - * 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.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ) - ).sort(this.sortByIdDesc), - })); - } - - /** - * 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.noteWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - accountCache, - ), - ), - ) - ).sort(this.sortByIdDesc), - })); - } - - // ====================================== - // 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); - }); - } - - private sortByIdDesc(a: Entity.Status, b: Entity.Status): number { - if (a.id < b.id) return 1; - if (a.id > b.id) return -1; - - return 0; - } - - // ====================================== - // 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 <= 100 ? options.limit : 100, - }); - } 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, - }); - } - const cache = this.getFreshAccountCache(); - return this.client - .post>( - "/api/i/notifications", - params, - ) - .then(async (res) => ({ - ...res, - data: await Promise.all( - res.data - .filter( - (p) => p.type != MisskeyNotificationType.FollowRequestAccepted, - ) // these aren't supported on mastodon - .map((n) => - this.notificationWithDetails( - n, - this.baseUrlToHost(this.baseUrl), - cache, - ), - ), - ), - })); - } - - 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< - Response - > { - 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": { - if (q.startsWith("http://") || q.startsWith("https://")) { - return this.client - .post("/api/ap/show", { uri: q }) - .then(async (res) => { - if (res.status != 200 || res.data.type != "User") { - res.status = 200; - res.statusText = "OK"; - res.data = { - accounts: [], - statuses: [], - hashtags: [], - }; - - return res; - } - - const account = await this.converter.userDetail( - res.data.object as MisskeyAPI.Entity.UserDetail, - this.baseUrlToHost(this.baseUrl), - ); - - return { - ...res, - data: { - accounts: - options?.max_id && options?.max_id >= account.id - ? [] - : [account], - statuses: [], - hashtags: [], - }, - }; - }); - } - 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( - /^@(?[a-zA-Z0-9_]+)(?:@(?[a-zA-Z0-9-.]+\.[a-zA-Z0-9-]+)|)$/, - ); - 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": { - if (q.startsWith("http://") || q.startsWith("https://")) { - return this.client - .post("/api/ap/show", { uri: q }) - .then(async (res) => { - if (res.status != 200 || res.data.type != "Note") { - res.status = 200; - res.statusText = "OK"; - res.data = { - accounts: [], - statuses: [], - hashtags: [], - }; - - return res; - } - - const post = await this.noteWithDetails( - res.data.object as MisskeyAPI.Entity.Note, - this.baseUrlToHost(this.baseUrl), - accountCache, - ); - - return { - ...res, - data: { - accounts: [], - statuses: - options?.max_id && options.max_id >= post.id ? [] : [post], - 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, - }); - } - 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.noteWithDetails( - 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< - Response> - > { - 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< - Response> - > { - 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.noteWithDetails( - 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.noteWithDetails( - 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 deleted file mode 100644 index 47932cbf19..0000000000 --- a/packages/megalodon/src/misskey/api_client.ts +++ /dev/null @@ -1,727 +0,0 @@ -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 State = MisskeyEntity.State; - 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, - header_static: this.plcUrl, - 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 || u.username, - locked: u.isLocked, - created_at: u.createdAt, - followers_count: u.followersCount, - following_count: u.followingCount, - statuses_count: u.notesCount, - note: u.description?.replace(/\n|\\n/g, "
") ?? "", - 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, - v: "public" | "unlisted" | "private" | "direct", - ): MegalodonEntity.Preferences => { - return { - "reading:expand:media": "default", - "reading:expand:spoilers": false, - "posting:default:language": u.lang, - "posting:default:sensitive": u.alwaysMarkNsfw, - "posting:default:visibility": v, - }; - }; - - 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, id: string): MegalodonEntity.Poll => { - const now = dayjs(); - const expire = dayjs(p.expiresAt); - const count = p.choices.reduce((sum, choice) => sum + choice.votes, 0); - return { - id: 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), - own_votes: p.choices - .filter((c) => c.isVoted) - .map((c) => p.choices.indexOf(c)), - }; - }; - - 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, - // Remove reaction emojis with names containing @ from the emojis list. - emojis: n.emojis - .filter((e) => e.name.indexOf("@") === -1) - .map((e) => 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((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, n.id) : null, - application: null, - language: null, - pinned: null, - // Use emojis list to provide URLs for emoji reactions. - reactions: this.mapReactions(n.emojis, n.reactions, n.myReaction), - bookmarked: false, - quote: n.renote && n.text ? this.note(n.renote, host) : null, - }; - }; - - mapReactions = ( - emojis: Array, - r: { [key: string]: number }, - myReaction?: string, - ): Array => { - // Map of emoji shortcodes to image URLs. - const emojiUrls = new Map( - emojis.map((e) => [e.name, e.url]), - ); - return Object.keys(r).map((key) => { - // Strip colons from custom emoji reaction names to match emoji shortcodes. - const shortcode = key.replaceAll(":", ""); - // If this is a custom emoji (vs. a Unicode emoji), find its image URL. - const url = emojiUrls.get(shortcode); - // Finally, remove trailing @. from local custom emoji reaction names. - const name = shortcode.replace("@.", ""); - return { - count: r[key], - me: key === myReaction, - name, - url, - // We don't actually have a static version of the asset, but clients expect one anyway. - static_url: url, - }; - }); - }; - - 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.Reaction: - return MisskeyNotificationType.Reaction; - case NotificationType.Reblog: - return MisskeyNotificationType.Renote; - case NotificationType.Poll: - return MisskeyNotificationType.PollEnded; - 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.Reaction; - case MisskeyNotificationType.PollEnded: - return NotificationType.Poll; - 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 (notification.type === NotificationType.Poll) { - notification = Object.assign(notification, { - account: this.note(n.note, host).account, - }); - } - if (n.reaction) { - notification = Object.assign(notification, { - reaction: this.mapReactions(n.note.emojis, { [n.reaction]: 1 })[0], - }); - } - } - 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, - }); - } - } - - 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 deleted file mode 100644 index 94ace2f184..0000000000 --- a/packages/megalodon/src/misskey/entities/GetAll.ts +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 7594ba7efc..0000000000 --- a/packages/megalodon/src/misskey/entities/announcement.ts +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index 5924060d81..0000000000 --- a/packages/megalodon/src/misskey/entities/app.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 3e56790a7b..0000000000 --- a/packages/megalodon/src/misskey/entities/blocking.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -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 deleted file mode 100644 index 235f7063fb..0000000000 --- a/packages/megalodon/src/misskey/entities/createdNote.ts +++ /dev/null @@ -1,7 +0,0 @@ -/// - -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 deleted file mode 100644 index d320760e91..0000000000 --- a/packages/megalodon/src/misskey/entities/emoji.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index ba948f2e73..0000000000 --- a/packages/megalodon/src/misskey/entities/favorite.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -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 deleted file mode 100644 index 8bbb2d7c42..0000000000 --- a/packages/megalodon/src/misskey/entities/field.ts +++ /dev/null @@ -1,7 +0,0 @@ -namespace MisskeyEntity { - export type Field = { - name: string; - value: string; - verified?: string; - }; -} diff --git a/packages/megalodon/src/misskey/entities/file.ts b/packages/megalodon/src/misskey/entities/file.ts deleted file mode 100644 index e823dde1be..0000000000 --- a/packages/megalodon/src/misskey/entities/file.ts +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 60bd0e0abc..0000000000 --- a/packages/megalodon/src/misskey/entities/followRequest.ts +++ /dev/null @@ -1,9 +0,0 @@ -/// - -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 deleted file mode 100644 index 34ae825519..0000000000 --- a/packages/megalodon/src/misskey/entities/follower.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// - -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 deleted file mode 100644 index 6cbc8f1c39..0000000000 --- a/packages/megalodon/src/misskey/entities/following.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// - -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 deleted file mode 100644 index 3ec4d6675b..0000000000 --- a/packages/megalodon/src/misskey/entities/hashtag.ts +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 60706592a4..0000000000 --- a/packages/megalodon/src/misskey/entities/list.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 97827fe8fd..0000000000 --- a/packages/megalodon/src/misskey/entities/meta.ts +++ /dev/null @@ -1,18 +0,0 @@ -/// - -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: 3000; - emojis: Array; - }; -} diff --git a/packages/megalodon/src/misskey/entities/mute.ts b/packages/megalodon/src/misskey/entities/mute.ts deleted file mode 100644 index 7975b3d315..0000000000 --- a/packages/megalodon/src/misskey/entities/mute.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - -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 deleted file mode 100644 index 64a0a50785..0000000000 --- a/packages/megalodon/src/misskey/entities/note.ts +++ /dev/null @@ -1,32 +0,0 @@ -/// -/// -/// -/// - -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 deleted file mode 100644 index 7ecb911537..0000000000 --- a/packages/megalodon/src/misskey/entities/notification.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// -/// - -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 deleted file mode 100644 index 9f6bfa40d2..0000000000 --- a/packages/megalodon/src/misskey/entities/poll.ts +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index b35a25bfb5..0000000000 --- a/packages/megalodon/src/misskey/entities/reaction.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// - -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 deleted file mode 100644 index 6db4a1b167..0000000000 --- a/packages/megalodon/src/misskey/entities/relation.ts +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 572333ff0b..0000000000 --- a/packages/megalodon/src/misskey/entities/session.ts +++ /dev/null @@ -1,6 +0,0 @@ -namespace MisskeyEntity { - export type Session = { - token: string; - url: string; - }; -} diff --git a/packages/megalodon/src/misskey/entities/state.ts b/packages/megalodon/src/misskey/entities/state.ts deleted file mode 100644 index 62d60ce282..0000000000 --- a/packages/megalodon/src/misskey/entities/state.ts +++ /dev/null @@ -1,7 +0,0 @@ -namespace MisskeyEntity { - export type State = { - isFavorited: boolean; - isMutedThread: boolean; - isWatching: boolean; - }; -} diff --git a/packages/megalodon/src/misskey/entities/stats.ts b/packages/megalodon/src/misskey/entities/stats.ts deleted file mode 100644 index 9832a0ad8a..0000000000 --- a/packages/megalodon/src/misskey/entities/stats.ts +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 96610f6e6d..0000000000 --- a/packages/megalodon/src/misskey/entities/user.ts +++ /dev/null @@ -1,13 +0,0 @@ -/// - -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 deleted file mode 100644 index 0f5bd5f644..0000000000 --- a/packages/megalodon/src/misskey/entities/userDetail.ts +++ /dev/null @@ -1,34 +0,0 @@ -/// -/// -/// - -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 deleted file mode 100644 index 272e65ffa4..0000000000 --- a/packages/megalodon/src/misskey/entities/userDetailMe.ts +++ /dev/null @@ -1,36 +0,0 @@ -/// -/// -/// - -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 deleted file mode 100644 index 921af65536..0000000000 --- a/packages/megalodon/src/misskey/entities/userkey.ts +++ /dev/null @@ -1,8 +0,0 @@ -/// - -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 deleted file mode 100644 index 72a80f9d96..0000000000 --- a/packages/megalodon/src/misskey/entity.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// - -export default MisskeyEntity; diff --git a/packages/megalodon/src/misskey/notification.ts b/packages/megalodon/src/misskey/notification.ts deleted file mode 100644 index eb7c2d23d8..0000000000 --- a/packages/megalodon/src/misskey/notification.ts +++ /dev/null @@ -1,18 +0,0 @@ -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 PollEnded: MisskeyEntity.NotificationType = "pollEnded"; - 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 deleted file mode 100644 index 677f2049d3..0000000000 --- a/packages/megalodon/src/misskey/web_socket.ts +++ /dev/null @@ -1,458 +0,0 @@ -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 = 60000; - private _pongWaiting = false; - - /** - * @param url Full url of websocket: e.g. wss://firefish.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 deleted file mode 100644 index 84cd23e40d..0000000000 --- a/packages/megalodon/src/notification.ts +++ /dev/null @@ -1,14 +0,0 @@ -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 Reaction: Entity.NotificationType = "reaction"; - export const FollowRequest: Entity.NotificationType = "follow_request"; - export const Status: Entity.NotificationType = "status"; - export const Poll: Entity.NotificationType = "poll"; -} - -export default NotificationType; diff --git a/packages/megalodon/src/oauth.ts b/packages/megalodon/src/oauth.ts deleted file mode 100644 index f0df721f0a..0000000000 --- a/packages/megalodon/src/oauth.ts +++ /dev/null @@ -1,123 +0,0 @@ -/** - * 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 deleted file mode 100644 index 2ddf2ac2e6..0000000000 --- a/packages/megalodon/src/parser.ts +++ /dev/null @@ -1,94 +0,0 @@ -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 = 0; - let offset = 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 deleted file mode 100644 index fadbcf084e..0000000000 --- a/packages/megalodon/src/proxy_config.ts +++ /dev/null @@ -1,92 +0,0 @@ -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 deleted file mode 100644 index 13fd8ab574..0000000000 --- a/packages/megalodon/src/response.ts +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 8964535509..0000000000 --- a/packages/megalodon/test/integration/megalodon.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 0ec1288428..0000000000 --- a/packages/megalodon/test/integration/misskey.spec.ts +++ /dev/null @@ -1,204 +0,0 @@ -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.PollEnded, - 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.Reaction, - title: 'reaction' - }, - { - event: pollVote, - expected: MegalodonNotificationType.Poll, - 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 deleted file mode 100644 index 7cf33b983d..0000000000 --- a/packages/megalodon/test/unit/misskey/api_client.spec.ts +++ /dev/null @@ -1,233 +0,0 @@ -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.Reaction, - dist: MisskeyNotificationType.Reaction - }, - { - src: MegalodonNotificationType.Reblog, - dist: MisskeyNotificationType.Renote - }, - { - src: MegalodonNotificationType.Poll, - dist: MisskeyNotificationType.PollEnded - }, - { - 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.Reaction - }, - { - src: MisskeyNotificationType.PollEnded, - dist: MegalodonNotificationType.Poll - }, - { - 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 deleted file mode 100644 index 5174a647c6..0000000000 --- a/packages/megalodon/test/unit/parser.spec.ts +++ /dev/null @@ -1,152 +0,0 @@ -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, - 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 deleted file mode 100644 index 5a9bfbde9a..0000000000 --- a/packages/megalodon/tsconfig.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "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": ["es2021", "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/packages/sw/package.json b/packages/sw/package.json index aa86e4c0a7..d92cfd5e89 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -2,7 +2,7 @@ "name": "sw", "private": true, "scripts": { - "build": "webpack", + "build": "pnpm vite build --emptyOutDir", "build:debug": "pnpm run build", "watch": "pnpm swc src -d built -D -w", "lint": "pnpm biome check **/*.ts --apply", @@ -14,8 +14,10 @@ "@swc/core-android-arm64": "1.3.11", "firefish-js": "workspace:*", "idb-keyval": "^6.2.1", - "swc-loader": "^0.2.3", - "webpack": "^5.85.1", - "webpack-cli": "^5.1.3" + "vite": "4.4.9", + "vite-plugin-compression": "^0.5.1" + }, + "optionalDependencies": { + "@swc/core-android-arm64": "1.3.11" } } diff --git a/packages/sw/vite.config.ts b/packages/sw/vite.config.ts new file mode 100644 index 0000000000..235ae1d6e8 --- /dev/null +++ b/packages/sw/vite.config.ts @@ -0,0 +1,42 @@ +import { defineConfig } from "vite"; +const locales = require("../../locales"); +const meta = require("../../package.json"); + +const isProduction = process.env.NODE_ENV === "production"; +import viteCompression from "vite-plugin-compression"; + +export default defineConfig({ + mode: isProduction ? "production" : "development", + build: { + target: "modules", + outDir: "../../built/_sw_dist_", + assetsDir: "", + rollupOptions: { + input: "./src/sw.ts", + output: { + entryFileNames: "sw.js", + }, + }, + }, + resolve: { + alias: { + "@/": `${__dirname}/src/`, + }, + extensions: [".js", ".ts"], + }, + define: { + _VERSION_: JSON.stringify(meta.version), + _LANGS_: JSON.stringify( + Object.entries(locales).map(([k, v]) => [k, v._lang_]), + ), + _ENV_: JSON.stringify(process.env.NODE_ENV), + _DEV_: !isProduction, + _PERF_PREFIX_: JSON.stringify("Firefish:"), + }, + plugins: [ + viteCompression({ + algorithm: "brotliCompress", + verbose: false, + }), + ], +}); diff --git a/packages/sw/webpack.config.js b/packages/sw/webpack.config.js deleted file mode 100644 index 5df2544098..0000000000 --- a/packages/sw/webpack.config.js +++ /dev/null @@ -1,50 +0,0 @@ -const webpack = require("webpack"); -const path = require("path"); -const locales = require("../../locales"); -const meta = require("../../package.json"); - -const isProduction = process.env.NODE_ENV === "production"; - -module.exports = { - mode: isProduction ? "production" : "development", - stats: "errors-only", - entry: "./src/sw.ts", - output: { - path: path.resolve(__dirname, "../../built/_sw_dist_"), - filename: "sw.js", - }, - resolve: { - extensions: [".js", ".ts"], - }, - module: { - rules: [ - { - test: /\.ts$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: "swc-loader", - options: { - // This makes swc-loader invoke swc synchronously. - sync: true, - jsc: { - parser: { - syntax: "typescript", - }, - }, - }, - }, - }, - ], - }, - plugins: [ - new webpack.DefinePlugin({ - _VERSION_: JSON.stringify(meta.version), - _LANGS_: JSON.stringify( - Object.entries(locales).map(([k, v]) => [k, v._lang_]), - ), - _ENV_: JSON.stringify(process.env.NODE_ENV), - _DEV_: !isProduction, - _PERF_PREFIX_: JSON.stringify("Firefish:"), - }), - ], -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f84c5f5813..43404fe04b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -280,8 +280,8 @@ importers: specifier: 7.0.2 version: 7.0.2(@types/koa@2.13.8)(ejs@3.1.9)(pug@3.0.2) megalodon: - specifier: workspace:* - version: link:../megalodon + specifier: 8.1.1 + version: 8.1.1 meilisearch: specifier: 0.34.1 version: 0.34.1 @@ -950,125 +950,11 @@ importers: specifier: 5.1.3 version: 5.1.3 - packages/megalodon: - dependencies: - '@types/oauth': - specifier: ^0.9.0 - version: 0.9.1 - '@types/ws': - specifier: ^8.5.4 - version: 8.5.5 - 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.7 - 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/node': - specifier: 18.11.18 - version: 18.11.18 - '@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.2 - '@typescript-eslint/eslint-plugin': - specifier: ^5.49.0 - version: 5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(typescript@4.9.4) - '@typescript-eslint/parser': - specifier: ^5.49.0 - version: 5.49.0(eslint@8.44.0)(typescript@4.9.4) - eslint: - specifier: ^8.32.0 - version: 8.44.0 - eslint-config-prettier: - specifier: ^8.6.0 - version: 8.9.0(eslint@8.44.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.44.0) - eslint-plugin-import: - specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.44.0) - eslint-plugin-node: - specifier: ^11.0.0 - version: 11.0.0(eslint@8.44.0) - eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.9.0)(eslint@8.44.0)(prettier@2.8.3) - eslint-plugin-promise: - specifier: ^6.1.1 - version: 6.1.1(eslint@8.44.0) - eslint-plugin-standard: - specifier: ^5.0.0 - version: 5.0.0(eslint@8.44.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.14 - prettier: - specifier: ^2.8.3 - version: 2.8.3 - ts-jest: - specifier: ^29.0.5 - version: 29.0.5(@babel/core@7.22.10)(jest@29.4.0)(typescript@4.9.4) - typedoc: - specifier: ^0.23.24 - version: 0.23.24(typescript@4.9.4) - packages/sw: + optionalDependencies: + '@swc/core-android-arm64': + specifier: 1.3.11 + version: 1.3.11 devDependencies: '@swc/cli': specifier: ^0.1.62 @@ -1076,24 +962,18 @@ importers: '@swc/core': specifier: 1.3.78 version: 1.3.78 - '@swc/core-android-arm64': - specifier: 1.3.11 - version: 1.3.11 firefish-js: specifier: workspace:* version: link:../firefish-js idb-keyval: specifier: ^6.2.1 version: 6.2.1 - swc-loader: - specifier: ^0.2.3 - version: 0.2.3(@swc/core@1.3.78)(webpack@5.88.1) - webpack: - specifier: ^5.85.1 - version: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - webpack-cli: - specifier: ^5.1.3 - version: 5.1.3(webpack@5.88.1) + vite: + specifier: 4.4.9 + version: 4.4.9(@types/node@20.5.8)(sass@1.66.1) + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1(vite@4.4.9) packages: @@ -1329,16 +1209,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.10): - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.10): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: @@ -1738,11 +1608,6 @@ packages: twemoji-parser: 14.0.0 universalify: 0.1.2 - /@discoveryjs/json-ext@0.5.7: - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} - dev: true - /@elastic/elasticsearch@7.17.0: resolution: {integrity: sha512-5QLPCjd0uLmLj1lSuKSThjNpq39f6NmlTy9ROLFwG5gjyTgpwSqufDeYG/Fm43Xs05uF7WcscoO7eguI3HuuYA==} engines: {node: '>=12'} @@ -1962,16 +1827,6 @@ packages: dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.44.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.44.0 - eslint-visitor-keys: 3.4.2 - dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.46.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2185,11 +2040,6 @@ packages: - supports-color dev: true - /@eslint/js@8.44.0: - resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - /@eslint/js@8.46.0: resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2269,18 +2119,6 @@ packages: slash: 3.0.0 dev: true - /@jest/console@29.6.2: - resolution: {integrity: sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - chalk: 4.1.2 - jest-message-util: 29.6.2 - jest-util: 29.6.2 - 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} @@ -2326,49 +2164,6 @@ packages: - utf-8-validate dev: true - /@jest/core@29.6.2: - resolution: {integrity: sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==} - 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.2 - '@jest/reporters': 29.6.2 - '@jest/test-result': 29.6.2 - '@jest/transform': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - 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.2(@types/node@20.5.8) - jest-haste-map: 29.6.2 - jest-message-util: 29.6.2 - jest-regex-util: 29.4.3 - jest-resolve: 29.6.2 - jest-resolve-dependencies: 29.6.2 - jest-runner: 29.6.2 - jest-runtime: 29.6.2 - jest-snapshot: 29.6.2 - jest-util: 29.6.2 - jest-validate: 29.6.2 - jest-watcher: 29.6.2 - micromatch: 4.0.5 - pretty-format: 29.6.2 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - 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} @@ -2379,33 +2174,6 @@ packages: jest-mock: 27.5.1 dev: true - /@jest/environment@29.6.2: - resolution: {integrity: sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - jest-mock: 29.6.2 - dev: true - - /@jest/expect-utils@29.6.2: - resolution: {integrity: sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.4.3 - dev: true - - /@jest/expect@29.6.2: - resolution: {integrity: sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.6.2 - jest-snapshot: 29.6.2 - 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} @@ -2418,18 +2186,6 @@ packages: jest-util: 27.5.1 dev: true - /@jest/fake-timers@29.6.2: - resolution: {integrity: sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.5.8 - jest-message-util: 29.6.2 - jest-mock: 29.6.2 - jest-util: 29.6.2 - 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} @@ -2439,18 +2195,6 @@ packages: expect: 27.5.1 dev: true - /@jest/globals@29.6.2: - resolution: {integrity: sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.6.2 - '@jest/expect': 29.6.2 - '@jest/types': 29.6.1 - jest-mock: 29.6.2 - 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} @@ -2489,43 +2233,6 @@ packages: - supports-color dev: true - /@jest/reporters@29.6.2: - resolution: {integrity: sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==} - 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.2 - '@jest/test-result': 29.6.2 - '@jest/transform': 29.6.2 - '@jest/types': 29.6.1 - '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.5.8 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - 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.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.6 - jest-message-util: 29.6.2 - jest-util: 29.6.2 - jest-worker: 29.6.2 - 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.6.0: resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2542,15 +2249,6 @@ 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.19 - 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} @@ -2561,16 +2259,6 @@ packages: collect-v8-coverage: 1.0.2 dev: true - /@jest/test-result@29.6.2: - resolution: {integrity: sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.6.2 - '@jest/types': 29.6.1 - '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.2 - 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} @@ -2583,16 +2271,6 @@ packages: - supports-color dev: true - /@jest/test-sequencer@29.6.2: - resolution: {integrity: sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.6.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.6.2 - 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} @@ -2616,29 +2294,6 @@ packages: - supports-color dev: true - /@jest/transform@29.6.2: - resolution: {integrity: sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.22.10 - '@jest/types': 29.6.1 - '@jridgewell/trace-mapping': 0.3.19 - 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.2 - jest-regex-util: 29.4.3 - jest-util: 29.6.2 - 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} @@ -2650,18 +2305,6 @@ packages: chalk: 4.1.2 dev: true - /@jest/types@29.6.1: - resolution: {integrity: sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==} - 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.5.8 - '@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'} @@ -3181,18 +2824,6 @@ 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: @@ -3235,8 +2866,11 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [android] + requiresBuild: true dependencies: '@swc/wasm': 1.2.130 + dev: false + optional: true /@swc/core-darwin-arm64@1.3.78: resolution: {integrity: sha512-596KRua/d5Gx1buHKKchSyHuwoIL4S1BRD/wCvYNLNZ3xOzcuBBmXOjrDVigKi1ztNDeS07p30RO5UyYur0XAA==} @@ -3341,6 +2975,9 @@ packages: /@swc/wasm@1.2.130: resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==} + requiresBuild: true + dev: false + optional: true /@syuilo/aiscript@0.11.1: resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==} @@ -3717,10 +3354,6 @@ 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: @@ -3791,10 +3424,6 @@ packages: '@types/keygrip': 1.0.2 '@types/node': 20.5.8 - /@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 @@ -3854,13 +3483,6 @@ packages: '@types/node': 18.11.18 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: @@ -3935,13 +3557,6 @@ packages: pretty-format: 27.5.1 dev: true - /@types/jest@29.4.0: - resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==} - dependencies: - expect: 29.6.2 - pretty-format: 29.6.2 - dev: true - /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true @@ -4191,11 +3806,14 @@ packages: resolution: {integrity: sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==} dependencies: '@types/node': 18.11.18 - - /@types/object-assign-deep@0.4.0: - resolution: {integrity: sha512-3D0F3rHRNDc8cQSXNzwF1jBrJi28Mdrhc10ZLlqbJWDPYRWTTWB9Tc8JoKrgBvLKioXoPoHT6Uzf3s2F7akCUg==} dev: true + /@types/oauth@0.9.2: + resolution: {integrity: sha512-Nu3/abQ6yR9VlsCdX3aiGsWFkj6OJvJqDvg/36t8Gwf2mFXdBZXPDN3K+2yfeA6Lo2m1Q12F8Qil9TZ48nWhOQ==} + dependencies: + '@types/node': 20.5.8 + dev: false + /@types/offscreencanvas@2019.3.0: resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==} dev: false @@ -4204,10 +3822,6 @@ 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 @@ -4412,12 +4026,6 @@ 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 @@ -4426,33 +4034,6 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.44.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.44.0)(typescript@4.9.4) - '@typescript-eslint/scope-manager': 5.49.0 - '@typescript-eslint/type-utils': 5.49.0(eslint@8.44.0)(typescript@4.9.4) - '@typescript-eslint/utils': 5.49.0(eslint@8.44.0)(typescript@4.9.4) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.44.0 - ignore: 5.2.4 - natural-compare-lite: 1.4.0 - regexpp: 3.2.0 - semver: 7.5.4 - tsutils: 3.21.0(typescript@4.9.4) - typescript: 4.9.4 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.46.0)(typescript@5.2.2): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4511,26 +4092,6 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@5.49.0(eslint@8.44.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.44.0 - typescript: 4.9.4 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.46.0)(typescript@5.2.2): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4572,14 +4133,6 @@ packages: - 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/scope-manager@5.62.0: resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4596,26 +4149,6 @@ packages: '@typescript-eslint/visitor-keys': 6.3.0 dev: true - /@typescript-eslint/type-utils@5.49.0(eslint@8.44.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.44.0)(typescript@4.9.4) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.44.0 - tsutils: 3.21.0(typescript@4.9.4) - typescript: 4.9.4 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/type-utils@5.62.0(eslint@8.46.0)(typescript@5.2.2): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4656,11 +4189,6 @@ packages: - 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/types@5.62.0: resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4671,27 +4199,6 @@ packages: engines: {node: ^16.0.0 || >=18.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.4 - tsutils: 3.21.0(typescript@4.9.4) - typescript: 4.9.4 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.2.2): resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4734,26 +4241,6 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@5.49.0(eslint@8.44.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.44.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0(eslint@8.44.0) - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.46.0)(typescript@5.2.2): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4793,14 +4280,6 @@ packages: - 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.2 - dev: true - /@typescript-eslint/visitor-keys@5.62.0: resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5052,43 +4531,6 @@ packages: resolution: {integrity: sha512-9AXJSmL3MzY8ZL//JjudA//q+2kBRGhLBFpkdGksWIuxrMy81nFrCzj2Am+mbh8WoU6rXmv7cY5E3rdlyru2Qg==} dev: false - /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.3)(webpack@5.88.1): - resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - dependencies: - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.88.1) - dev: true - - /@webpack-cli/info@2.0.2(webpack-cli@5.1.3)(webpack@5.88.1): - resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - dependencies: - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.88.1) - dev: true - - /@webpack-cli/serve@2.0.5(webpack-cli@5.1.3)(webpack@5.88.1): - resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - webpack-dev-server: '*' - peerDependenciesMeta: - webpack-dev-server: - optional: true - dependencies: - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.88.1) - dev: true - /@withtypes/mime@0.1.2: resolution: {integrity: sha512-PB9BfZGzwblUONJY0LiOwsHCA6uV3DIPj/w9ReekdHxPOl0VdUFgI5s4avKycuuq9Gf5Nz2ZPA2O36GAUzlMPA==} dependencies: @@ -5668,10 +5110,6 @@ 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'} @@ -5828,8 +5266,8 @@ packages: - debug dev: true - /axios@1.2.2: - resolution: {integrity: sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==} + /axios@1.4.0: + resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 @@ -5838,8 +5276,8 @@ packages: - debug dev: false - /axios@1.4.0: - resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} + /axios@1.5.1: + resolution: {integrity: sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==} dependencies: follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 @@ -5871,24 +5309,6 @@ packages: - supports-color dev: true - /babel-jest@29.6.2(@babel/core@7.22.10): - resolution: {integrity: sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.22.10 - '@jest/transform': 29.6.2 - '@types/babel__core': 7.20.1 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.5.0(@babel/core@7.22.10) - 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'} @@ -5912,16 +5332,6 @@ 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.10 - '@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.10): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: @@ -5953,17 +5363,6 @@ packages: babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) dev: true - /babel-preset-jest@29.5.0(@babel/core@7.22.10): - 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.10 - babel-plugin-jest-hoist: 29.5.0 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) - dev: true - /babel-walk@3.0.0-canary-5: resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} engines: {node: '>= 10.0.0'} @@ -6785,15 +6184,6 @@ packages: engines: {node: '>= 0.10'} dev: true - /clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - /clone-response@1.0.3: resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} dependencies: @@ -7262,10 +6652,6 @@ 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} @@ -7582,8 +6968,8 @@ packages: time-zone: 1.0.0 dev: true - /dayjs@1.11.7: - resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: false /dayjs@1.11.9: @@ -7724,15 +7110,6 @@ packages: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} dev: true - /dedent@1.5.1: - resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - dev: true - /deep-email-validator@0.1.21: resolution: {integrity: sha512-DBAmMzbr+MAubXQ+TS9tZuPwLcdKscb8YzKZiwoLqF3NmaeEgXvSSHhZ0EXOFeKFE2FNWC4mNXCyiQ/JdFXUwg==} dependencies: @@ -8078,11 +7455,6 @@ packages: /electron-to-chromium@1.4.488: resolution: {integrity: sha512-Dv4sTjiW7t/UWGL+H8ZkgIjtUAVZDgb/PwGWvMsCT7jipzUV/u5skbLXPFKb6iV0tiddVi/bcS2/kUrczeWgIQ==} - /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'} @@ -8163,12 +7535,6 @@ packages: engines: {node: '>=6'} dev: false - /envinfo@7.10.0: - resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} - engines: {node: '>=4'} - hasBin: true - dev: true - /err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} dev: false @@ -8368,15 +7734,6 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-prettier@8.9.0(eslint@8.44.0): - resolution: {integrity: sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.44.0 - dev: true - /eslint-config-prettier@8.9.0(eslint@8.46.0): resolution: {integrity: sha512-+sbni7NfVXnOpnRadUA8S28AUlsZt9GjgFvABIRL9Hkn8KqNzOp+7Lw4QWtrwn20KzU3wqu1QoOj2m+7rKRqkA==} hasBin: true @@ -8395,20 +7752,6 @@ packages: eslint: 8.46.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.44.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.44.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.44.0) - eslint-plugin-node: 11.0.0(eslint@8.44.0) - eslint-plugin-promise: 6.1.1(eslint@8.44.0) - dev: true - /eslint-formatter-pretty@4.1.0: resolution: {integrity: sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==} engines: {node: '>=10'} @@ -8433,35 +7776,6 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.9)(eslint@8.44.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.44.0)(typescript@4.9.4) - debug: 3.2.7(supports-color@8.1.1) - eslint: 8.44.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.46.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} @@ -8531,17 +7845,6 @@ packages: eslint: 8.46.0 dev: true - /eslint-plugin-es@3.0.1(eslint@8.44.0): - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - dependencies: - eslint: 8.44.0 - eslint-utils: 2.1.0 - regexpp: 3.2.0 - dev: true - /eslint-plugin-es@4.1.0(eslint@8.46.0): resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} engines: {node: '>=8.10.0'} @@ -8580,39 +7883,6 @@ packages: htmlparser2: 8.0.2 dev: true - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.44.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.44.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.44.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.9)(eslint@8.44.0) - has: 1.0.3 - is-core-module: 2.13.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.6 - resolve: 1.22.4 - semver: 6.3.1 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - /eslint-plugin-import@2.28.0(@typescript-eslint/parser@5.62.0)(eslint@8.46.0): resolution: {integrity: sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==} engines: {node: '>=4'} @@ -8763,38 +8033,6 @@ packages: semver: 7.5.4 dev: true - /eslint-plugin-node@11.0.0(eslint@8.44.0): - resolution: {integrity: sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - dependencies: - eslint: 8.44.0 - eslint-plugin-es: 3.0.1(eslint@8.44.0) - eslint-utils: 2.1.0 - ignore: 5.2.4 - minimatch: 3.1.2 - resolve: 1.22.4 - semver: 6.3.1 - dev: true - - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.9.0)(eslint@8.44.0)(prettier@2.8.3): - 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.44.0 - eslint-config-prettier: 8.9.0(eslint@8.44.0) - prettier: 2.8.3 - prettier-linter-helpers: 1.0.0 - dev: true - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.9.0)(eslint@8.46.0)(prettier@3.0.3): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} @@ -8842,15 +8080,6 @@ packages: eslint: 8.46.0 dev: true - /eslint-plugin-promise@6.1.1(eslint@8.44.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.44.0 - dev: true - /eslint-plugin-promise@6.1.1(eslint@8.46.0): resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8860,15 +8089,6 @@ packages: eslint: 8.46.0 dev: true - /eslint-plugin-standard@5.0.0(eslint@8.44.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.44.0 - dev: true - /eslint-plugin-tsdoc@0.2.17: resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} dependencies: @@ -9008,16 +8228,6 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils@3.0.0(eslint@8.44.0): - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.44.0 - eslint-visitor-keys: 2.1.0 - dev: true - /eslint-utils@3.0.0(eslint@8.46.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} @@ -9043,54 +8253,6 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.44.0: - resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) - '@eslint-community/regexpp': 4.6.2 - '@eslint/eslintrc': 2.1.1 - '@eslint/js': 8.44.0 - '@humanwhocodes/config-array': 0.11.10 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.2 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.20.0 - graphemer: 1.4.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - /eslint@8.46.0: resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -9357,18 +8519,6 @@ packages: jest-message-util: 27.5.1 dev: true - /expect@29.6.2: - resolution: {integrity: sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.6.2 - '@types/node': 20.5.8 - jest-get-type: 29.4.3 - jest-matcher-utils: 29.6.2 - jest-message-util: 29.6.2 - jest-util: 29.6.2 - dev: true - /exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} dev: false @@ -9498,11 +8648,6 @@ packages: strnum: 1.0.5 dev: false - /fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - dev: true - /fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: @@ -9832,6 +8977,7 @@ 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==} @@ -10795,6 +9941,16 @@ packages: - supports-color dev: false + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + dev: false + /human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} @@ -10956,11 +10112,6 @@ packages: engines: {node: '>= 0.10'} dev: true - /interpret@3.1.1: - resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} - engines: {node: '>=10.13.0'} - dev: true - /invert-kv@1.0.0: resolution: {integrity: sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==} engines: {node: '>=0.10.0'} @@ -11623,14 +10774,6 @@ 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} @@ -11658,35 +10801,6 @@ packages: - supports-color dev: true - /jest-circus@29.6.2: - resolution: {integrity: sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.6.2 - '@jest/expect': 29.6.2 - '@jest/test-result': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.1 - is-generator-fn: 2.1.0 - jest-each: 29.6.2 - jest-matcher-utils: 29.6.2 - jest-message-util: 29.6.2 - jest-runtime: 29.6.2 - jest-snapshot: 29.6.2 - jest-util: 29.6.2 - p-limit: 3.1.0 - pretty-format: 29.6.2 - pure-rand: 6.0.2 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - 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} @@ -11717,35 +10831,6 @@ packages: - utf-8-validate dev: true - /jest-cli@29.6.2(@types/node@18.11.18): - resolution: {integrity: sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==} - 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.2 - '@jest/test-result': 29.6.2 - '@jest/types': 29.6.1 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - import-local: 3.1.0 - jest-config: 29.6.2(@types/node@18.11.18) - jest-util: 29.6.2 - jest-validate: 29.6.2 - prompts: 2.4.2 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - 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} @@ -11787,86 +10872,6 @@ packages: - utf-8-validate dev: true - /jest-config@29.6.2(@types/node@18.11.18): - resolution: {integrity: sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==} - 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.10 - '@jest/test-sequencer': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 18.11.18 - babel-jest: 29.6.2(@babel/core@7.22.10) - 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.2 - jest-environment-node: 29.6.2 - jest-get-type: 29.4.3 - jest-regex-util: 29.4.3 - jest-resolve: 29.6.2 - jest-runner: 29.6.2 - jest-util: 29.6.2 - jest-validate: 29.6.2 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.6.2 - slash: 3.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-config@29.6.2(@types/node@20.5.8): - resolution: {integrity: sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==} - 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.10 - '@jest/test-sequencer': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - babel-jest: 29.6.2(@babel/core@7.22.10) - 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.2 - jest-environment-node: 29.6.2 - jest-get-type: 29.4.3 - jest-regex-util: 29.4.3 - jest-resolve: 29.6.2 - jest-runner: 29.6.2 - jest-util: 29.6.2 - jest-validate: 29.6.2 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.6.2 - slash: 3.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - babel-plugin-macros - - 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} @@ -11894,13 +10899,6 @@ 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} @@ -11912,17 +10910,6 @@ packages: pretty-format: 27.5.1 dev: true - /jest-each@29.6.2: - resolution: {integrity: sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - chalk: 4.1.2 - jest-get-type: 29.4.3 - jest-util: 29.6.2 - pretty-format: 29.6.2 - 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} @@ -11953,18 +10940,6 @@ packages: jest-util: 27.5.1 dev: true - /jest-environment-node@29.6.2: - resolution: {integrity: sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.6.2 - '@jest/fake-timers': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - jest-mock: 29.6.2 - jest-util: 29.6.2 - dev: true - /jest-fetch-mock@3.0.3: resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} dependencies: @@ -12004,25 +10979,6 @@ packages: fsevents: 2.3.2 dev: true - /jest-haste-map@29.6.2: - resolution: {integrity: sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - '@types/graceful-fs': 4.1.6 - '@types/node': 20.5.8 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.4.3 - jest-util: 29.6.2 - jest-worker: 29.6.2 - 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} @@ -12056,14 +11012,6 @@ packages: pretty-format: 27.5.1 dev: true - /jest-leak-detector@29.6.2: - resolution: {integrity: sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.4.3 - pretty-format: 29.6.2 - 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} @@ -12074,16 +11022,6 @@ packages: pretty-format: 27.5.1 dev: true - /jest-matcher-utils@29.6.2: - resolution: {integrity: sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.6.2 - jest-get-type: 29.4.3 - pretty-format: 29.6.2 - 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} @@ -12099,21 +11037,6 @@ packages: stack-utils: 2.0.6 dev: true - /jest-message-util@29.6.2: - resolution: {integrity: sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.22.10 - '@jest/types': 29.6.1 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.5 - pretty-format: 29.6.2 - 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} @@ -12122,15 +11045,6 @@ packages: '@types/node': 20.5.8 dev: true - /jest-mock@29.6.2: - resolution: {integrity: sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - jest-util: 29.6.2 - dev: true - /jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -12143,28 +11057,11 @@ packages: jest-resolve: 27.5.1 dev: true - /jest-pnp-resolver@1.2.3(jest-resolve@29.6.2): - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.6.2 - 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} @@ -12176,16 +11073,6 @@ packages: - supports-color dev: true - /jest-resolve-dependencies@29.6.2: - resolution: {integrity: sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.4.3 - jest-snapshot: 29.6.2 - 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} @@ -12202,21 +11089,6 @@ packages: slash: 3.0.0 dev: true - /jest-resolve@29.6.2: - resolution: {integrity: sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==} - 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.2 - jest-pnp-resolver: 1.2.3(jest-resolve@29.6.2) - jest-util: 29.6.2 - jest-validate: 29.6.2 - resolve: 1.22.4 - 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} @@ -12249,35 +11121,6 @@ packages: - utf-8-validate dev: true - /jest-runner@29.6.2: - resolution: {integrity: sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.6.2 - '@jest/environment': 29.6.2 - '@jest/test-result': 29.6.2 - '@jest/transform': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.4.3 - jest-environment-node: 29.6.2 - jest-haste-map: 29.6.2 - jest-leak-detector: 29.6.2 - jest-message-util: 29.6.2 - jest-resolve: 29.6.2 - jest-runtime: 29.6.2 - jest-util: 29.6.2 - jest-watcher: 29.6.2 - jest-worker: 29.6.2 - 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} @@ -12308,36 +11151,6 @@ packages: - supports-color dev: true - /jest-runtime@29.6.2: - resolution: {integrity: sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.6.2 - '@jest/fake-timers': 29.6.2 - '@jest/globals': 29.6.2 - '@jest/source-map': 29.6.0 - '@jest/test-result': 29.6.2 - '@jest/transform': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - chalk: 4.1.2 - cjs-module-lexer: 1.2.3 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.6.2 - jest-message-util: 29.6.2 - jest-mock: 29.6.2 - jest-regex-util: 29.4.3 - jest-resolve: 29.6.2 - jest-snapshot: 29.6.2 - jest-util: 29.6.2 - 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} @@ -12376,34 +11189,6 @@ packages: - supports-color dev: true - /jest-snapshot@29.6.2: - resolution: {integrity: sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.22.10 - '@babel/generator': 7.22.10 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.10) - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.10) - '@babel/types': 7.22.10 - '@jest/expect-utils': 29.6.2 - '@jest/transform': 29.6.2 - '@jest/types': 29.6.1 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) - chalk: 4.1.2 - expect: 29.6.2 - graceful-fs: 4.2.11 - jest-diff: 29.6.2 - jest-get-type: 29.4.3 - jest-matcher-utils: 29.6.2 - jest-message-util: 29.6.2 - jest-util: 29.6.2 - natural-compare: 1.4.0 - pretty-format: 29.6.2 - semver: 7.5.4 - 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} @@ -12416,18 +11201,6 @@ packages: picomatch: 2.3.1 dev: true - /jest-util@29.6.2: - resolution: {integrity: sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - 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} @@ -12440,18 +11213,6 @@ packages: pretty-format: 27.5.1 dev: true - /jest-validate@29.6.2: - resolution: {integrity: sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.1 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.4.3 - leven: 3.1.0 - pretty-format: 29.6.2 - 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} @@ -12465,20 +11226,6 @@ packages: string-length: 4.0.2 dev: true - /jest-watcher@29.6.2: - resolution: {integrity: sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.6.2 - '@jest/types': 29.6.1 - '@types/node': 20.5.8 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.6.2 - string-length: 4.0.2 - dev: true - /jest-websocket-mock@2.2.1(mock-socket@9.0.8): resolution: {integrity: sha512-fhsGLXrPfs06PhHoxqOSA9yZ6Rb4qYrf4Wcm7/nfRzjlrf1gIeuhYUkzMRjjE0TMQ37SwkmeLanwrZY4ZaNp8g==} peerDependencies: @@ -12497,26 +11244,6 @@ 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': 18.11.18 - jest-util: 29.6.2 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest-worker@29.6.2: - resolution: {integrity: sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 20.5.8 - jest-util: 29.6.2 - 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} @@ -12538,27 +11265,6 @@ 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.2 - '@jest/types': 29.6.1 - import-local: 3.1.0 - jest-cli: 29.6.2(@types/node@18.11.18) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - /jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true @@ -12779,10 +11485,6 @@ packages: semver: 7.5.4 dev: 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: @@ -13415,10 +12117,6 @@ packages: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} dev: true - /lodash@4.17.14: - resolution: {integrity: sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==} - dev: true - /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -13481,10 +12179,6 @@ 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'} @@ -13594,12 +12288,6 @@ 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'} @@ -13655,6 +12343,30 @@ packages: engines: {node: '>= 0.6'} dev: false + /megalodon@8.1.1: + resolution: {integrity: sha512-K7YjGmRbNkJao2E0hadJCW3IDloufVPUbYA/3+RFDFZvZO5v1MBz3rU4OixIgrHHY74PVTkSU8YHzyv7KA4rhA==} + engines: {node: '>=15.0.0'} + dependencies: + '@types/oauth': 0.9.2 + '@types/ws': 8.5.5 + axios: 1.5.1 + dayjs: 1.11.10 + form-data: 4.0.0 + https-proxy-agent: 7.0.2 + oauth: 0.10.0 + object-assign-deep: 0.4.0 + parse-link-header: 2.0.0 + socks-proxy-agent: 8.0.2 + typescript: 5.2.2 + uuid: 9.0.1 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: false + /meilisearch@0.34.1: resolution: {integrity: sha512-7mrLp88JfrbvhAMhOjNPzHGd2iCLHgzNhkveMxppMOToMLQw4Ygof4ksQ9uFi7SKq3UwEhIoMoFT1rUHLD3vWQ==} dependencies: @@ -15467,12 +14179,6 @@ packages: prettier: 2.8.8 dev: true - /prettier@2.8.3: - resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - /prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} @@ -15733,10 +14439,6 @@ 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.4.8: resolution: {integrity: sha512-/yNBs67VB4moPB7tqfupxFhYYaSlpnBpDb5995B0FP+vTqKwR2KD2uEIvch9NmpqUpVnsXcDOsFgmuGTgLX/Lg==} engines: {node: '>=14.19.0'} @@ -15991,13 +14693,6 @@ packages: resolve: 1.22.4 dev: true - /rechoir@0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - dependencies: - resolve: 1.22.4 - dev: true - /reconnecting-websocket@4.4.0: resolution: {integrity: sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==} dev: false @@ -16282,11 +14977,6 @@ 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: @@ -16600,13 +15290,6 @@ packages: crypt: 0.0.2 dev: true - /shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - /sharp@0.32.5: resolution: {integrity: sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ==} engines: {node: '>=14.15.0'} @@ -16644,14 +15327,6 @@ 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: @@ -16772,6 +15447,17 @@ packages: - supports-color dev: false + /socks-proxy-agent@8.0.2: + resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@8.1.1) + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: false + /socks@2.7.1: resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} @@ -16822,13 +15508,6 @@ packages: decode-uri-component: 0.2.2 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: @@ -17299,16 +15978,6 @@ packages: whet.extend: 0.9.9 dev: true - /swc-loader@0.2.3(@swc/core@1.3.78)(webpack@5.88.1): - resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} - peerDependencies: - '@swc/core': ^1.2.147 - webpack: '>=2' - dependencies: - '@swc/core': 1.3.78 - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - dev: true - /swc-loader@0.2.3(@swc/core@1.3.78)(webpack@5.88.2): resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} peerDependencies: @@ -17452,31 +16121,6 @@ packages: supports-hyperlinks: 2.3.0 dev: true - /terser-webpack-plugin@5.3.9(@swc/core@1.3.78)(webpack@5.88.1): - resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.19 - '@swc/core': 1.3.78 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.1 - terser: 5.19.2 - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - dev: true - /terser-webpack-plugin@5.3.9(@swc/core@1.3.78)(webpack@5.88.2): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} @@ -17800,40 +16444,6 @@ packages: yargs-parser: 20.2.9 dev: true - /ts-jest@29.0.5(@babel/core@7.22.10)(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.10 - 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.2 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.5.4 - typescript: 4.9.4 - yargs-parser: 21.1.1 - dev: true - /ts-loader@9.4.4(typescript@5.1.6)(webpack@5.88.2): resolution: {integrity: sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==} engines: {node: '>=12.0.0'} @@ -17967,16 +16577,6 @@ 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 - /tsutils@3.21.0(typescript@5.2.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -18099,20 +16699,6 @@ 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.17(ioredis@5.3.2)(pg@8.11.3)(ts-node@10.9.1): resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==} engines: {node: '>= 12.9.0'} @@ -18193,11 +16779,6 @@ packages: - supports-color dev: false - /typescript@4.9.4: - resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} - engines: {node: '>=4.2.0'} - hasBin: true - /typescript@5.0.4: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} @@ -18219,7 +16800,6 @@ packages: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true - dev: true /ulid@2.3.0: resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} @@ -18450,6 +17030,11 @@ packages: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -18462,15 +17047,6 @@ 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.19 - '@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'} @@ -18624,14 +17200,6 @@ 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-draggable-plus@0.2.6(@types/sortablejs@1.15.1): resolution: {integrity: sha512-d+0omKIBIfLiJFggc6H4ePRaifbX+33+OiCMsxn8rG59yWXlJGrobexxgXetnSo/1NLTd0TkYZKNc4CA6iwJZw==} peerDependencies: @@ -18800,93 +17368,11 @@ packages: engines: {node: '>=12'} dev: false - /webpack-cli@5.1.3(webpack@5.88.1): - resolution: {integrity: sha512-MTuk7NUMvEHQUSXCpvUrF1q2p0FJS40dPFfqQvG3jTWcgv/8plBNz2Kv2HXZiLGPnfmSAA5uCtCILO1JBmmkfw==} - engines: {node: '>=14.15.0'} - hasBin: true - peerDependencies: - '@webpack-cli/generators': '*' - webpack: 5.x.x - webpack-bundle-analyzer: '*' - webpack-dev-server: '*' - peerDependenciesMeta: - '@webpack-cli/generators': - optional: true - webpack-bundle-analyzer: - optional: true - webpack-dev-server: - optional: true - dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.3)(webpack@5.88.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.3)(webpack@5.88.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.3)(webpack@5.88.1) - colorette: 2.0.20 - commander: 10.0.1 - cross-spawn: 7.0.3 - envinfo: 7.10.0 - fastest-levenshtein: 1.0.16 - import-local: 3.1.0 - interpret: 3.1.1 - rechoir: 0.8.0 - webpack: 5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3) - webpack-merge: 5.9.0 - dev: true - - /webpack-merge@5.9.0: - resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==} - engines: {node: '>=10.0.0'} - dependencies: - clone-deep: 4.0.1 - wildcard: 2.0.1 - dev: true - /webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} dev: true - /webpack@5.88.1(@swc/core@1.3.78)(webpack-cli@5.1.3): - resolution: {integrity: sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.1 - '@webassemblyjs/ast': 1.11.6 - '@webassemblyjs/wasm-edit': 1.11.6 - '@webassemblyjs/wasm-parser': 1.11.6 - acorn: 8.10.0 - acorn-import-assertions: 1.9.0(acorn@8.10.0) - browserslist: 4.21.10 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.15.0 - es-module-lexer: 1.3.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.9(@swc/core@1.3.78)(webpack@5.88.1) - watchpack: 2.4.0 - webpack-cli: 5.1.3(webpack@5.88.1) - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - /webpack@5.88.2(@swc/core@1.3.78): resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} engines: {node: '>=10.13.0'} @@ -19035,10 +17521,6 @@ packages: string-width: 4.2.3 dev: false - /wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - dev: true - /with@7.0.2: resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} engines: {node: '>= 10.0.0'} @@ -19097,14 +17579,6 @@ 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} @@ -19126,19 +17600,6 @@ packages: optional: true dev: true - /ws@8.12.0: - resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - /ws@8.13.0: resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} engines: {node: '>=10.0.0'} @@ -19152,6 +17613,19 @@ packages: optional: true dev: true + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xev@3.0.2: resolution: {integrity: sha512-8kxuH95iMXzHZj+fwqfA4UrPcYOy6bGIgfWzo9Ji23JoEc30ge/Z++Ubkiuy8c0+M64nXmmxrmJ7C8wnuBhluw==} dev: false diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fd5cd65e6d..c70c008eaf 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,4 +4,3 @@ packages: - 'packages/client' - 'packages/sw' - 'packages/firefish-js' - - 'packages/megalodon' diff --git a/scripts/clean-all.js b/scripts/clean-all.js index e3394f4098..7beed3fe26 100644 --- a/scripts/clean-all.js +++ b/scripts/clean-all.js @@ -46,14 +46,6 @@ const { join } = require("node:path"); recursive: true, force: true, }); - fs.rmSync(join(__dirname, "/../packages/megalodon/lib"), { - recursive: true, - force: true, - }); - fs.rmSync(join(__dirname, "/../packages/megalodon/node_modules"), { - recursive: true, - force: true, - }); fs.rmSync(join(__dirname, "/../built"), { recursive: true, force: true }); fs.rmSync(join(__dirname, "/../node_modules"), { diff --git a/scripts/clean.js b/scripts/clean.js index 455c436285..e4ae085b4c 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -23,9 +23,5 @@ const { join } = require("node:path"); recursive: true, force: true, }); - fs.rmSync(join(__dirname, "/../packages/megalodon/lib"), { - recursive: true, - force: true, - }); fs.rmSync(join(__dirname, "/../built"), { recursive: true, force: true }); })();