From dd434a739b772b231056bcf94c3d8a6326a0497f Mon Sep 17 00:00:00 2001 From: naskya <m@naskya.net> Date: Sun, 9 Jul 2023 13:58:58 +0000 Subject: [PATCH 001/162] fix reactions_not_public condition --- packages/backend/src/server/api/endpoints/users/reactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 17b7a04a0..6b6d32e8a 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -49,7 +49,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneByOrFail({ userId: ps.userId }); - if (me == null || (me.id !== ps.userId && !profile.publicReactions)) { + if (me.id !== ps.userId && !profile.publicReactions) { throw new ApiError(meta.errors.reactionsNotPublic); } From 081a3177b8e22807ec2312b2ec262673b28c44a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= <git@mkljczk.pl> Date: Sun, 9 Jul 2023 18:22:53 +0200 Subject: [PATCH 002/162] Fix Mastodon compatibility string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak <git@mkljczk.pl> --- packages/backend/src/server/api/mastodon/endpoints/meta.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts index 2df4af82a..042071f0e 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/meta.ts @@ -1,4 +1,5 @@ import { Entity } from "megalodon"; +import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; import { Users, Notes } from "@/models/index.js"; import { IsNull, MoreThan } from "typeorm"; @@ -17,7 +18,7 @@ export async function getInstance(response: Entity.Instance) { response.description || "This is a vanilla Calckey Instance. It doesnt seem to have a description. BTW you are using the Mastodon api to access this server :)", email: response.email || "", - version: "3.0.0 compatible (3.5+ Calckey)", //I hope this version string is correct, we will need to test it. + version: `3.0.0 (compatible; Calckey ${config.version})`, urls: response.urls, stats: { user_count: await totalUsers, From 0d36fb9ea3f6f48ef6dd5df9688d149b6f2c9a77 Mon Sep 17 00:00:00 2001 From: sinofp <sinofp@tuta.io> Date: Sun, 9 Jul 2023 18:54:12 +0100 Subject: [PATCH 003/162] Implement speak-as-cat for Chinese and Greek MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Chinese meow character is 喵, whose pinyin is miāo. 妙, 庙, 描, 渺, 瞄, 秒, 苗, and 藐 are all the miao characters from *3500 commonly used Chinese characters.xls* @naskya proposed to include 廟 and να. Download the spreadsheet from https://faculty.blcu.edu.cn/xinghb/zh_CN/article/167473/content/1045.htm See the discussion at https://codeberg.org/calckey/calckey/issues/9746#issuecomment-974699 --- packages/backend/src/misc/nyaize.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index dd0c5bbdf..2b996c611 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,5 +20,9 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") + // Chinese + .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") + // Greek + .replaceAll("να", "νια") ); } From 52caeaacbba3c7d0a9071a134add03c10ff2b496 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sun, 9 Jul 2023 15:05:39 -0400 Subject: [PATCH 004/162] style: link underlines --- packages/client/src/components/MkUrlPreview.vue | 3 ++- packages/client/src/components/global/MkUrl.vue | 2 ++ packages/client/src/components/mfm.ts | 1 + packages/client/src/style.scss | 16 ++++++++++++---- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/MkUrlPreview.vue b/packages/client/src/components/MkUrlPreview.vue index 6452e135d..8fa8092b8 100644 --- a/packages/client/src/components/MkUrlPreview.vue +++ b/packages/client/src/components/MkUrlPreview.vue @@ -196,6 +196,7 @@ onUnmounted(() => { > a { display: flex; transition: background 0.2s; + text-decoration: none; > div:first-child:not(:last-child) { position: relative; width: 90px; @@ -277,7 +278,7 @@ onUnmounted(() => { &:focus, &:focus-within { background: var(--panelHighlight); - h1 { + h3 { text-decoration: underline; } } diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 98ba8d94e..3453bf5ed 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -80,6 +80,8 @@ const target = self ? null : "_blank"; display: inline-block; overflow: clip; text-overflow: ellipsis; + text-decoration: none !important; + line-height: 1.05; > .icon { padding-left: 2px; diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index cb0942a33..63465f38b 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -409,6 +409,7 @@ export default defineComponent({ key: Math.random(), to: `/tags/${encodeURIComponent(token.props.hashtag)}`, style: "color:var(--hashtag);", + class: "_link", }, `#${token.props.hashtag}`, ), diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index a6ef73015..be12f8b15 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -145,6 +145,9 @@ a { cursor: pointer; color: inherit; -webkit-tap-highlight-color: transparent; + &:hover { + text-decoration: underline; + } } // i { @@ -229,6 +232,7 @@ hr { font-size: 1em; font-family: inherit; line-height: inherit; + text-decoration: none; &, * { @@ -628,18 +632,22 @@ hr { ._link { position: relative; color: var(--link); + text-decoration: none !important; - &:after { + &::before, &::after { content: ""; position: absolute; bottom: 0; left: 0; width: 0%; - border-bottom: 2px solid var(--link); + border-bottom: 1px solid var(--link); transition: 0.3s ease-in-out; } - - &:hover:after { + &::before { + width: 100%; + opacity: .4; + } + &:hover:after, &:focus:after { width: 100%; } } From f7185169eddaf587af8739f686e10387a86779ec Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Sun, 9 Jul 2023 21:19:09 +0000 Subject: [PATCH 005/162] Nya-ify capital Greek alphabets --- packages/backend/src/misc/nyaize.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index 2b996c611..2ae3ceccd 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,9 +20,11 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") - // Chinese + // zh-CN, zh-TW .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") - // Greek + // el-GR .replaceAll("να", "νια") + .replaceAll("ΝΑ", "ΝΙΑ") + .replaceAll("Να", "Νια") ); } From 9bb8abce73dcc272eb07d617c55c339626f816ce Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 21:27:09 +0200 Subject: [PATCH 006/162] [mastodon-client] fix poll notifications --- packages/megalodon/src/misskey/api_client.ts | 13 +++++++++---- packages/megalodon/src/misskey/notification.ts | 2 +- packages/megalodon/src/notification.ts | 3 +-- packages/megalodon/test/integration/misskey.spec.ts | 4 ++-- .../megalodon/test/unit/misskey/api_client.spec.ts | 8 ++++---- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 34e11784e..813ffe08a 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -396,8 +396,8 @@ namespace MisskeyAPI { return MisskeyNotificationType.Reaction case NotificationType.Reblog: return MisskeyNotificationType.Renote - case NotificationType.PollVote: - return MisskeyNotificationType.PollVote + case NotificationType.Poll: + return MisskeyNotificationType.PollEnded case NotificationType.FollowRequest: return MisskeyNotificationType.ReceiveFollowRequest default: @@ -417,8 +417,8 @@ namespace MisskeyAPI { return NotificationType.Reblog case MisskeyNotificationType.Reaction: return NotificationType.EmojiReaction - case MisskeyNotificationType.PollVote: - return NotificationType.PollVote + case MisskeyNotificationType.PollEnded: + return NotificationType.Poll case MisskeyNotificationType.ReceiveFollowRequest: return NotificationType.FollowRequest case MisskeyNotificationType.FollowRequestAccepted: @@ -458,6 +458,11 @@ namespace MisskeyAPI { 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, { diff --git a/packages/megalodon/src/misskey/notification.ts b/packages/megalodon/src/misskey/notification.ts index 9cf3dc58a..e44b6159c 100644 --- a/packages/megalodon/src/misskey/notification.ts +++ b/packages/megalodon/src/misskey/notification.ts @@ -7,7 +7,7 @@ namespace MisskeyNotificationType { export const Renote: MisskeyEntity.NotificationType = 'renote' export const Quote: MisskeyEntity.NotificationType = 'quote' export const Reaction: MisskeyEntity.NotificationType = 'favourite' - export const PollVote: MisskeyEntity.NotificationType = 'pollVote' + export const PollEnded: MisskeyEntity.NotificationType = 'pollEnded' export const ReceiveFollowRequest: MisskeyEntity.NotificationType = 'receiveFollowRequest' export const FollowRequestAccepted: MisskeyEntity.NotificationType = 'followRequestAccepted' export const GroupInvited: MisskeyEntity.NotificationType = 'groupInvited' diff --git a/packages/megalodon/src/notification.ts b/packages/megalodon/src/notification.ts index 9ea3898c6..8e8c13579 100644 --- a/packages/megalodon/src/notification.ts +++ b/packages/megalodon/src/notification.ts @@ -8,8 +8,7 @@ namespace NotificationType { export const EmojiReaction: Entity.NotificationType = 'emoji_reaction' export const FollowRequest: Entity.NotificationType = 'follow_request' export const Status: Entity.NotificationType = 'status' - export const PollVote: Entity.NotificationType = 'poll_vote' - export const PollExpired: Entity.NotificationType = 'poll_expired' + export const Poll: Entity.NotificationType = 'poll' } export default NotificationType diff --git a/packages/megalodon/test/integration/misskey.spec.ts b/packages/megalodon/test/integration/misskey.spec.ts index 754f6cc28..49d39a097 100644 --- a/packages/megalodon/test/integration/misskey.spec.ts +++ b/packages/megalodon/test/integration/misskey.spec.ts @@ -93,7 +93,7 @@ const pollVote: MisskeyEntity.Notification = { createdAt: '2021-02-01T01:49:29', userId: user.id, user: user, - type: MisskeyNotificationType.PollVote, + type: MisskeyNotificationType.PollEnded, note: note } @@ -168,7 +168,7 @@ describe('getNotifications', () => { }, { event: pollVote, - expected: MegalodonNotificationType.PollVote, + expected: MegalodonNotificationType.Poll, title: 'pollVote' }, { diff --git a/packages/megalodon/test/unit/misskey/api_client.spec.ts b/packages/megalodon/test/unit/misskey/api_client.spec.ts index acaac39ca..b8e1df048 100644 --- a/packages/megalodon/test/unit/misskey/api_client.spec.ts +++ b/packages/megalodon/test/unit/misskey/api_client.spec.ts @@ -42,8 +42,8 @@ describe('api_client', () => { dist: MisskeyNotificationType.Renote }, { - src: MegalodonNotificationType.PollVote, - dist: MisskeyNotificationType.PollVote + src: MegalodonNotificationType.Poll, + dist: MisskeyNotificationType.PollEnded }, { src: MegalodonNotificationType.FollowRequest, @@ -83,8 +83,8 @@ describe('api_client', () => { dist: MegalodonNotificationType.EmojiReaction }, { - src: MisskeyNotificationType.PollVote, - dist: MegalodonNotificationType.PollVote + src: MisskeyNotificationType.PollEnded, + dist: MegalodonNotificationType.Poll }, { src: MisskeyNotificationType.ReceiveFollowRequest, From b4d52ee24cfee021b113ea2836568637f5f1cc0c Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 21:47:49 +0200 Subject: [PATCH 007/162] [mastodon-client] populate user details for notifications --- packages/megalodon/src/misskey.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index dbf3471c0..1c15acf38 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1236,6 +1236,8 @@ export default class Misskey implements MegalodonInterface { 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; } From 8d988e645677b2fd7931377a69b17a633b32d3f9 Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 22:59:04 +0200 Subject: [PATCH 008/162] [mastodon-client] fix posting polls --- .../server/api/mastodon/endpoints/status.ts | 19 +++++++++++++++++++ packages/megalodon/src/misskey.ts | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 76057ef0a..1bff3aa4c 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -67,6 +67,25 @@ export function apiStatusMastodon(router: Router): void { const { sensitive } = body; body.sensitive = typeof sensitive === "string" ? sensitive === "true" : sensitive; + + if (body.poll) { + if ( + body.poll.expires_in != null && + typeof body.poll.expires_in === "string" + ) + body.poll.expires_in = parseInt(body.poll.expires_in); + if ( + body.poll.multiple != null && + typeof body.poll.multiple === "string" + ) + body.poll.multiple = body.poll.multiple == "true"; + if ( + body.poll.hide_totals != null && + typeof body.poll.hide_totals === "string" + ) + body.poll.hide_totals = body.poll.hide_totals == "true"; + } + const data = await client.postStatus(text, body); ctx.body = convertStatus(data.data); } catch (e: any) { diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 1c15acf38..7ff802dc8 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1169,7 +1169,7 @@ export default class Misskey implements MegalodonInterface { let pollParam = { choices: options.poll.options, expiresAt: null, - expiredAfter: options.poll.expires_in + expiredAfter: options.poll.expires_in * 1000 } if (options.poll.multiple !== undefined) { pollParam = Object.assign(pollParam, { From 02bc972b2a9e79a7bdf885f0ce5eac35b695da2d Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 23:35:07 +0200 Subject: [PATCH 009/162] [server/api/notes/show] return correct status code --- packages/backend/src/server/api/endpoints/notes/show.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index 39d128134..8c5f91c5c 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -21,6 +21,7 @@ export const meta = { message: "No such note.", code: "NO_SUCH_NOTE", id: "24fcbfc6-2e37-42b6-8388-c29b3861a08d", + httpStatusCode: 404, }, }, } as const; From 3a9e917e2e963f7e5ecf0132b0ee5d41b204942d Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 23:39:48 +0200 Subject: [PATCH 010/162] [mastodon-client] return 404 instead of 401 on NO_SUCH_NOTE --- packages/backend/src/server/api/mastodon/endpoints/status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 1bff3aa4c..caa9d1d68 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -105,7 +105,7 @@ export function apiStatusMastodon(router: Router): void { ctx.body = convertStatus(data.data); } catch (e: any) { console.error(e); - ctx.status = 401; + ctx.status = ctx.status == 404 ? 404 : 401; ctx.body = e.response.data; } }); From 0529576277e55efb315fc28f6005bf7fffb8ed3d Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Sun, 9 Jul 2023 23:53:15 +0200 Subject: [PATCH 011/162] [mastodon-client] enforce limits for favorites and bookmarks --- packages/megalodon/src/misskey.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 7ff802dc8..fd765b3dc 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -408,7 +408,7 @@ export default class Misskey implements MegalodonInterface { if (options) { if (options.limit) { params = Object.assign(params, { - limit: options.limit + limit: options.limit <= 100 ? options.limit : 100 }) } if (options.max_id) { @@ -738,7 +738,7 @@ export default class Misskey implements MegalodonInterface { if (options) { if (options.limit) { params = Object.assign(params, { - limit: options.limit + limit: options.limit <= 100 ? options.limit : 100 }) } else { From 0518683b5ec21ba6a38a05e45eb3030c670f199d Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Mon, 10 Jul 2023 00:05:52 +0200 Subject: [PATCH 012/162] [mastodon-client] return actual status bookmark state --- packages/megalodon/src/misskey.ts | 8 ++++++++ packages/megalodon/src/misskey/api_client.ts | 3 ++- packages/megalodon/src/misskey/entities/state.ts | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 packages/megalodon/src/misskey/entities/state.ts diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index fd765b3dc..026b8e9b7 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1243,9 +1243,17 @@ export default class Misskey implements MegalodonInterface { public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise<MegalodonEntity.Status> { 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<boolean> { + return this.client + .post<MisskeyAPI.Entity.State>('/api/notes/state', { + noteId: id + }).then(p => p.data.isFavorited ?? false); + } + public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise<Entity.Status> { 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; diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 813ffe08a..f80d5a442 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -40,7 +40,8 @@ namespace MisskeyAPI { export type GetAll = MisskeyEntity.GetAll export type UserKey = MisskeyEntity.UserKey export type Session = MisskeyEntity.Session - export type Stats = MisskeyEntity.Stats + export type Stats = MisskeyEntity.Stats + export type State = MisskeyEntity.State export type APIEmoji = { emojis: Emoji[] } } diff --git a/packages/megalodon/src/misskey/entities/state.ts b/packages/megalodon/src/misskey/entities/state.ts new file mode 100644 index 000000000..4538fb461 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/state.ts @@ -0,0 +1,7 @@ +namespace MisskeyEntity { + export type State = { + isFavorited: boolean + isMutedThread: boolean + isWatching: boolean + } +} From d678d4729befcc8c1749fb90941a9b772757ca6e Mon Sep 17 00:00:00 2001 From: jolupa <jolupameister@gmail.com> Date: Sat, 8 Jul 2023 22:48:22 +0000 Subject: [PATCH 013/162] chore: Translated using Weblate (Catalan) Currently translated at 100.0% (1819 of 1819 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ca/ --- locales/ca-ES.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 6cda10f96..1f291ac22 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -2144,3 +2144,6 @@ _skinTones: swipeOnMobile: Permet lliscar entre pàgines enableIdenticonGeneration: Habilitar la generació d'Identicon enableServerMachineStats: Habilitar les estadístiques del maquinari del servidor +showPopup: Notificar els usuaris amb una finestra emergent +showWithSparkles: Mostra amb espurnes +youHaveUnreadAnnouncements: Tens anuncis sense llegir From 1a482447b0234b0f60cd81afb99ffd09d2c64d33 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sun, 9 Jul 2023 21:59:57 -0400 Subject: [PATCH 014/162] Isolate text directions in posts --- packages/client/src/components/MkSubNoteContent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkSubNoteContent.vue b/packages/client/src/components/MkSubNoteContent.vue index 586c3678c..34ee945ad 100644 --- a/packages/client/src/components/MkSubNoteContent.vue +++ b/packages/client/src/components/MkSubNoteContent.vue @@ -35,7 +35,7 @@ /> </p> <div class="wrmlmaau"> - <div + <bdi class="content" :class="{ collapsed, @@ -154,7 +154,7 @@ v-model="showContent" :note="note" /> - </div> + </bdi> <MkButton v-if="hasMfm && defaultStore.state.animatedMfm" @click.stop="toggleMfm" From 1924823fbfda34d70ebeea86edb03a5ff06b1b8f Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 19:54:33 -0700 Subject: [PATCH 015/162] build: :zap: parallel build (pnpm 8.6.7) --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ec899739f..defe75bb3 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "type": "git", "url": "https://codeberg.org/calckey/calckey.git" }, - "packageManager": "pnpm@8.6.6", + "packageManager": "pnpm@8.6.7", "private": true, "scripts": { - "rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", - "build": "pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", + "rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp", + "build": "pnpm node ./scripts/build-greet.js && pnpm -r --parallel run build && pnpm run gulp", "start": "pnpm --filter backend run start", "start:test": "pnpm --filter backend run start:test", "init": "pnpm run migrate", @@ -21,13 +21,13 @@ "watch": "pnpm run dev", "dev": "pnpm node ./scripts/dev.js", "dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start", - "lint": "pnpm -r run lint", + "lint": "pnpm -r --parallel run lint", "cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts", "cy:run": "cypress run", "e2e": "start-server-and-test start:test http://localhost:61812 cy:run", "mocha": "pnpm --filter backend run mocha", "test": "pnpm run mocha", - "format": "pnpm -r run format", + "format": "pnpm -r --parallel run format", "clean": "pnpm node ./scripts/clean.js", "clean-all": "pnpm node ./scripts/clean-all.js", "cleanall": "pnpm run clean-all" From ddf067941e9d34b2724812d6c0820ce9a6371fdc Mon Sep 17 00:00:00 2001 From: Kainoa Kanter <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 02:59:16 +0000 Subject: [PATCH 016/162] revert 4795a501626414c898e8b9792431d96daff4c74a revert Isolate text directions in posts --- packages/client/src/components/MkSubNoteContent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkSubNoteContent.vue b/packages/client/src/components/MkSubNoteContent.vue index 34ee945ad..586c3678c 100644 --- a/packages/client/src/components/MkSubNoteContent.vue +++ b/packages/client/src/components/MkSubNoteContent.vue @@ -35,7 +35,7 @@ /> </p> <div class="wrmlmaau"> - <bdi + <div class="content" :class="{ collapsed, @@ -154,7 +154,7 @@ v-model="showContent" :note="note" /> - </bdi> + </div> <MkButton v-if="hasMfm && defaultStore.state.animatedMfm" @click.stop="toggleMfm" From 21011fa2ea7b97f68042b8ab505fc941cbf297b2 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:00:55 -0700 Subject: [PATCH 017/162] Revert "Isolate text directions in posts" This reverts commit 4795a501626414c898e8b9792431d96daff4c74a. --- packages/client/src/components/MkSubNoteContent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkSubNoteContent.vue b/packages/client/src/components/MkSubNoteContent.vue index 34ee945ad..586c3678c 100644 --- a/packages/client/src/components/MkSubNoteContent.vue +++ b/packages/client/src/components/MkSubNoteContent.vue @@ -35,7 +35,7 @@ /> </p> <div class="wrmlmaau"> - <bdi + <div class="content" :class="{ collapsed, @@ -154,7 +154,7 @@ v-model="showContent" :note="note" /> - </bdi> + </div> <MkButton v-if="hasMfm && defaultStore.state.animatedMfm" @click.stop="toggleMfm" From 1296516160ed8e41216ec5a395fb21a837289d32 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:01:01 -0700 Subject: [PATCH 018/162] Revert "style: link underlines" This reverts commit 46d97d49a2298c1b8c1537ef1ed3eff376b49285. --- packages/client/src/components/MkUrlPreview.vue | 3 +-- packages/client/src/components/global/MkUrl.vue | 2 -- packages/client/src/components/mfm.ts | 1 - packages/client/src/style.scss | 16 ++++------------ 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/packages/client/src/components/MkUrlPreview.vue b/packages/client/src/components/MkUrlPreview.vue index 8fa8092b8..6452e135d 100644 --- a/packages/client/src/components/MkUrlPreview.vue +++ b/packages/client/src/components/MkUrlPreview.vue @@ -196,7 +196,6 @@ onUnmounted(() => { > a { display: flex; transition: background 0.2s; - text-decoration: none; > div:first-child:not(:last-child) { position: relative; width: 90px; @@ -278,7 +277,7 @@ onUnmounted(() => { &:focus, &:focus-within { background: var(--panelHighlight); - h3 { + h1 { text-decoration: underline; } } diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 3453bf5ed..98ba8d94e 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -80,8 +80,6 @@ const target = self ? null : "_blank"; display: inline-block; overflow: clip; text-overflow: ellipsis; - text-decoration: none !important; - line-height: 1.05; > .icon { padding-left: 2px; diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index 63465f38b..cb0942a33 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -409,7 +409,6 @@ export default defineComponent({ key: Math.random(), to: `/tags/${encodeURIComponent(token.props.hashtag)}`, style: "color:var(--hashtag);", - class: "_link", }, `#${token.props.hashtag}`, ), diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index be12f8b15..a6ef73015 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -145,9 +145,6 @@ a { cursor: pointer; color: inherit; -webkit-tap-highlight-color: transparent; - &:hover { - text-decoration: underline; - } } // i { @@ -232,7 +229,6 @@ hr { font-size: 1em; font-family: inherit; line-height: inherit; - text-decoration: none; &, * { @@ -632,22 +628,18 @@ hr { ._link { position: relative; color: var(--link); - text-decoration: none !important; - &::before, &::after { + &:after { content: ""; position: absolute; bottom: 0; left: 0; width: 0%; - border-bottom: 1px solid var(--link); + border-bottom: 2px solid var(--link); transition: 0.3s ease-in-out; } - &::before { - width: 100%; - opacity: .4; - } - &:hover:after, &:focus:after { + + &:hover:after { width: 100%; } } From e586331859ef67c81e3faf26c82cd4c375182b19 Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Mon, 10 Jul 2023 03:05:27 +0000 Subject: [PATCH 019/162] revert Chinese cat mode for now https://codeberg.org/calckey/calckey/issues/9746#issuecomment-978014 --- packages/backend/src/misc/nyaize.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index 2ae3ceccd..13a112ce5 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,8 +20,6 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") - // zh-CN, zh-TW - .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") // el-GR .replaceAll("να", "νια") .replaceAll("ΝΑ", "ΝΙΑ") From 0a4a16518b5e417441ce94cbb0af286bef4a1e3e Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:12:13 -0700 Subject: [PATCH 020/162] Revert "[mastodon-client] send proper user preferences" This reverts commit 3fe156f79578d8506cfbb70f3f6f806f50a818b9. --- packages/megalodon/src/misskey.ts | 24 +++++++++++++++----- packages/megalodon/src/misskey/api_client.ts | 4 ++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 026b8e9b7..b4a9c6adb 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1079,11 +1079,23 @@ export default class Misskey implements MegalodonInterface { // accounts/preferences // ====================================== public async getPreferences(): Promise<Response<Entity.Preferences>> { - return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(async res => { - return Object.assign(res, { - data: this.converter.userPreferences(res.data, await this.getDefaultPostPrivacy()) - }) - }) + return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(res => { + /* + return this.client.post<MisskeyAPI.Entity.GetAll>('/api/i/registry/get-all', { + scope: ['client', 'base'], + }).then(ga => { + return Object.assign(res, { + data: this.converter.userPreferences(res.data, ga.data) + }) + }) + */ + + // TODO: + // FIXME: get this from api + return Object.assign(res, { + data: this.converter.userPreferences(res.data, {defaultNoteVisibility: "followers", tutorial: -1}) + }) + }) } // ====================================== @@ -1527,7 +1539,7 @@ export default class Misskey implements MegalodonInterface { .then(res => res.data[0] ?? '⭐'); } - private async getDefaultPostPrivacy(): Promise<'public' | 'unlisted' | 'private' | 'direct'> { + private async getDefaultPostPrivacy(): Promise<string> { // 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. diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index f80d5a442..aabb1f3ee 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -175,13 +175,13 @@ namespace MisskeyAPI { } } - userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, v: 'public' | 'unlisted' | 'private' | 'direct'): MegalodonEntity.Preferences => { + userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll): MegalodonEntity.Preferences => { return { "reading:expand:media": "default", "reading:expand:spoilers": false, "posting:default:language": u.lang, "posting:default:sensitive": u.alwaysMarkNsfw, - "posting:default:visibility": v + "posting:default:visibility": this.visibility(g.defaultNoteVisibility) } } From b23d5bb16f246107b470e87a309ae4c285cb50c5 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:12:16 -0700 Subject: [PATCH 021/162] Revert "[mastodon-client] send actual default post privacy instead of fallback value" This reverts commit 81145570fcb458a9239f88fe9a273d6c2f1810d3. --- .../api/endpoints/i/registry/get-unsecure.ts | 2 +- .../server/api/mastodon/endpoints/account.ts | 2 +- packages/megalodon/src/misskey.ts | 17 ----------------- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts index a9bcf6935..f98c6c929 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts @@ -33,7 +33,7 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, user) => { - if (ps.key !== "reactions" && ps.key !== "defaultNoteVisibility") return; + if (ps.key !== "reactions") return; const query = RegistryItems.createQueryBuilder("item") .where("item.domain IS NULL") .andWhere("item.userId = :userId", { userId: user.id }) diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index 5d0abdedd..3fb1c9cbe 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -48,7 +48,7 @@ export function apiAccountMastodon(router: Router): void { acct.source = { note: acct.note, fields: acct.fields, - privacy: await client.getDefaultPostPrivacy(), + privacy: "public", sensitive: false, language: "", }; diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index b4a9c6adb..de62b9850 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1539,23 +1539,6 @@ export default class Misskey implements MegalodonInterface { .then(res => res.data[0] ?? '⭐'); } - private async getDefaultPostPrivacy(): Promise<string> { - // 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<string>('/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); - }); - } - public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> { // NOTE: Misskey allows only one reaction per status, so we don't need to care what that emoji was. return this.deleteEmojiReaction(id, ''); From 1da503eb11f9eb01d0c44c9779cee3c0d135f2e1 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:46:53 -0700 Subject: [PATCH 022/162] feat: :sparkles: Timestamps on announcements Closes #10453 --- packages/client/src/components/MkAnnouncement.vue | 11 +++++++++++ packages/client/src/pages/announcements.vue | 13 +++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkAnnouncement.vue b/packages/client/src/components/MkAnnouncement.vue index 24bf886dd..bd1091b7f 100644 --- a/packages/client/src/components/MkAnnouncement.vue +++ b/packages/client/src/components/MkAnnouncement.vue @@ -5,6 +5,13 @@ <MkSparkle v-if="isGoodNews">{{ title }}</MkSparkle> <p v-else>{{ title }}</p> </div> + <div :class="$style.time"> + <MkTime :time="announcement.createdAt" /> + <div v-if="announcement.updatedAt"> + {{ i18n.ts.updatedAt }}: + <MkTime :time="announcement.createdAt" /> + </div> + </div> <Mfm :text="text" /> <img v-if="imageUrl != null" @@ -68,6 +75,10 @@ const gotIt = () => { } } +.time { + font-size: 0.8rem; +} + .gotIt { margin: 8px 0 0 0; } diff --git a/packages/client/src/pages/announcements.vue b/packages/client/src/pages/announcements.vue index 8e9975020..cc62ce0f5 100644 --- a/packages/client/src/pages/announcements.vue +++ b/packages/client/src/pages/announcements.vue @@ -15,8 +15,13 @@ class="_card announcement" > <div class="_title"> - <span v-if="$i && !announcement.isRead">🆕 </span - >{{ announcement.title }} + <span v-if="$i && !announcement.isRead">🆕 </span> + <h3>{{ announcement.title }}</h3> + <MkTime :time="announcement.createdAt" /> + <div v-if="announcement.updatedAt"> + {{ i18n.ts.updatedAt }}: + <MkTime :time="announcement.createdAt" /> + </div> </div> <div class="_content"> <Mfm :text="announcement.text" /> @@ -76,6 +81,10 @@ definePageMetadata({ margin-bottom: var(--margin); } + > ._title { + padding: 14px 32px !important; + } + > ._content { > img { display: block; From 7a6c602bab9e0747c83e4eb4a7ceb0cf2a818238 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 20:46:58 -0700 Subject: [PATCH 023/162] chore: :art: format --- packages/client/src/components/MkMedia.vue | 10 +++++++--- packages/client/src/pages/user/home.vue | 13 +++++++------ packages/client/src/ui/_common_/navbar.vue | 11 +++++++---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/packages/client/src/components/MkMedia.vue b/packages/client/src/components/MkMedia.vue index d697054b6..4c023f131 100644 --- a/packages/client/src/components/MkMedia.vue +++ b/packages/client/src/components/MkMedia.vue @@ -226,11 +226,13 @@ watch( display: flex; min-width: max-content; width: 110px; - transition: width 0.2s cubic-bezier(0,0,0,1); + transition: width 0.2s cubic-bezier(0, 0, 0, 1); [data-plyr="volume"] { width: 0; flex-grow: 1; - transition: margin 0.3s, opacity .2s 0.2s; + transition: + margin 0.3s, + opacity 0.2s 0.2s; } &:not(:hover):not(:focus-within) { width: 0px; @@ -238,7 +240,9 @@ watch( [data-plyr="volume"] { margin-inline: 0px; opacity: 0; - transition: margin 0.3s, opacity 0.1s; + transition: + margin 0.3s, + opacity 0.1s; } } } diff --git a/packages/client/src/pages/user/home.vue b/packages/client/src/pages/user/home.vue index 5a8482fb8..e87052ea2 100644 --- a/packages/client/src/pages/user/home.vue +++ b/packages/client/src/pages/user/home.vue @@ -26,12 +26,13 @@ class="banner" :style="{ backgroundImage: `url('${user.bannerUrl}')`, - '--backgroundImageStatic': defaultStore - .state.useBlurEffect && user.bannerUrl - ? `url('${getStaticImageUrl( - user.bannerUrl, - )}')` - : null, + '--backgroundImageStatic': + defaultStore.state.useBlurEffect && + user.bannerUrl + ? `url('${getStaticImageUrl( + user.bannerUrl, + )}')` + : null, }" ></div> <div class="fade"></div> diff --git a/packages/client/src/ui/_common_/navbar.vue b/packages/client/src/ui/_common_/navbar.vue index e98aa738c..ef9f473f3 100644 --- a/packages/client/src/ui/_common_/navbar.vue +++ b/packages/client/src/ui/_common_/navbar.vue @@ -285,7 +285,8 @@ function more(ev: MouseEvent) { box-sizing: border-box; color: var(--navFg); - &:before, &.post::after { + &:before, + &.post::after { content: ""; display: block; width: calc(100% - 34px); @@ -342,7 +343,9 @@ function more(ev: MouseEvent) { &.active { color: var(--accent); opacity: 1; - transition: color 0.4s, opacity 0.4s; + transition: + color 0.4s, + opacity 0.4s; &::before { opacity: 1; } @@ -536,7 +539,6 @@ function more(ev: MouseEvent) { width: calc(100% - 32px); border-top: solid 0.5px var(--divider); } - } } .nav-item { @@ -571,7 +573,8 @@ function more(ev: MouseEvent) { width: 100%; height: 52px; margin-bottom: 16px; - &:before, &::after { + &:before, + &::after { inset: 0; margin: auto; width: 52px; From 0129fa68f0abe5ef06c44634e2a93e209cc97a06 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 9 Jul 2023 21:08:24 -0700 Subject: [PATCH 024/162] Revert "fix: nav post button gradient transition (#10401) + half refactor ?" This reverts commit 6031e11721d02c26afae99b800a483b5aa514e1a. --- packages/client/src/ui/_common_/navbar.vue | 410 ++++++++++++--------- 1 file changed, 229 insertions(+), 181 deletions(-) diff --git a/packages/client/src/ui/_common_/navbar.vue b/packages/client/src/ui/_common_/navbar.vue index ef9f473f3..7905c331c 100644 --- a/packages/client/src/ui/_common_/navbar.vue +++ b/packages/client/src/ui/_common_/navbar.vue @@ -26,7 +26,7 @@ <MkA v-click-anime v-tooltip.noDelay.right="i18n.ts.timeline" - class="nav-item index" + class="item index" active-class="active" to="/" exact @@ -46,7 +46,7 @@ v-tooltip.noDelay.right=" i18n.ts[navbarItemDef[item].title] " - class="nav-item _button" + class="item _button" :class="[item, { active: navbarItemDef[item].active }]" active-class="active" :to="navbarItemDef[item].to" @@ -66,9 +66,6 @@ <span v-if="navbarItemDef[item].indicated" class="indicator" - :class="{ - animateIndicator: $store.state.animation, - }" ><i class="icon ph-circle ph-fill"></i ></span> </component> @@ -78,7 +75,7 @@ v-if="$i.isAdmin || $i.isModerator" v-click-anime v-tooltip.noDelay.right="i18n.ts.controlPanel" - class="nav-item _button" + class="item _button" active-class="active" to="/admin" > @@ -91,7 +88,6 @@ updateAvailable " class="indicator" - :class="{ animateIndicator: $store.state.animation }" ></span ><i class="icon ph-door ph-bold ph-fw ph-lg"></i ><span class="text">{{ i18n.ts.controlPanel }}</span> @@ -99,24 +95,21 @@ <button v-click-anime v-tooltip.noDelay.right="i18n.ts.more" - class="nav-item _button" + class="item _button" @click="more" > <i class="icon ph-dots-three-outline ph-bold ph-fw ph-lg" ></i ><span class="text">{{ i18n.ts.more }}</span> - <span - v-if="otherMenuItemIndicated" - class="indicator" - :class="{ animateIndicator: $store.state.animation }" + <span v-if="otherMenuItemIndicated" class="indicator" ><i class="icon ph-circle ph-fill"></i ></span> </button> <MkA v-click-anime v-tooltip.noDelay.right="i18n.ts.settings" - class="nav-item _button" + class="item _button" active-class="active" to="/settings" > @@ -127,7 +120,7 @@ <div class="bottom"> <button v-tooltip.noDelay.right="i18n.ts.note" - class="nav-item _button post" + class="item _button post" data-cy-open-post-form @click="os.post" > @@ -224,7 +217,7 @@ function openAccountMenu(ev: MouseEvent) { { withExtraOperation: true, }, - ev, + ev ); } @@ -239,7 +232,7 @@ function more(ev: MouseEvent) { src: ev.currentTarget ?? ev.target, }, {}, - "closed", + "closed" ); } </script> @@ -272,128 +265,6 @@ function more(ev: MouseEvent) { flex-direction: column; } - .nav-item { - position: relative; - display: flex; - align-items: center; - padding-inline: 30px; - line-height: 2.85rem; - margin-bottom: 0.5rem; - white-space: nowrap; - width: 100%; - text-align: left; - box-sizing: border-box; - color: var(--navFg); - - &:before, - &.post::after { - content: ""; - display: block; - width: calc(100% - 34px); - height: 100%; - margin: auto; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-radius: 999px; - background: var(--accentedBg); - opacity: 0; - z-index: -2; - } - - > .icon { - position: relative; - width: 32px; - margin-right: 8px; - } - - > .indicator { - position: absolute; - top: 0; - left: 20px; - color: var(--navIndicator); - font-size: 8px; - } - - > .animateIndicator { - animation: blink 1s infinite; - } - > .text { - position: relative; - font-size: 0.9em; - overflow: hidden; - text-overflow: ellipsis; - } - - &:hover, - &:focus-within { - text-decoration: none; - color: var(--navHoverFg); - transition: color 0.4s ease; - } - - &.active { - color: var(--navActive); - } - - &:hover, - &:focus-within, - &.active { - color: var(--accent); - opacity: 1; - transition: - color 0.4s, - opacity 0.4s; - &::before { - opacity: 1; - } - } - } - .post { - padding-inline: 0; - color: var(--fgOnAccent); - font-weight: bold; - - &::before { - opacity: 1; - background: linear-gradient( - 90deg, - var(--buttonGradateA), - var(--buttonGradateB) - ); - } - &::after { - background: var(--accentLighten) !important; - opacity: 0; - z-index: -1; - transition: opacity 0.2s; - } - - &:hover, - &:focus-within, - &.active { - &::after { - opacity: 1; - } - } - - > .icon, - > .text { - position: relative; - left: 3rem; - margin: 0; - width: auto; - color: var(--fgOnAccent); - transform: translateY(0em); - } - - > .text { - margin-left: 1rem; - } - } - &:not(.iconOnly) { > .body { margin-left: -200px; @@ -434,6 +305,57 @@ function more(ev: MouseEvent) { > .bottom { padding: 20px 0; + > .post { + position: relative; + width: 100%; + height: 40px; + color: var(--fgOnAccent); + font-weight: bold; + text-align: left; + display: flex; + align-items: center; + + &:before { + content: ""; + display: block; + width: calc(100% - 38px); + height: 100%; + margin: auto; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 999px; + background: linear-gradient( + 90deg, + var(--buttonGradateA), + var(--buttonGradateB) + ); + } + + &:hover, + &:focus-within, + &.active { + &:before { + background: var(--accentLighten); + transition: all 0.4s ease; + } + } + + > .icon, + > .text { + position: relative; + left: 3rem; + color: var(--fgOnAccent); + transform: translateY(0em); + } + + > .text { + margin-left: 1rem; + } + } + > .instance { position: relative; display: block; @@ -471,6 +393,75 @@ function more(ev: MouseEvent) { margin: 16px 16px; border-top: solid 0.5px var(--divider); } + + > .item { + position: relative; + display: flex; + align-items: center; + padding-left: 30px; + line-height: 2.85rem; + margin-bottom: 0.5rem; + white-space: nowrap; + width: 100%; + text-align: left; + box-sizing: border-box; + color: var(--navFg); + + > .icon { + position: relative; + width: 32px; + margin-right: 8px; + } + + > .indicator { + position: absolute; + top: 0; + left: 20px; + color: var(--navIndicator); + font-size: 8px; + animation: blink 1s infinite; + } + + > .text { + position: relative; + font-size: 0.9em; + overflow: hidden; + text-overflow: ellipsis; + } + + &:hover, + &:focus-within { + text-decoration: none; + color: var(--navHoverFg); + transition: all 0.4s ease; + } + + &.active { + color: var(--navActive); + } + + &:hover, + &:focus-within, + &.active { + color: var(--accent); + transition: all 0.4s ease; + + &:before { + content: ""; + display: block; + width: calc(100% - 34px); + height: 100%; + margin: auto; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 999px; + background: var(--accentedBg); + } + } + } } } } @@ -502,6 +493,52 @@ function more(ev: MouseEvent) { > .bottom { padding: 20px 0; + > .post { + display: block; + position: relative; + width: 100%; + height: 52px; + margin-bottom: 16px; + text-align: center; + + &:before { + content: ""; + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + width: 52px; + aspect-ratio: 1/1; + border-radius: 100%; + background: linear-gradient( + 90deg, + var(--buttonGradateA), + var(--buttonGradateB) + ); + } + + &:hover, + &:focus-within, + &.active { + &:before { + background: var(--accentLighten); + transition: all 0.4s ease; + } + } + + > .icon { + position: relative; + color: var(--fgOnAccent); + } + + > .text { + display: none; + } + } + > .help { position: relative; display: block; @@ -539,57 +576,68 @@ function more(ev: MouseEvent) { width: calc(100% - 32px); border-top: solid 0.5px var(--divider); } - } - } - .nav-item { - padding: 1.1rem 0; - margin-bottom: 0.2rem; - text-align: center; - > .icon { - display: block; - margin: 0 auto; - opacity: 0.7; - transform: translateY(0em); - } + > .item { + display: block; + position: relative; + padding: 1.1rem 0; + margin-bottom: 0.2rem; + width: 100%; + text-align: center; - > .text { - display: none; - } + > .icon { + display: block; + margin: 0 auto; + opacity: 0.7; + transform: translateY(0em); + } - > .indicator { - position: absolute; - top: 6px; - left: 24px; - color: var(--navIndicator); - font-size: 8px; - } + > .text { + display: none; + } - > .animateIndicator { - animation: blink 1s infinite; - } - } - .post { - width: 100%; - height: 52px; - margin-bottom: 16px; - &:before, - &::after { - inset: 0; - margin: auto; - width: 52px; - aspect-ratio: 1/1; - } - > .icon { - left: unset; - } - > .text { - display: none; + > .indicator { + position: absolute; + top: 6px; + left: 24px; + color: var(--navIndicator); + font-size: 8px; + animation: blink 1s infinite; + } + + &:hover, + &:focus-within, + &.active { + text-decoration: none; + color: var(--accent); + transition: all 0.4s ease; + + &:before { + content: ""; + display: block; + height: 100%; + aspect-ratio: 1; + margin: auto; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 999px; + background: var(--accentedBg); + } + + > .icon, + > .text { + opacity: 1; + } + } + } } } } - .nav-item { + .item { outline: none; &:focus-visible:before { outline: auto; From 85fcb8b348e0f90b2ec280a0c26660c49fbcafbf Mon Sep 17 00:00:00 2001 From: Namekuji <nmkj@waah.day> Date: Mon, 10 Jul 2023 12:50:54 -0400 Subject: [PATCH 025/162] docs: fix typo --- docs/migrate.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/migrate.md b/docs/migrate.md index 7e9653e70..ae7df286a 100644 --- a/docs/migrate.md +++ b/docs/migrate.md @@ -83,9 +83,9 @@ NODE_ENV=production pnpm run migrate cd packages/backend LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)" -NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | nl)" +NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)" -for i in $(seq 1 $NUM_MIGRAIONS); do +for i in $(seq 1 $NUM_MIGRATIONS); do npx typeorm migration:revert -d ormconfig.js done From b0cf9c6faa2a68b3b983b16b50d03db21464a28a Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Mon, 10 Jul 2023 18:50:07 +0200 Subject: [PATCH 026/162] Revert "Revert "[mastodon-client] send actual default post privacy instead of fallback value"" This reverts commit a441cc6067c487c563bf673be261a179d96e0533. --- .../api/endpoints/i/registry/get-unsecure.ts | 2 +- .../server/api/mastodon/endpoints/account.ts | 2 +- packages/megalodon/src/misskey.ts | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts index f98c6c929..a9bcf6935 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-unsecure.ts @@ -33,7 +33,7 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, user) => { - if (ps.key !== "reactions") return; + if (ps.key !== "reactions" && ps.key !== "defaultNoteVisibility") return; const query = RegistryItems.createQueryBuilder("item") .where("item.domain IS NULL") .andWhere("item.userId = :userId", { userId: user.id }) diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index 3fb1c9cbe..5d0abdedd 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -48,7 +48,7 @@ export function apiAccountMastodon(router: Router): void { acct.source = { note: acct.note, fields: acct.fields, - privacy: "public", + privacy: await client.getDefaultPostPrivacy(), sensitive: false, language: "", }; diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index de62b9850..b4a9c6adb 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1539,6 +1539,23 @@ export default class Misskey implements MegalodonInterface { .then(res => res.data[0] ?? '⭐'); } + private async getDefaultPostPrivacy(): Promise<string> { + // 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<string>('/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); + }); + } + public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> { // NOTE: Misskey allows only one reaction per status, so we don't need to care what that emoji was. return this.deleteEmojiReaction(id, ''); From f57f2d868f35a01db40267c33be3e19448b91d0a Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Mon, 10 Jul 2023 18:50:12 +0200 Subject: [PATCH 027/162] Revert "Revert "[mastodon-client] send proper user preferences"" This reverts commit dfd9bd5dd106f27fc6dde09d80d40c07116ae517. --- packages/megalodon/src/misskey.ts | 24 +++++--------------- packages/megalodon/src/misskey/api_client.ts | 4 ++-- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index b4a9c6adb..026b8e9b7 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1079,23 +1079,11 @@ export default class Misskey implements MegalodonInterface { // accounts/preferences // ====================================== public async getPreferences(): Promise<Response<Entity.Preferences>> { - return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(res => { - /* - return this.client.post<MisskeyAPI.Entity.GetAll>('/api/i/registry/get-all', { - scope: ['client', 'base'], - }).then(ga => { - return Object.assign(res, { - data: this.converter.userPreferences(res.data, ga.data) - }) - }) - */ - - // TODO: - // FIXME: get this from api - return Object.assign(res, { - data: this.converter.userPreferences(res.data, {defaultNoteVisibility: "followers", tutorial: -1}) - }) - }) + return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(async res => { + return Object.assign(res, { + data: this.converter.userPreferences(res.data, await this.getDefaultPostPrivacy()) + }) + }) } // ====================================== @@ -1539,7 +1527,7 @@ export default class Misskey implements MegalodonInterface { .then(res => res.data[0] ?? '⭐'); } - private async getDefaultPostPrivacy(): Promise<string> { + 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. diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index aabb1f3ee..f80d5a442 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -175,13 +175,13 @@ namespace MisskeyAPI { } } - userPreferences = (u: MisskeyAPI.Entity.UserDetailMe, g: MisskeyAPI.Entity.GetAll): MegalodonEntity.Preferences => { + 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": this.visibility(g.defaultNoteVisibility) + "posting:default:visibility": v } } From a2d870a803f1d9c96138ed3e0587fadfebdc32cb Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Mon, 10 Jul 2023 18:05:34 +0200 Subject: [PATCH 028/162] [mastodon-client] userDetail: fallback to username if displayname is null --- packages/megalodon/src/misskey/api_client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index f80d5a442..1c198ecc9 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -156,7 +156,7 @@ namespace MisskeyAPI { id: u.id, username: u.username, acct: acct, - display_name: u.name, + display_name: u.name || u.username, locked: u.isLocked, created_at: u.createdAt, followers_count: u.followersCount, From b9ae9717f362a2fbad4a694e6a23944ed7738b41 Mon Sep 17 00:00:00 2001 From: Laura Hausmann <laura@hausmann.dev> Date: Mon, 10 Jul 2023 18:45:01 +0200 Subject: [PATCH 029/162] [mastodon-client] fix getDefaultPostPrivacy --- packages/megalodon/src/misskey.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 026b8e9b7..ca418439e 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1541,7 +1541,7 @@ export default class Misskey implements MegalodonInterface { 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<Response<Entity.Status>> { From 8f6d5c2d3d649197a3206263c8ef0c760355f951 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Mon, 10 Jul 2023 13:09:44 -0400 Subject: [PATCH 030/162] =?UTF-8?q?style:=20link=20underlines,=20attempt?= =?UTF-8?q?=20two=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/src/components/MkUrlPreview.vue | 8 ++++++-- .../client/src/components/global/MkUrl.vue | 2 ++ packages/client/src/style.scss | 19 +++++++++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/client/src/components/MkUrlPreview.vue b/packages/client/src/components/MkUrlPreview.vue index 6452e135d..73938cf86 100644 --- a/packages/client/src/components/MkUrlPreview.vue +++ b/packages/client/src/components/MkUrlPreview.vue @@ -196,6 +196,7 @@ onUnmounted(() => { > a { display: flex; transition: background 0.2s; + text-decoration: none; > div:first-child:not(:last-child) { position: relative; width: 90px; @@ -252,6 +253,9 @@ onUnmounted(() => { font-size: 1em; white-space: nowrap; margin-bottom: 0.2em; + text-decoration: underline; + text-decoration-color: transparent; + transition: text-decoration-color .2s; } p { margin-bottom: -0.5em; @@ -277,8 +281,8 @@ onUnmounted(() => { &:focus, &:focus-within { background: var(--panelHighlight); - h1 { - text-decoration: underline; + h3 { + text-decoration-color: currentColor; } } } diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 98ba8d94e..3453bf5ed 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -80,6 +80,8 @@ const target = self ? null : "_blank"; display: inline-block; overflow: clip; text-overflow: ellipsis; + text-decoration: none !important; + line-height: 1.05; > .icon { padding-left: 2px; diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index a6ef73015..7f3713881 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -145,6 +145,12 @@ a { cursor: pointer; color: inherit; -webkit-tap-highlight-color: transparent; + text-decoration: underline; + text-decoration-color: transparent; + transition: text-decoration-color .2s; + &:hover { + text-decoration-color: currentColor; + } } // i { @@ -229,6 +235,7 @@ hr { font-size: 1em; font-family: inherit; line-height: inherit; + text-decoration: none; &, * { @@ -628,18 +635,22 @@ hr { ._link { position: relative; color: var(--link); + text-decoration: none !important; - &:after { + &::before, &::after { content: ""; position: absolute; bottom: 0; left: 0; width: 0%; - border-bottom: 2px solid var(--link); + border-bottom: 1px solid currentColor; transition: 0.3s ease-in-out; } - - &:hover:after { + &::before { + width: 100%; + opacity: .4; + } + &:hover:after, &:focus:after { width: 100%; } } From aabbe7777d2f1f9f51cdc032e7523575ec9ed1ef Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 14:02:44 -0700 Subject: [PATCH 031/162] chore: :busts_in_silhouette: patrons --- patrons.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/patrons.json b/patrons.json index fbd46ee06..cf56fa839 100644 --- a/patrons.json +++ b/patrons.json @@ -86,6 +86,13 @@ "@irfan@calckey.social", "@dvd@dvd.chat", "@charlie2alpha@electricrequiem.com", + "@arndot@layer8.space", + "@ryan@c.ryanccn.dev", + "@lapastora_deprova@calckey.social", + "@rameez@calckey.social", + "@dracoling@firetribe.org", + "@Space6host@calckey.social", + "@zakalwe@plasmatrap.com", "\nInterkosmos Link" ] } From 51203b2bc1b53b48034cad0537448c0fe35ec740 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Mon, 10 Jul 2023 17:43:02 -0400 Subject: [PATCH 032/162] style: use muted repeat icon instead of forbidden for disabled boosts --- packages/client/src/components/MkNote.vue | 3 +++ packages/client/src/components/MkNoteSub.vue | 3 +++ packages/client/src/components/MkRenoteButton.vue | 9 +++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkNote.vue b/packages/client/src/components/MkNote.vue index a1a519f79..2f524c64a 100644 --- a/packages/client/src/components/MkNote.vue +++ b/packages/client/src/components/MkNote.vue @@ -869,6 +869,9 @@ defineExpose({ margin: 0; padding: 8px; opacity: 0.7; + &:disabled { + opacity: 0.5 !important; + } flex-grow: 1; max-width: 3.5em; width: max-content; diff --git a/packages/client/src/components/MkNoteSub.vue b/packages/client/src/components/MkNoteSub.vue index 113abefd6..9b7f1f5f5 100644 --- a/packages/client/src/components/MkNoteSub.vue +++ b/packages/client/src/components/MkNoteSub.vue @@ -477,6 +477,9 @@ function noteClick(e) { margin: 0; padding: 8px; opacity: 0.7; + &:disabled { + opacity: 0.5 !important; + } flex-grow: 1; max-width: 3.5em; width: max-content; diff --git a/packages/client/src/components/MkRenoteButton.vue b/packages/client/src/components/MkRenoteButton.vue index 15fd627fd..16a8b9536 100644 --- a/packages/client/src/components/MkRenoteButton.vue +++ b/packages/client/src/components/MkRenoteButton.vue @@ -10,8 +10,13 @@ <i class="ph-repeat ph-bold ph-lg"></i> <p v-if="count > 0 && !detailedView" class="count">{{ count }}</p> </button> - <button v-else class="eddddedb _button"> - <i class="ph-prohibit ph-bold ph-lg"></i> + <button + v-else + class="eddddedb _button" + disabled="true" + v-tooltip.noDelay.bottom="i18n.ts.disabled" + > + <i class="ph-repeat ph-bold ph-lg"></i> </button> </template> From d9c027e28672cc2820af44f8a748fccb64d563c6 Mon Sep 17 00:00:00 2001 From: PrivateGER <privateger@privateger.me> Date: Mon, 10 Jul 2023 23:44:31 +0200 Subject: [PATCH 033/162] Fix Postgres error loop when indexing notes --- .../processors/background/index-all-notes.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts index 1dce4406a..fc453eb26 100644 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ b/packages/backend/src/queue/processors/background/index-all-notes.ts @@ -1,4 +1,5 @@ import type Bull from "bull"; +import type { DoneCallback } from "bull"; import { queueLogger } from "../../logger.js"; import { Notes } from "@/models/index.js"; @@ -11,7 +12,7 @@ const logger = queueLogger.createSubLogger("index-all-notes"); export default async function indexAllNotes( job: Bull.Job<Record<string, unknown>>, - done: () => void, + done: DoneCallback, ): Promise<void> { logger.info("Indexing all notes..."); @@ -20,7 +21,7 @@ export default async function indexAllNotes( let total: number = (job.data.total as number) ?? 0; let running = true; - const take = 100000; + const take = 10000; const batch = 100; while (running) { logger.info( @@ -41,13 +42,14 @@ export default async function indexAllNotes( }, relations: ["user"], }); - } catch (e) { + } catch (e: any) { logger.error(`Failed to query notes ${e}`); - continue; + done(e); + break; } if (notes.length === 0) { - job.progress(100); + await job.progress(100); running = false; break; } @@ -55,7 +57,7 @@ export default async function indexAllNotes( try { const count = await Notes.count(); total = count; - job.update({ indexedCount, cursor, total }); + await job.update({indexedCount, cursor, total}); } catch (e) {} for (let i = 0; i < notes.length; i += batch) { @@ -69,12 +71,12 @@ export default async function indexAllNotes( indexedCount += chunk.length; const pct = (indexedCount / total) * 100; - job.update({ indexedCount, cursor, total }); - job.progress(+pct.toFixed(1)); + await job.update({ indexedCount, cursor, total }); + await job.progress(+pct.toFixed(1)); logger.info(`Indexed notes ${indexedCount}/${total ? total : "?"}`); } cursor = notes[notes.length - 1].id; - job.update({ indexedCount, cursor, total }); + await job.update({ indexedCount, cursor, total }); if (notes.length < take) { running = false; From 2bedc268858ad6783219c36deb846f2cad2afdcc Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Mon, 10 Jul 2023 19:02:31 -0400 Subject: [PATCH 034/162] style: don't truncate URL's --- .../client/src/components/MkUrlPreview.vue | 2 +- .../client/src/components/global/MkUrl.vue | 14 ++++--- packages/client/src/style.scss | 37 ++++++++++--------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/packages/client/src/components/MkUrlPreview.vue b/packages/client/src/components/MkUrlPreview.vue index 73938cf86..29d045ebf 100644 --- a/packages/client/src/components/MkUrlPreview.vue +++ b/packages/client/src/components/MkUrlPreview.vue @@ -255,7 +255,7 @@ onUnmounted(() => { margin-bottom: 0.2em; text-decoration: underline; text-decoration-color: transparent; - transition: text-decoration-color .2s; + transition: text-decoration-color 0.2s; } p { margin-bottom: -0.5em; diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 3453bf5ed..6e50c851e 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -75,13 +75,11 @@ const target = self ? null : "_blank"; <style lang="scss" scoped> .url { - white-space: nowrap; - max-width: 80%; - display: inline-block; - overflow: clip; - text-overflow: ellipsis; text-decoration: none !important; - line-height: 1.05; + > span { + text-decoration: underline var(--fgTransparent); + transition: text-decoration-color 0.2s; + } > .icon { padding-left: 2px; @@ -111,5 +109,9 @@ const target = self ? null : "_blank"; > .hash { font-style: italic; } + + &:hover span { + text-decoration-color: var(--link); + } } </style> diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index 7f3713881..a53f47f14 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -147,7 +147,7 @@ a { -webkit-tap-highlight-color: transparent; text-decoration: underline; text-decoration-color: transparent; - transition: text-decoration-color .2s; + transition: text-decoration-color 0.2s; &:hover { text-decoration-color: currentColor; } @@ -635,24 +635,25 @@ hr { ._link { position: relative; color: var(--link); - text-decoration: none !important; - &::before, &::after { - content: ""; - position: absolute; - bottom: 0; - left: 0; - width: 0%; - border-bottom: 1px solid currentColor; - transition: 0.3s ease-in-out; - } - &::before { - width: 100%; - opacity: .4; - } - &:hover:after, &:focus:after { - width: 100%; - } + // &::before, + // &::after { + // content: ""; + // position: absolute; + // bottom: 0; + // left: 0; + // width: 0%; + // border-bottom: 1px solid currentColor; + // transition: 0.3s ease-in-out; + // } + // &::before { + // width: 100%; + // opacity: 0.4; + // } + // &:hover:after, + // &:focus:after { + // width: 100%; + // } } ._caption { From 0f96f496657c62b73a9cc7e97584a48da1306aa0 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Mon, 10 Jul 2023 19:38:32 -0400 Subject: [PATCH 035/162] style: underline-offset tweak --- packages/client/src/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index a53f47f14..9df882ec7 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -635,6 +635,7 @@ hr { ._link { position: relative; color: var(--link); + text-underline-offset: 0.2em; // &::before, // &::after { From 5ad6dba98de2214e94db6611ee1c90abf9376429 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 21:09:07 -0700 Subject: [PATCH 036/162] perf: :zap: use fast-blurhash for blurhash decoding, up deps --- package.json | 12 +- .../processors/background/index-all-notes.ts | 2 +- packages/client/package.json | 35 +- .../src/components/MkImgWithBlurhash.vue | 6 +- .../extract-avg-color-from-blurhash.ts | 21 +- packages/client/src/ui/_common_/navbar.vue | 4 +- pnpm-lock.yaml | 751 +++++++++++------- 7 files changed, 484 insertions(+), 347 deletions(-) diff --git a/package.json b/package.json index defe75bb3..592788316 100644 --- a/package.json +++ b/package.json @@ -36,17 +36,17 @@ "chokidar": "^3.3.1" }, "dependencies": { - "@bull-board/api": "5.2.0", - "@bull-board/ui": "5.2.0", + "@bull-board/api": "5.6.0", + "@bull-board/ui": "5.6.0", "@napi-rs/cli": "^2.16.1", "@tensorflow/tfjs": "^3.21.0", "js-yaml": "4.1.0", "seedrandom": "^3.0.5" }, "devDependencies": { - "@types/node": "18.11.18", - "@types/gulp": "4.0.10", - "@types/gulp-rename": "2.0.1", + "@types/gulp": "4.0.13", + "@types/gulp-rename": "2.0.2", + "@types/node": "20.4.1", "chalk": "4.1.2", "cross-env": "7.0.3", "cypress": "10.11.0", @@ -59,6 +59,6 @@ "install-peers": "^1.0.4", "rome": "^12.1.3", "start-server-and-test": "1.15.2", - "typescript": "4.9.4" + "typescript": "5.1.6" } } diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts index fc453eb26..c0275b420 100644 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ b/packages/backend/src/queue/processors/background/index-all-notes.ts @@ -57,7 +57,7 @@ export default async function indexAllNotes( try { const count = await Notes.count(); total = count; - await job.update({indexedCount, cursor, total}); + await job.update({ indexedCount, cursor, total }); } catch (e) {} for (let i = 0; i < notes.length; i += batch) { diff --git a/packages/client/package.json b/packages/client/package.json index e34773ffe..81c252d66 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -16,7 +16,7 @@ "@syuilo/aiscript": "0.11.1", "@types/escape-regexp": "0.0.1", "@types/glob": "8.1.0", - "@types/gulp": "4.0.11", + "@types/gulp": "4.0.13", "@types/gulp-rename": "2.0.2", "@types/katex": "0.16.0", "@types/matter-js": "0.18.2", @@ -29,8 +29,8 @@ "@vue/compiler-sfc": "3.3.4", "autobind-decorator": "2.4.0", "autosize": "5.0.2", - "blurhash": "1.1.5", - "broadcast-channel": "4.19.1", + "blurhash": "2.0.5", + "broadcast-channel": "5.1.0", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", "calckey-js": "workspace:*", "chart.js": "4.3.0", @@ -39,51 +39,52 @@ "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.0.1", "city-timezones": "^1.2.1", - "compare-versions": "5.0.3", + "compare-versions": "6.0.0", "cropperjs": "2.0.0-beta.2", "cross-env": "7.0.3", "cypress": "10.11.0", "date-fns": "2.30.0", "emojilib": "github:thatonecalculator/emojilib", "escape-regexp": "0.0.1", - "eventemitter3": "4.0.7", - "focus-trap": "^7.4.3", + "eventemitter3": "5.0.1", + "fast-blurhash": "^1.1.2", + "focus-trap": "^7.5.2", "focus-trap-vue": "^4.0.2", - "gsap": "^3.11.5", + "gsap": "^3.12.2", "idb-keyval": "6.2.1", "insert-text-at-cursor": "0.3.0", "json5": "2.2.3", - "katex": "0.16.7", + "katex": "0.16.8", "matter-js": "0.18.0", "mfm-js": "0.23.3", - "photoswipe": "5.3.7", + "photoswipe": "5.3.8", "prettier": "3.0.0", "prettier-plugin-vue": "1.1.6", "prismjs": "1.29.0", - "punycode": "2.1.1", + "punycode": "2.3.0", "querystring": "0.2.1", "rndstr": "1.0.0", - "rollup": "3.23.1", + "rollup": "3.26.2", "s-age": "1.1.2", - "sass": "1.62.1", + "sass": "1.63.6", "seedrandom": "3.0.5", "start-server-and-test": "1.15.2", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "swiper": "9.3.2", + "swiper": "10.0.4", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", "three": "0.146.0", "throttle-debounce": "5.0.0", - "tinycolor2": "1.5.2", - "tsc-alias": "1.8.6", + "tinycolor2": "1.6.0", + "tsc-alias": "1.8.7", "tsconfig-paths": "4.2.0", "twemoji-parser": "14.0.0", - "typescript": "5.1.3", + "typescript": "5.1.6", "unicode-emoji-json": "^0.4.0", "uuid": "9.0.0", "vanilla-tilt": "1.8.0", - "vite": "4.3.9", + "vite": "4.4.2", "vite-plugin-compression": "^0.5.1", "vue": "3.3.4", "vue-isyourpasswordsafe": "^2.0.0", diff --git a/packages/client/src/components/MkImgWithBlurhash.vue b/packages/client/src/components/MkImgWithBlurhash.vue index 03e6ea503..5a0cefec2 100644 --- a/packages/client/src/components/MkImgWithBlurhash.vue +++ b/packages/client/src/components/MkImgWithBlurhash.vue @@ -21,7 +21,7 @@ <script lang="ts" setup> import { onMounted } from "vue"; -import { decode } from "blurhash"; +import { decodeBlurHash } from "fast-blurhash"; const props = withDefaults( defineProps<{ @@ -47,8 +47,8 @@ const canvas = $ref<HTMLCanvasElement>(); let loaded = $ref(false); function draw() { - if (props.hash == null) return; - const pixels = decode(props.hash, props.size, props.size); + if (props.hash == null || canvas == null) return; + const pixels = decodeBlurHash(props.hash, props.size, props.size); const ctx = canvas.getContext("2d"); const imageData = ctx!.createImageData(props.size, props.size); imageData.data.set(pixels); diff --git a/packages/client/src/scripts/extract-avg-color-from-blurhash.ts b/packages/client/src/scripts/extract-avg-color-from-blurhash.ts index 9f758cd6d..08e9972f4 100644 --- a/packages/client/src/scripts/extract-avg-color-from-blurhash.ts +++ b/packages/client/src/scripts/extract-avg-color-from-blurhash.ts @@ -1,13 +1,16 @@ +import { getBlurHashAverageColor } from "fast-blurhash"; + +function rgbToHex(rgb: number[]): string { + return `#${rgb + .map((x) => { + const hex = x.toString(16); + return hex.length === 1 ? `0${hex}` : hex; + }) + .join("")}`; +} + export function extractAvgColorFromBlurhash(hash: string) { return typeof hash === "string" - ? `#${[...hash.slice(2, 6)] - .map((x) => - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".indexOf( - x, - ), - ) - .reduce((a, c) => a * 83 + c, 0) - .toString(16) - .padStart(6, "0")}` + ? rgbToHex(getBlurHashAverageColor(hash)) : undefined; } diff --git a/packages/client/src/ui/_common_/navbar.vue b/packages/client/src/ui/_common_/navbar.vue index 7905c331c..17c05884d 100644 --- a/packages/client/src/ui/_common_/navbar.vue +++ b/packages/client/src/ui/_common_/navbar.vue @@ -217,7 +217,7 @@ function openAccountMenu(ev: MouseEvent) { { withExtraOperation: true, }, - ev + ev, ); } @@ -232,7 +232,7 @@ function more(ev: MouseEvent) { src: ev.currentTarget ?? ev.target, }, {}, - "closed" + "closed", ); } </script> diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b18c93854..8285d327c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,11 +12,11 @@ importers: .: dependencies: '@bull-board/api': - specifier: 5.2.0 - version: 5.2.0(@bull-board/ui@5.2.0) + specifier: 5.6.0 + version: 5.6.0(@bull-board/ui@5.6.0) '@bull-board/ui': - specifier: 5.2.0 - version: 5.2.0 + specifier: 5.6.0 + version: 5.6.0 '@napi-rs/cli': specifier: ^2.16.1 version: 2.16.1 @@ -31,14 +31,14 @@ importers: version: 3.0.5 devDependencies: '@types/gulp': - specifier: 4.0.10 - version: 4.0.10 + specifier: 4.0.13 + version: 4.0.13 '@types/gulp-rename': - specifier: 2.0.1 - version: 2.0.1 + specifier: 2.0.2 + version: 2.0.2 '@types/node': - specifier: 18.11.18 - version: 18.11.18 + specifier: 20.4.1 + version: 20.4.1 chalk: specifier: 4.1.2 version: 4.1.2 @@ -76,8 +76,8 @@ importers: specifier: 1.15.2 version: 1.15.2 typescript: - specifier: 4.9.4 - version: 4.9.4 + specifier: 5.1.6 + version: 5.1.6 packages/backend: dependencies: @@ -666,7 +666,7 @@ importers: version: 9.0.8 ts-jest: specifier: ^27.1.2 - version: 27.1.2(@babel/core@7.22.5)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3) + version: 27.1.2(@babel/core@7.22.8)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3) ts-node: specifier: 10.4.0 version: 10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3) @@ -687,10 +687,10 @@ importers: version: 2.0.3 '@rollup/plugin-alias': specifier: 3.1.9 - version: 3.1.9(rollup@3.23.1) + version: 3.1.9(rollup@3.26.2) '@rollup/plugin-json': specifier: 4.1.0 - version: 4.1.0(rollup@3.23.1) + version: 4.1.0(rollup@3.26.2) '@rollup/pluginutils': specifier: ^4.2.1 version: 4.2.1 @@ -704,8 +704,8 @@ importers: specifier: 8.1.0 version: 8.1.0 '@types/gulp': - specifier: 4.0.11 - version: 4.0.11 + specifier: 4.0.13 + version: 4.0.13 '@types/gulp-rename': specifier: 2.0.2 version: 2.0.2 @@ -732,7 +732,7 @@ importers: version: 8.3.4 '@vitejs/plugin-vue': specifier: 4.2.3 - version: 4.2.3(vite@4.3.9)(vue@3.3.4) + version: 4.2.3(vite@4.4.2)(vue@3.3.4) '@vue/compiler-sfc': specifier: 3.3.4 version: 3.3.4 @@ -743,11 +743,11 @@ importers: specifier: 5.0.2 version: 5.0.2 blurhash: - specifier: 1.1.5 - version: 1.1.5 + specifier: 2.0.5 + version: 2.0.5 broadcast-channel: - specifier: 4.19.1 - version: 4.19.1 + specifier: 5.1.0 + version: 5.1.0 browser-image-resizer: specifier: github:misskey-dev/browser-image-resizer version: github.com/misskey-dev/browser-image-resizer/56f504427ad7f6500e141a6d9f3aee42023d7f3e @@ -773,8 +773,8 @@ importers: specifier: ^1.2.1 version: 1.2.1 compare-versions: - specifier: 5.0.3 - version: 5.0.3 + specifier: 6.0.0 + version: 6.0.0 cropperjs: specifier: 2.0.0-beta.2 version: 2.0.0-beta.2 @@ -789,22 +789,25 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e + version: github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b escape-regexp: specifier: 0.0.1 version: 0.0.1 eventemitter3: - specifier: 4.0.7 - version: 4.0.7 + specifier: 5.0.1 + version: 5.0.1 + fast-blurhash: + specifier: ^1.1.2 + version: 1.1.2 focus-trap: - specifier: ^7.4.3 - version: 7.4.3 + specifier: ^7.5.2 + version: 7.5.2 focus-trap-vue: specifier: ^4.0.2 - version: 4.0.2(focus-trap@7.4.3)(vue@3.3.4) + version: 4.0.2(focus-trap@7.5.2)(vue@3.3.4) gsap: - specifier: ^3.11.5 - version: 3.11.5 + specifier: ^3.12.2 + version: 3.12.2 idb-keyval: specifier: 6.2.1 version: 6.2.1 @@ -815,8 +818,8 @@ importers: specifier: 2.2.3 version: 2.2.3 katex: - specifier: 0.16.7 - version: 0.16.7 + specifier: 0.16.8 + version: 0.16.8 matter-js: specifier: 0.18.0 version: 0.18.0 @@ -824,8 +827,8 @@ importers: specifier: 0.23.3 version: 0.23.3 photoswipe: - specifier: 5.3.7 - version: 5.3.7 + specifier: 5.3.8 + version: 5.3.8 prettier: specifier: 3.0.0 version: 3.0.0 @@ -836,8 +839,8 @@ importers: specifier: 1.29.0 version: 1.29.0 punycode: - specifier: 2.1.1 - version: 2.1.1 + specifier: 2.3.0 + version: 2.3.0 querystring: specifier: 0.2.1 version: 0.2.1 @@ -845,14 +848,14 @@ importers: specifier: 1.0.0 version: 1.0.0 rollup: - specifier: 3.23.1 - version: 3.23.1 + specifier: 3.26.2 + version: 3.26.2 s-age: specifier: 1.1.2 version: 1.1.2 sass: - specifier: 1.62.1 - version: 1.62.1 + specifier: 1.63.6 + version: 1.63.6 seedrandom: specifier: 3.0.5 version: 3.0.5 @@ -866,8 +869,8 @@ importers: specifier: 2.1.0 version: 2.1.0 swiper: - specifier: 9.3.2 - version: 9.3.2 + specifier: 10.0.4 + version: 10.0.4 syuilo-password-strength: specifier: 0.0.1 version: 0.0.1 @@ -881,11 +884,11 @@ importers: specifier: 5.0.0 version: 5.0.0 tinycolor2: - specifier: 1.5.2 - version: 1.5.2 + specifier: 1.6.0 + version: 1.6.0 tsc-alias: - specifier: 1.8.6 - version: 1.8.6 + specifier: 1.8.7 + version: 1.8.7 tsconfig-paths: specifier: 4.2.0 version: 4.2.0 @@ -893,8 +896,8 @@ importers: specifier: 14.0.0 version: 14.0.0 typescript: - specifier: 5.1.3 - version: 5.1.3 + specifier: 5.1.6 + version: 5.1.6 unicode-emoji-json: specifier: ^0.4.0 version: 0.4.0 @@ -905,11 +908,11 @@ importers: specifier: 1.8.0 version: 1.8.0 vite: - specifier: 4.3.9 - version: 4.3.9(@types/node@18.11.18)(sass@1.62.1) + specifier: 4.4.2 + version: 4.4.2(@types/node@20.4.1)(sass@1.63.6) vite-plugin-compression: specifier: ^0.5.1 - version: 0.5.1(vite@4.3.9) + version: 0.5.1(vite@4.4.2) vue: specifier: 3.3.4 version: 3.3.4 @@ -1039,7 +1042,7 @@ importers: version: 2.8.8 ts-jest: specifier: ^29.0.5 - version: 29.0.5(@babel/core@7.22.5)(jest@29.4.0)(typescript@4.9.4) + version: 29.0.5(@babel/core@7.22.8)(jest@29.4.0)(typescript@4.9.4) typedoc: specifier: ^0.23.24 version: 0.23.24(typescript@4.9.4) @@ -1094,6 +1097,11 @@ packages: resolution: {integrity: sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==} engines: {node: '>=6.9.0'} + /@babel/compat-data@7.22.6: + resolution: {integrity: sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/core@7.22.5: resolution: {integrity: sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==} engines: {node: '>=6.9.0'} @@ -1116,6 +1124,29 @@ packages: transitivePeerDependencies: - supports-color + /@babel/core@7.22.8: + resolution: {integrity: sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.5 + '@babel/generator': 7.22.7 + '@babel/helper-compilation-targets': 7.22.6(@babel/core@7.22.8) + '@babel/helper-module-transforms': 7.22.5 + '@babel/helpers': 7.22.6 + '@babel/parser': 7.22.7 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + '@nicolo-ribaudo/semver-v6': 6.3.3 + convert-source-map: 1.9.0 + debug: 4.3.4(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/generator@7.22.5: resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==} engines: {node: '>=6.9.0'} @@ -1125,6 +1156,16 @@ packages: '@jridgewell/trace-mapping': 0.3.18 jsesc: 2.5.2 + /@babel/generator@7.22.7: + resolution: {integrity: sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + jsesc: 2.5.2 + dev: true + /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==} engines: {node: '>=6.9.0'} @@ -1138,6 +1179,20 @@ packages: lru-cache: 5.1.1 semver: 6.3.0 + /@babel/helper-compilation-targets@7.22.6(@babel/core@7.22.8): + resolution: {integrity: sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.22.6 + '@babel/core': 7.22.8 + '@babel/helper-validator-option': 7.22.5 + '@nicolo-ribaudo/semver-v6': 6.3.3 + browserslist: 4.21.9 + lru-cache: 5.1.1 + dev: true + /@babel/helper-environment-visitor@7.22.5: resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} engines: {node: '>=6.9.0'} @@ -1192,6 +1247,13 @@ packages: dependencies: '@babel/types': 7.22.5 + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + /@babel/helper-string-parser@7.22.5: resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} engines: {node: '>=6.9.0'} @@ -1214,6 +1276,17 @@ packages: transitivePeerDependencies: - supports-color + /@babel/helpers@7.22.6: + resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/highlight@7.22.5: resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} engines: {node: '>=6.9.0'} @@ -1229,6 +1302,14 @@ packages: dependencies: '@babel/types': 7.22.5 + /@babel/parser@7.22.7: + resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.5 + dev: true + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.5): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} @@ -1392,8 +1473,8 @@ packages: - supports-color dev: false - /@babel/runtime@7.20.7: - resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==} + /@babel/runtime@7.21.0: + resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 @@ -1430,6 +1511,24 @@ packages: transitivePeerDependencies: - supports-color + /@babel/traverse@7.22.8: + resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.5 + '@babel/generator': 7.22.7 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.22.7 + '@babel/types': 7.22.5 + debug: 4.3.4(supports-color@8.1.1) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/types@7.22.5: resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} engines: {node: '>=6.9.0'} @@ -1451,6 +1550,15 @@ packages: redis-info: 3.1.0 dev: false + /@bull-board/api@5.6.0(@bull-board/ui@5.6.0): + resolution: {integrity: sha512-a2O15p5oEm+/E/0I2l2nE2NKK0dkgNNTaamu+0gGyfUxWoCS3fCGX6LLEyl3jgOz0IC3GKRnwtVgbZFzk42sGQ==} + peerDependencies: + '@bull-board/ui': 5.6.0 + dependencies: + '@bull-board/ui': 5.6.0 + redis-info: 3.1.0 + dev: false + /@bull-board/koa@5.2.0(@types/koa@2.13.5)(pug@3.0.2): resolution: {integrity: sha512-jntDAl/POouD0PS/iiKXBNl26SuUf7Y5uL3EgpDN7isvwFcpKhvdk0VdBypjrkRHN6rPaEJJPkEtK30qv01XYw==} dependencies: @@ -1525,6 +1633,12 @@ packages: '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) dev: false + /@bull-board/ui@5.6.0: + resolution: {integrity: sha512-mc9T+kijDX5ZJMJCzeKPk9uLfOtcuefdDLPqWi961EiiNKfkDex+Gh41DAfcyrNjYsAkBsphvgBgcvundHPGIw==} + dependencies: + '@bull-board/api': 5.6.0(@bull-board/ui@5.6.0) + dev: false + /@colors/colors@1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -1707,8 +1821,8 @@ packages: - supports-color dev: false - /@esbuild/android-arm64@0.17.19: - resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + /@esbuild/android-arm64@0.18.11: + resolution: {integrity: sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -1716,8 +1830,8 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.17.19: - resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + /@esbuild/android-arm@0.18.11: + resolution: {integrity: sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1725,8 +1839,8 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.17.19: - resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + /@esbuild/android-x64@0.18.11: + resolution: {integrity: sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1734,8 +1848,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.17.19: - resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + /@esbuild/darwin-arm64@0.18.11: + resolution: {integrity: sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1743,8 +1857,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.17.19: - resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + /@esbuild/darwin-x64@0.18.11: + resolution: {integrity: sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1752,8 +1866,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.17.19: - resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + /@esbuild/freebsd-arm64@0.18.11: + resolution: {integrity: sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1761,8 +1875,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.17.19: - resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + /@esbuild/freebsd-x64@0.18.11: + resolution: {integrity: sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1770,8 +1884,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.17.19: - resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + /@esbuild/linux-arm64@0.18.11: + resolution: {integrity: sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1779,8 +1893,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.17.19: - resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + /@esbuild/linux-arm@0.18.11: + resolution: {integrity: sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1788,8 +1902,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.17.19: - resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + /@esbuild/linux-ia32@0.18.11: + resolution: {integrity: sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1797,8 +1911,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.17.19: - resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + /@esbuild/linux-loong64@0.18.11: + resolution: {integrity: sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1806,8 +1920,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.17.19: - resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + /@esbuild/linux-mips64el@0.18.11: + resolution: {integrity: sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1815,8 +1929,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.17.19: - resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + /@esbuild/linux-ppc64@0.18.11: + resolution: {integrity: sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1824,8 +1938,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.17.19: - resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + /@esbuild/linux-riscv64@0.18.11: + resolution: {integrity: sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1833,8 +1947,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.17.19: - resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + /@esbuild/linux-s390x@0.18.11: + resolution: {integrity: sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1842,8 +1956,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.17.19: - resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + /@esbuild/linux-x64@0.18.11: + resolution: {integrity: sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1851,8 +1965,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.17.19: - resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + /@esbuild/netbsd-x64@0.18.11: + resolution: {integrity: sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -1860,8 +1974,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.17.19: - resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + /@esbuild/openbsd-x64@0.18.11: + resolution: {integrity: sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -1869,8 +1983,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.17.19: - resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + /@esbuild/sunos-x64@0.18.11: + resolution: {integrity: sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -1878,8 +1992,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.17.19: - resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + /@esbuild/win32-arm64@0.18.11: + resolution: {integrity: sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -1887,8 +2001,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.17.19: - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + /@esbuild/win32-ia32@0.18.11: + resolution: {integrity: sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -1896,8 +2010,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.17.19: - resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + /@esbuild/win32-x64@0.18.11: + resolution: {integrity: sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2013,7 +2127,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 jest-message-util: 29.6.0 jest-util: 29.6.0 @@ -2079,14 +2193,14 @@ packages: '@jest/test-result': 29.6.0 '@jest/transform': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.5.0 - jest-config: 29.6.0(@types/node@20.3.1) + jest-config: 29.6.0(@types/node@18.11.18) jest-haste-map: 29.6.0 jest-message-util: 29.6.0 jest-regex-util: 29.4.3 @@ -2123,7 +2237,7 @@ packages: dependencies: '@jest/fake-timers': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-mock: 29.6.0 dev: true @@ -2162,7 +2276,7 @@ packages: dependencies: '@jest/types': 29.6.0 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-message-util: 29.6.0 jest-mock: 29.6.0 jest-util: 29.6.0 @@ -2242,7 +2356,7 @@ packages: '@jest/transform': 29.6.0 '@jest/types': 29.6.0 '@jridgewell/trace-mapping': 0.3.18 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -2402,7 +2516,7 @@ packages: '@jest/schemas': 29.6.0 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.3.1 + '@types/node': 18.11.18 '@types/yargs': 17.0.24 chalk: 4.1.2 dev: true @@ -2650,6 +2764,11 @@ packages: engines: {node: '>= 10'} hasBin: true + /@nicolo-ribaudo/semver-v6@6.3.3: + resolution: {integrity: sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==} + hasBin: true + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2781,7 +2900,7 @@ packages: engines: {node: '>=12.0.0'} dependencies: '@redocly/ajv': 8.11.0 - '@types/node': 14.18.52 + '@types/node': 14.18.53 colorette: 1.4.0 js-levenshtein: 1.1.6 js-yaml: 4.1.0 @@ -2794,26 +2913,26 @@ packages: - encoding dev: false - /@rollup/plugin-alias@3.1.9(rollup@3.23.1): + /@rollup/plugin-alias@3.1.9(rollup@3.26.2): resolution: {integrity: sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw==} engines: {node: '>=8.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0 dependencies: - rollup: 3.23.1 + rollup: 3.26.2 slash: 3.0.0 dev: true - /@rollup/plugin-json@4.1.0(rollup@3.23.1): + /@rollup/plugin-json@4.1.0(rollup@3.26.2): resolution: {integrity: sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 dependencies: - '@rollup/pluginutils': 3.1.0(rollup@3.23.1) - rollup: 3.23.1 + '@rollup/pluginutils': 3.1.0(rollup@3.26.2) + rollup: 3.26.2 dev: true - /@rollup/pluginutils@3.1.0(rollup@3.23.1): + /@rollup/pluginutils@3.1.0(rollup@3.26.2): resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: @@ -2822,7 +2941,7 @@ packages: '@types/estree': 0.0.39 estree-walker: 1.0.1 picomatch: 2.3.1 - rollup: 3.23.1 + rollup: 3.26.2 dev: true /@rollup/pluginutils@4.2.1: @@ -3373,12 +3492,12 @@ packages: /@types/accepts@1.3.5: resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/adm-zip@0.5.0: resolution: {integrity: sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/argparse@1.0.38: @@ -3426,7 +3545,7 @@ packages: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/bull@3.15.9: resolution: {integrity: sha512-MPUcyPPQauAmynoO3ezHAmCOhbB0pWmYyijr/5ctaCqhbKWsjW0YCod38ZcLzUBprosfZ9dPqfYIcfdKjk7RNQ==} @@ -3442,7 +3561,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.3.1 + '@types/node': 18.11.18 '@types/responselike': 1.0.0 /@types/cbor@6.0.0: @@ -3455,14 +3574,14 @@ packages: /@types/co-body@6.1.0: resolution: {integrity: sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 '@types/qs': 6.9.7 dev: false /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/content-disposition@0.5.5: resolution: {integrity: sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==} @@ -3473,7 +3592,7 @@ packages: '@types/connect': 3.4.35 '@types/express': 4.17.17 '@types/keygrip': 1.0.2 - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/core-js@2.5.0: resolution: {integrity: sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==} @@ -3523,7 +3642,7 @@ packages: /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -3539,7 +3658,7 @@ packages: /@types/fluent-ffmpeg@2.1.20: resolution: {integrity: sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/form-data@2.5.0: @@ -3552,13 +3671,13 @@ packages: /@types/formidable@2.0.6: resolution: {integrity: sha512-L4HcrA05IgQyNYJj6kItuIkXrInJvsXTPC5B1i64FggWKKqSL+4hgt7asiSNva75AoLQjq29oPxFfU4GAQ6Z2w==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: false /@types/glob-stream@8.0.0: resolution: {integrity: sha512-fxTWwdQmX9LWSHD7ZLlv3BHR992mKcVcDnT/2v+l/QZZo7TfDdyasqlSYVzOnMGWhRbrWeWkbj/mgezFjKynhw==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/picomatch': 2.3.0 '@types/streamx': 2.9.1 dev: true @@ -3567,7 +3686,7 @@ packages: resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true /@types/graceful-fs@4.1.6: @@ -3576,34 +3695,19 @@ packages: '@types/node': 20.3.1 dev: true - /@types/gulp-rename@2.0.1: - resolution: {integrity: sha512-9ZjeS2RHEnmBmTcyi2+oeye3BgCsWhvi4uv3qCnAg8i6plOuRdaeNxjOves0ELysEXYLBl7bCl5fbVs7AZtgTA==} - dependencies: - '@types/node': 20.3.1 - '@types/vinyl': 2.0.7 - dev: true - /@types/gulp-rename@2.0.2: resolution: {integrity: sha512-CQsXqTVtAXqrPd4IbrrlJEEzRkUR3RXsyZbrVoOVqjlchDDmnyRDatAUisjpQjjCg/wjJrSiNg8T1uAbJ/7Qqg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/vinyl': 2.0.7 dev: true - /@types/gulp@4.0.10: - resolution: {integrity: sha512-spgZHJFqiEJGwqGlf7T/k4nkBpBcLgP7T0EfN6G2vvnhUfvd4uO1h8RwpXOE8x/54DVYUs1XCAtBHkX/R3axAQ==} + /@types/gulp@4.0.13: + resolution: {integrity: sha512-Ms20Q2tZ3MpThZGn4Ag6e7ifz/oQJFxsuiopqz5oHmhE6q2ohnELgafi5K/pKX/4ntlpidS61v/TXAguYsVcaA==} dependencies: '@types/undertaker': 1.2.8 '@types/vinyl-fs': 3.0.2 - chokidar: 3.3.1 - dev: true - - /@types/gulp@4.0.11: - resolution: {integrity: sha512-jy0nfcsjiGqO1prNsYMK/bHkTblIBgG04sL2nxPpnP9MyNicHp1SUblomjOla6JoW1qkR67HjFHqIibpPoShNQ==} - dependencies: - '@types/undertaker': 1.2.8 - '@types/vinyl-fs': 3.0.2 - chokidar: 3.3.1 + chokidar: 3.5.3 dev: true /@types/http-assert@1.5.3: @@ -3661,7 +3765,7 @@ packages: /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 '@types/tough-cookie': 4.0.2 parse5: 7.1.2 dev: true @@ -3692,7 +3796,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/koa-bodyparser@4.3.10: resolution: {integrity: sha512-6ae05pjhmrmGhUR8GYD5qr5p9LTEMEGfGXCsK8VaSL+totwigm8+H/7MHW7K4854CMeuwRAubT8qcc/EagaeIA==} @@ -3808,7 +3912,7 @@ packages: '@types/http-errors': 2.0.1 '@types/keygrip': 1.0.2 '@types/koa-compose': 3.2.5 - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/koa__cors@3.3.0: resolution: {integrity: sha512-FUN8YxcBakIs+walVe3+HcNP+Bxd0SB8BJHBWkglZ5C1XQWljlKcEFDG/dPiCIqwVCUbc5X0nYDlH62uEhdHMA==} @@ -3857,13 +3961,13 @@ packages: /@types/needle@3.2.0: resolution: {integrity: sha512-6XzvzEyJ2ozFNfPajFmqH9JOt0Hp+9TawaYpJT59iIP/zR0U37cfWCRwosyIeEBBZBi021Osq4jGAD3AOju5fg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 form-data: 3.0.1 dev: false @@ -3874,19 +3978,23 @@ packages: node-fetch: 3.3.1 dev: true - /@types/node@14.18.52: - resolution: {integrity: sha512-DGhiXKOHSFVVm+PJD+9Y0ObxXLeG6qwc0HoOn+ooQKeNNu+T2mEJCM5UBDUREKAggl9MHYjb5E71PAmx6MbzIg==} + /@types/node@14.18.53: + resolution: {integrity: sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A==} /@types/node@18.11.18: resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} /@types/node@20.3.1: resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==} + dev: true + + /@types/node@20.4.1: + resolution: {integrity: sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==} /@types/nodemailer@6.4.8: resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/normalize-package-data@2.4.1: @@ -3896,7 +4004,7 @@ packages: /@types/oauth@0.9.1: resolution: {integrity: sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/object-assign-deep@0.4.0: resolution: {integrity: sha512-3D0F3rHRNDc8cQSXNzwF1jBrJi28Mdrhc10ZLlqbJWDPYRWTTWB9Tc8JoKrgBvLKioXoPoHT6Uzf3s2F7akCUg==} @@ -3926,7 +4034,7 @@ packages: resolution: {integrity: sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew==} dependencies: '@types/needle': 3.2.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/pug@2.0.6: @@ -3940,7 +4048,7 @@ packages: /@types/qrcode@1.5.0: resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/qs@6.9.7: @@ -3960,7 +4068,7 @@ packages: /@types/redis@2.8.32: resolution: {integrity: sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/redis@4.0.11: @@ -3977,7 +4085,7 @@ packages: /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/sanitize-html@2.9.0: resolution: {integrity: sha512-4fP/kEcKNj2u39IzrxWYuf/FnCCwwQCpif6wwY6ROUS1EPRIfWJjGkY3HIowY1EX/VbX5e86yq8AAE7UPMgATg==} @@ -4001,19 +4109,19 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/serve-static@1.15.2: resolution: {integrity: sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==} dependencies: '@types/http-errors': 2.0.1 '@types/mime': 3.0.1 - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/sharp@0.31.1: resolution: {integrity: sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/sinonjs__fake-timers@8.1.1: @@ -4035,7 +4143,7 @@ packages: /@types/streamx@2.9.1: resolution: {integrity: sha512-9bywzhouyedmci7WCIPFwJ8zASDnxt2gaVUy52X0p0Tt085IJSAEP0L6j4SSNeDMSLzpYu6cPz0GrJZ7kPJ6Bg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true /@types/throttle-debounce@5.0.0: @@ -4061,7 +4169,7 @@ packages: /@types/undertaker@1.2.8: resolution: {integrity: sha512-gW3PRqCHYpo45XFQHJBhch7L6hytPsIe0QeLujlnFsjHPnXLhJcPdN6a9368d7aIQgH2I/dUTPFBlGeSNA3qOg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/undertaker-registry': 1.0.1 async-done: 1.3.2 dev: true @@ -4078,7 +4186,7 @@ packages: resolution: {integrity: sha512-ctNcmmzbMIKooXjRkyyUCOu2Z4AyqibL+RhXoF3pb7K7j+ezItnakmpm31LymkYHSIM5ey0tjIFzTvFOTSBCGw==} dependencies: '@types/glob-stream': 8.0.0 - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/vinyl': 2.0.7 dev: true @@ -4086,13 +4194,13 @@ packages: resolution: {integrity: sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==} dependencies: '@types/expect': 1.20.4 - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true /@types/web-push@3.3.2: resolution: {integrity: sha512-JxWGVL/m7mWTIg4mRYO+A6s0jPmBkr4iJr39DqJpRJAc+jrPiEe1/asmkwerzRon8ZZDxaZJpsxpv0Z18Wo9gw==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/webgl-ext@0.0.30: @@ -4106,13 +4214,13 @@ packages: /@types/websocket@1.0.5: resolution: {integrity: sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 dev: true /@types/ws@8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} @@ -4134,7 +4242,7 @@ packages: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true optional: true @@ -4267,14 +4375,14 @@ packages: eslint-visitor-keys: 3.4.1 dev: true - /@vitejs/plugin-vue@4.2.3(vite@4.3.9)(vue@3.3.4): + /@vitejs/plugin-vue@4.2.3(vite@4.4.2)(vue@3.3.4): resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 4.3.9(@types/node@18.11.18)(sass@1.62.1) + vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6) vue: 3.3.4 dev: true @@ -4298,7 +4406,7 @@ packages: resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==} dependencies: '@babel/parser': 7.22.5 - postcss: 8.4.24 + postcss: 8.4.25 source-map: 0.6.1 dev: true @@ -5465,6 +5573,11 @@ packages: /blurhash@1.1.5: resolution: {integrity: sha512-a+LO3A2DfxTaTztsmkbLYmUzUeApi0LZuKalwbNmqAHR6HhJGMt1qSV/R3wc+w4DL28holjqO3Bg74aUGavGjg==} + dev: false + + /blurhash@2.0.5: + resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} + dev: true /bmp-js@0.1.0: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} @@ -5513,10 +5626,10 @@ packages: dependencies: fill-range: 7.0.1 - /broadcast-channel@4.19.1: - resolution: {integrity: sha512-CroDV8L4QdMuCHtjs0AATaN2w1rA5e6ca9a3yZATmAs3lbFu3q3QkITkuMS4sQ/NjtZwkVANXLlhgyQfiukBuw==} + /broadcast-channel@5.1.0: + resolution: {integrity: sha512-wAbP+mtQ28N+iX3scX6Q97UN39ER5jRWOtM3r1BNPLWFOMt3AGmwN9kS3fqwgaUW0tbWHRSfTpsT+pAvrzQz0Q==} dependencies: - '@babel/runtime': 7.20.7 + '@babel/runtime': 7.21.0 oblivious-set: 1.1.1 p-queue: 6.6.2 rimraf: 3.0.2 @@ -5646,7 +5759,7 @@ packages: dependencies: '@npmcli/fs': 3.1.0 fs-minipass: 3.0.2 - glob: 10.3.1 + glob: 10.3.3 lru-cache: 7.18.3 minipass: 5.0.0 minipass-collect: 1.0.2 @@ -5927,6 +6040,21 @@ packages: optionalDependencies: fsevents: 2.1.3 + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} dev: false @@ -6299,8 +6427,8 @@ packages: engines: {node: '>=4.0.0'} dev: true - /compare-versions@5.0.3: - resolution: {integrity: sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==} + /compare-versions@6.0.0: + resolution: {integrity: sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ==} dev: true /component-emitter@1.3.0: @@ -6587,6 +6715,12 @@ packages: /core-js@3.31.0: resolution: {integrity: sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==} requiresBuild: true + dev: false + + /core-js@3.31.1: + resolution: {integrity: sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==} + requiresBuild: true + dev: true /core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -6769,7 +6903,7 @@ packages: dependencies: '@cypress/request': 2.88.11 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 14.18.52 + '@types/node': 14.18.53 '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 arch: 2.2.0 @@ -7476,34 +7610,34 @@ packages: es6-symbol: 3.1.3 dev: true - /esbuild@0.17.19: - resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + /esbuild@0.18.11: + resolution: {integrity: sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.17.19 - '@esbuild/android-arm64': 0.17.19 - '@esbuild/android-x64': 0.17.19 - '@esbuild/darwin-arm64': 0.17.19 - '@esbuild/darwin-x64': 0.17.19 - '@esbuild/freebsd-arm64': 0.17.19 - '@esbuild/freebsd-x64': 0.17.19 - '@esbuild/linux-arm': 0.17.19 - '@esbuild/linux-arm64': 0.17.19 - '@esbuild/linux-ia32': 0.17.19 - '@esbuild/linux-loong64': 0.17.19 - '@esbuild/linux-mips64el': 0.17.19 - '@esbuild/linux-ppc64': 0.17.19 - '@esbuild/linux-riscv64': 0.17.19 - '@esbuild/linux-s390x': 0.17.19 - '@esbuild/linux-x64': 0.17.19 - '@esbuild/netbsd-x64': 0.17.19 - '@esbuild/openbsd-x64': 0.17.19 - '@esbuild/sunos-x64': 0.17.19 - '@esbuild/win32-arm64': 0.17.19 - '@esbuild/win32-ia32': 0.17.19 - '@esbuild/win32-x64': 0.17.19 + '@esbuild/android-arm': 0.18.11 + '@esbuild/android-arm64': 0.18.11 + '@esbuild/android-x64': 0.18.11 + '@esbuild/darwin-arm64': 0.18.11 + '@esbuild/darwin-x64': 0.18.11 + '@esbuild/freebsd-arm64': 0.18.11 + '@esbuild/freebsd-x64': 0.18.11 + '@esbuild/linux-arm': 0.18.11 + '@esbuild/linux-arm64': 0.18.11 + '@esbuild/linux-ia32': 0.18.11 + '@esbuild/linux-loong64': 0.18.11 + '@esbuild/linux-mips64el': 0.18.11 + '@esbuild/linux-ppc64': 0.18.11 + '@esbuild/linux-riscv64': 0.18.11 + '@esbuild/linux-s390x': 0.18.11 + '@esbuild/linux-x64': 0.18.11 + '@esbuild/netbsd-x64': 0.18.11 + '@esbuild/openbsd-x64': 0.18.11 + '@esbuild/sunos-x64': 0.18.11 + '@esbuild/win32-arm64': 0.18.11 + '@esbuild/win32-ia32': 0.18.11 + '@esbuild/win32-x64': 0.18.11 dev: true /escalade@3.1.1: @@ -7889,6 +8023,10 @@ packages: /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true + /events@1.1.1: resolution: {integrity: sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==} engines: {node: '>=0.4.x'} @@ -8017,7 +8155,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/expect-utils': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-get-type: 29.4.3 jest-matcher-utils: 29.6.0 jest-message-util: 29.6.0 @@ -8109,6 +8247,10 @@ packages: time-stamp: 1.1.0 dev: true + /fast-blurhash@1.1.2: + resolution: {integrity: sha512-lJVOgYSlahqkRhrKumNx/SGB2F/qS0D1z7xjGYjb5EZJRtlzySGMniZjkQ9h9Rv8sPmM/V9orEgRiMwazDNH6A==} + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -8127,6 +8269,17 @@ packages: micromatch: 4.0.5 dev: true + /fast-glob@3.3.0: + resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -8371,18 +8524,18 @@ packages: readable-stream: 2.3.8 dev: true - /focus-trap-vue@4.0.2(focus-trap@7.4.3)(vue@3.3.4): + /focus-trap-vue@4.0.2(focus-trap@7.5.2)(vue@3.3.4): resolution: {integrity: sha512-2iQN2xKCSCzyhcD90VpueQcTIAhaCRxxo67fkz7RSqLmEd16QKjfGslCr3KxvBx0LfpVN9j0IAyKKuJKw3Intg==} peerDependencies: focus-trap: ^7.0.0 vue: ^3.0.0 dependencies: - focus-trap: 7.4.3 + focus-trap: 7.5.2 vue: 3.3.4 dev: true - /focus-trap@7.4.3: - resolution: {integrity: sha512-BgSSbK4GPnS2VbtZ50VtOv1Sti6DIkj3+LkVjiWMNjLeAp1SH1UlLx3ULu/DCu4vq5R4/uvTm+zrvsMsuYmGLg==} + /focus-trap@7.5.2: + resolution: {integrity: sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==} dependencies: tabbable: 6.2.0 dev: true @@ -8786,8 +8939,8 @@ packages: - supports-color dev: true - /glob@10.3.1: - resolution: {integrity: sha512-9BKYcEeIs7QwlCYs+Y3GBvqAMISufUS0i2ELd11zpZjxI5V9iyRj0HgzB5/cLf2NY4vcYBTYzJ7GIui7j/4DOw==} + /glob@10.3.3: + resolution: {integrity: sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true dependencies: @@ -8795,7 +8948,7 @@ packages: jackspeak: 2.2.1 minimatch: 9.0.2 minipass: 5.0.0 - path-scurry: 1.10.0 + path-scurry: 1.10.1 dev: false /glob@7.2.0: @@ -8879,7 +9032,7 @@ packages: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.0 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 @@ -8952,8 +9105,8 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - /gsap@3.11.5: - resolution: {integrity: sha512-Q89nKCLgoX5xUjznh9LcaIUkz54k1voNucT1Rpf9SJNFIQznBwFqt5qUUQbeVInFyN/n18OUJkpeI6CNEDt74w==} + /gsap@3.12.2: + resolution: {integrity: sha512-EkYnpG8qHgYBFAwsgsGEqvT1WUidX0tt/ijepx7z8EUJHElykg91RvW1XbkT59T0gZzzszOpjQv7SE41XuIXyQ==} dev: true /gulp-cli@2.3.0: @@ -9002,7 +9155,7 @@ packages: resolution: {integrity: sha512-SVSF7ikuWKhpAW4l4wapAqPPSToJoiNKsbDoUnRrSgwZHH7lH8pbPeQj1aOVYQrbZKhfSVBxVW+Py7vtulRktw==} engines: {node: '>=10'} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/vinyl': 2.0.7 istextorbinary: 3.3.0 replacestream: 4.0.3 @@ -10143,7 +10296,7 @@ packages: '@jest/expect': 29.6.0 '@jest/test-result': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -10301,45 +10454,6 @@ packages: - supports-color dev: true - /jest-config@29.6.0(@types/node@20.3.1): - resolution: {integrity: sha512-fKA4jM91PDqWVkMpb1FVKxIuhg3hC6hgaen57cr1rRZkR96dCatvJZsk3ik7/GNu9ERj9wgAspOmyvkFoGsZhA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.22.5 - '@jest/test-sequencer': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 20.3.1 - babel-jest: 29.6.0(@babel/core@7.22.5) - chalk: 4.1.2 - ci-info: 3.8.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.6.0 - jest-environment-node: 29.6.0 - jest-get-type: 29.4.3 - jest-regex-util: 29.4.3 - jest-resolve: 29.6.0 - jest-runner: 29.6.0 - jest-util: 29.6.0 - jest-validate: 29.6.0 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.6.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - /jest-diff@27.5.1: resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -10443,7 +10557,7 @@ packages: '@jest/environment': 29.6.0 '@jest/fake-timers': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-mock: 29.6.0 jest-util: 29.6.0 dev: true @@ -10493,7 +10607,7 @@ packages: dependencies: '@jest/types': 29.6.0 '@types/graceful-fs': 4.1.6 - '@types/node': 20.3.1 + '@types/node': 18.11.18 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -10610,7 +10724,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-util: 29.6.0 dev: true @@ -10741,7 +10855,7 @@ packages: '@jest/test-result': 29.6.0 '@jest/transform': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -10802,7 +10916,7 @@ packages: '@jest/test-result': 29.6.0 '@jest/transform': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.1 @@ -10905,7 +11019,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -10955,7 +11069,7 @@ packages: dependencies: '@jest/test-result': 29.6.0 '@jest/types': 29.6.0 - '@types/node': 20.3.1 + '@types/node': 18.11.18 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -10976,7 +11090,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -10985,7 +11099,7 @@ packages: resolution: {integrity: sha512-dICMQ+Q4W0QVMsaQzWlA1FVQhKNz7QcDCOGtbk1GCAd0Lai+wdkQvfmQwL4MjGumineh1xz+6M5oMj3rfWS02A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-util: 29.6.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -10995,7 +11109,7 @@ packages: resolution: {integrity: sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.3.1 + '@types/node': 18.11.18 jest-util: 29.6.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -11365,8 +11479,8 @@ packages: safe-buffer: 5.2.1 dev: false - /katex@0.16.7: - resolution: {integrity: sha512-Xk9C6oGKRwJTfqfIbtr0Kes9OSv6IFsuhFGc7tW4urlpMJtuh+7YhzU6YEG9n8gmWKcMAFzkp7nr+r69kV0zrA==} + /katex@0.16.8: + resolution: {integrity: sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==} hasBin: true dependencies: commander: 8.3.0 @@ -13238,8 +13352,8 @@ packages: path-root-regex: 0.1.2 dev: true - /path-scurry@1.10.0: - resolution: {integrity: sha512-tZFEaRQbMLjwrsmidsGJ6wDMv0iazJWk6SfIKnY4Xru8auXgmJkOBa5DUbYFcFD2Rzk2+KDlIiF0GVXNCbgC7g==} + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} dependencies: lru-cache: 10.0.0 @@ -13345,8 +13459,8 @@ packages: split2: 4.2.0 dev: false - /photoswipe@5.3.7: - resolution: {integrity: sha512-zsyLsTTLFrj0XR1m4/hO7qNooboFKUrDy+Zt5i2d6qjFPAtBjzaj/Xtydso4uxzcXpcqbTmyxDibb3BcSISseg==} + /photoswipe@5.3.8: + resolution: {integrity: sha512-4vTzOQt8GP4Chsm0s+8j2xDtVHAEN252PxrU12A1zXauNn0zD5HRHgjALKO2GKTyBnTnOrJUOxbV8LTrFIMrYw==} engines: {node: '>= 0.12.0'} dev: true @@ -13672,6 +13786,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.25: + resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -14003,11 +14126,6 @@ packages: resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} dev: false - /punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: true - /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -14256,6 +14374,13 @@ packages: dependencies: picomatch: 2.3.1 + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} engines: {node: '>= 0.10'} @@ -14616,8 +14741,8 @@ packages: rangestr: 0.0.1 seedrandom: 2.4.2 - /rollup@3.23.1: - resolution: {integrity: sha512-ybRdFVHOoljGEFILHLd2g/qateqUdjE6YS41WXq4p3C/WwD3xtWxV4FYWETA1u9TeXQc5K8L8zHE5d/scOvrOQ==} + /rollup@3.26.2: + resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -14694,12 +14819,12 @@ packages: postcss: 8.4.24 dev: false - /sass@1.62.1: - resolution: {integrity: sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==} + /sass@1.63.6: + resolution: {integrity: sha512-MJuxGMHzaOW7ipp+1KdELtqKbfAWbH7OLIdoSMnVe3EXPMTmxTmlaZDCTsgIpPCs3w99lLo9/zDKkOrJuT5byw==} engines: {node: '>=14.0.0'} hasBin: true dependencies: - chokidar: 3.3.1 + chokidar: 3.5.3 immutable: 4.3.0 source-map-js: 1.0.2 dev: true @@ -15172,10 +15297,6 @@ packages: safer-buffer: 2.1.2 tweetnacl: 0.14.5 - /ssr-window@4.0.2: - resolution: {integrity: sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==} - dev: true - /ssri@10.0.4: resolution: {integrity: sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -15534,11 +15655,9 @@ packages: webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) dev: true - /swiper@9.3.2: - resolution: {integrity: sha512-Kj9Z4kXRmJR3YT/Wj+XLWj8P6IcRt+WG38uL8M3/Wny7+6sV0TlP9vnE1X+Co9c7VzNooojWGnFa+Wf/9+CUMA==} + /swiper@10.0.4: + resolution: {integrity: sha512-DlNR3KiaVkPep6RraZ2tNr7lvyuzELuR+4NZr4wO42t0UworIO3DxDlz8b5Q3uUioh7cJad99EdRJLkPF+r8Ag==} engines: {node: '>= 4.7.0'} - dependencies: - ssr-window: 4.0.2 dev: true /symbol-tree@3.2.4: @@ -15781,6 +15900,11 @@ packages: /tinycolor2@1.5.2: resolution: {integrity: sha512-h80m9GPFGbcLzZByXlNSEhp1gf8Dy+VX/2JCGUZsWLo7lV1mnE/XlxGYgRBoMLJh1lIDXP0EMC4RPTjlRaV+Bg==} + dev: false + + /tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + dev: true /tmp@0.2.1: resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} @@ -15905,7 +16029,7 @@ packages: escape-string-regexp: 5.0.0 dev: true - /ts-jest@27.1.2(@babel/core@7.22.5)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3): + /ts-jest@27.1.2(@babel/core@7.22.8)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3): resolution: {integrity: sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true @@ -15926,7 +16050,7 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.8 '@types/jest': 27.4.0 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -15940,7 +16064,7 @@ packages: yargs-parser: 20.2.9 dev: true - /ts-jest@29.0.5(@babel/core@7.22.5)(jest@29.4.0)(typescript@4.9.4): + /ts-jest@29.0.5(@babel/core@7.22.8)(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 @@ -15961,7 +16085,7 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.8 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 jest: 29.4.0(@types/node@18.11.18) @@ -16051,11 +16175,11 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - /tsc-alias@1.8.6: - resolution: {integrity: sha512-vq+i6VpE83IeMsSJVcFN03ZBofADhr8/gIJXjxpbnTRfN/MFXy0+SBaKG2o7p95QqXBGkeG98HYz3IkOOveFbg==} + /tsc-alias@1.8.7: + resolution: {integrity: sha512-59Q/zUQa3miTf99mLbSqaW0hi1jt4WoG8Uhe5hSZJHQpSoFW9eEwvW7jlKMHXWvT+zrzy3SN9PE/YBhQ+WVydA==} hasBin: true dependencies: - chokidar: 3.3.1 + chokidar: 3.5.3 commander: 9.5.0 globby: 11.1.0 mylas: 2.1.13 @@ -16315,6 +16439,12 @@ packages: engines: {node: '>=14.17'} hasBin: true + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + /ulid@2.3.0: resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} hasBin: true @@ -16649,7 +16779,7 @@ packages: replace-ext: 1.0.1 dev: true - /vite-plugin-compression@0.5.1(vite@4.3.9): + /vite-plugin-compression@0.5.1(vite@4.4.2): resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} peerDependencies: vite: '>=2.0.0' @@ -16657,18 +16787,19 @@ packages: chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 10.1.0 - vite: 4.3.9(@types/node@18.11.18)(sass@1.62.1) + vite: 4.4.2(@types/node@20.4.1)(sass@1.63.6) transitivePeerDependencies: - supports-color dev: true - /vite@4.3.9(@types/node@18.11.18)(sass@1.62.1): - resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + /vite@4.4.2(@types/node@20.4.1)(sass@1.63.6): + resolution: {integrity: sha512-zUcsJN+UvdSyHhYa277UHhiJ3iq4hUBwHavOpsNUGsTgjBeoBlK8eDt+iT09pBq0h9/knhG/SPrZiM7cGmg7NA==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: '@types/node': '>= 14' less: '*' + lightningcss: ^1.21.0 sass: '*' stylus: '*' sugarss: '*' @@ -16678,6 +16809,8 @@ packages: optional: true less: optional: true + lightningcss: + optional: true sass: optional: true stylus: @@ -16687,11 +16820,11 @@ packages: terser: optional: true dependencies: - '@types/node': 18.11.18 - esbuild: 0.17.19 - postcss: 8.4.24 - rollup: 3.23.1 - sass: 1.62.1 + '@types/node': 20.4.1 + esbuild: 0.18.11 + postcss: 8.4.25 + rollup: 3.26.2 + sass: 1.63.6 optionalDependencies: fsevents: 2.3.2 dev: true @@ -17422,15 +17555,15 @@ packages: name: plyr version: 3.7.0 dependencies: - core-js: 3.31.0 + core-js: 3.31.1 custom-event-polyfill: 1.0.7 loadjs: 4.2.0 rangetouch: 2.0.1 url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/9d16541664dc8fef3201ae9b647477070676a52e: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/9d16541664dc8fef3201ae9b647477070676a52e} + github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/15fd9504f943763a057ff803ee2009ec0524c96b} name: emojilib version: 3.0.10 dev: true From 4a9d85fdc15ab0d5c7e18edb2644e8c5507d3420 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 21:14:22 -0700 Subject: [PATCH 037/162] dev60 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 592788316..0f14400cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-rc3", + "version": "14.0.0-dev60", "codename": "aqua", "repository": { "type": "git", From 774dbbc3602b85b119ea40a5889369b4b34eb950 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 21:16:56 -0700 Subject: [PATCH 038/162] fix: :ambulance: correct import for swiper 10 --- packages/client/src/pages/about.vue | 2 +- packages/client/src/pages/admin-file.vue | 2 +- packages/client/src/pages/channels.vue | 2 +- packages/client/src/pages/explore.vue | 2 +- packages/client/src/pages/gallery/index.vue | 2 +- packages/client/src/pages/instance-info.vue | 2 +- packages/client/src/pages/messaging/index.vue | 2 +- packages/client/src/pages/notifications.vue | 2 +- packages/client/src/pages/pages.vue | 2 +- packages/client/src/pages/search.vue | 2 +- packages/client/src/pages/tag.vue | 2 +- packages/client/src/pages/timeline.vue | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue index b7fe6fe7a..88ed1add2 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -163,7 +163,7 @@ <script lang="ts" setup> import { ref, computed, onMounted, watch } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import XEmojis from "./about.emojis.vue"; import XFederation from "./about.federation.vue"; diff --git a/packages/client/src/pages/admin-file.vue b/packages/client/src/pages/admin-file.vue index 4a2c87e93..87647dc1d 100644 --- a/packages/client/src/pages/admin-file.vue +++ b/packages/client/src/pages/admin-file.vue @@ -157,7 +157,7 @@ <script lang="ts" setup> import { computed, watch } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import MkButton from "@/components/MkButton.vue"; import MkSwitch from "@/components/form/switch.vue"; diff --git a/packages/client/src/pages/channels.vue b/packages/client/src/pages/channels.vue index 75e922440..65f4dbf0c 100644 --- a/packages/client/src/pages/channels.vue +++ b/packages/client/src/pages/channels.vue @@ -112,7 +112,7 @@ <script lang="ts" setup> import { computed, onMounted, defineComponent, inject, watch } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import MkChannelPreview from "@/components/MkChannelPreview.vue"; import MkChannelList from "@/components/MkChannelList.vue"; diff --git a/packages/client/src/pages/explore.vue b/packages/client/src/pages/explore.vue index 3e0a114ec..c5b638ba4 100644 --- a/packages/client/src/pages/explore.vue +++ b/packages/client/src/pages/explore.vue @@ -38,7 +38,7 @@ <script lang="ts" setup> import { computed, watch, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import XFeatured from "./explore.featured.vue"; import XUsers from "./explore.users.vue"; diff --git a/packages/client/src/pages/gallery/index.vue b/packages/client/src/pages/gallery/index.vue index a4a09325c..45e7bd7ae 100644 --- a/packages/client/src/pages/gallery/index.vue +++ b/packages/client/src/pages/gallery/index.vue @@ -107,7 +107,7 @@ <script lang="ts" setup> import { computed, defineComponent, watch, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import MkFolder from "@/components/MkFolder.vue"; import MkPagination from "@/components/MkPagination.vue"; diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue index cd6a390c8..20643a32f 100644 --- a/packages/client/src/pages/instance-info.vue +++ b/packages/client/src/pages/instance-info.vue @@ -338,7 +338,7 @@ <script lang="ts" setup> import { watch } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import type * as calckey from "calckey-js"; import MkChart from "@/components/MkChart.vue"; diff --git a/packages/client/src/pages/messaging/index.vue b/packages/client/src/pages/messaging/index.vue index 72d32fa21..59ef02094 100644 --- a/packages/client/src/pages/messaging/index.vue +++ b/packages/client/src/pages/messaging/index.vue @@ -90,7 +90,7 @@ <script lang="ts" setup> import { ref, markRaw, onMounted, onUnmounted, watch } from "vue"; import * as Acct from "calckey-js/built/acct"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import MkButton from "@/components/MkButton.vue"; import MkChatPreview from "@/components/MkChatPreview.vue"; diff --git a/packages/client/src/pages/notifications.vue b/packages/client/src/pages/notifications.vue index 47554d9ae..f8e68a99f 100644 --- a/packages/client/src/pages/notifications.vue +++ b/packages/client/src/pages/notifications.vue @@ -52,7 +52,7 @@ <script lang="ts" setup> import { computed, ref, watch } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import { notificationTypes } from "calckey-js"; import XNotifications from "@/components/MkNotifications.vue"; diff --git a/packages/client/src/pages/pages.vue b/packages/client/src/pages/pages.vue index a3a08be7c..6b051f683 100644 --- a/packages/client/src/pages/pages.vue +++ b/packages/client/src/pages/pages.vue @@ -81,7 +81,7 @@ <script lang="ts" setup> import { computed, watch, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import MkPagePreview from "@/components/MkPagePreview.vue"; import MkPagination from "@/components/MkPagination.vue"; diff --git a/packages/client/src/pages/search.vue b/packages/client/src/pages/search.vue index 3968348a5..fdab6636e 100644 --- a/packages/client/src/pages/search.vue +++ b/packages/client/src/pages/search.vue @@ -41,7 +41,7 @@ <script lang="ts" setup> import { computed, watch, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import XNotes from "@/components/MkNotes.vue"; import XUserList from "@/components/MkUserList.vue"; diff --git a/packages/client/src/pages/tag.vue b/packages/client/src/pages/tag.vue index d60bee652..e9a1792a0 100644 --- a/packages/client/src/pages/tag.vue +++ b/packages/client/src/pages/tag.vue @@ -41,7 +41,7 @@ <script lang="ts" setup> import { computed, watch, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import XNotes from "@/components/MkNotes.vue"; import XUserList from "@/components/MkUserList.vue"; diff --git a/packages/client/src/pages/timeline.vue b/packages/client/src/pages/timeline.vue index a28e3d9f6..930a9635a 100644 --- a/packages/client/src/pages/timeline.vue +++ b/packages/client/src/pages/timeline.vue @@ -65,7 +65,7 @@ <script lang="ts" setup> import { computed, ref, onMounted } from "vue"; -import { Virtual } from "swiper"; +import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; import XTutorial from "@/components/MkTutorialDialog.vue"; import XTimeline from "@/components/MkTimeline.vue"; From ad6b2262ac77d2e29077d34b15406c6c104c0839 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Tue, 11 Jul 2023 00:27:21 -0400 Subject: [PATCH 039/162] style: consistent link underline thickness --- packages/client/src/components/global/MkUrl.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 6e50c851e..41bb05392 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -78,6 +78,7 @@ const target = self ? null : "_blank"; text-decoration: none !important; > span { text-decoration: underline var(--fgTransparent); + text-decoration-thickness: 1px; transition: text-decoration-color 0.2s; } From 21e4859564a4c91667f409cf5b80e951aafbe2cf Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 21:29:01 -0700 Subject: [PATCH 040/162] build: :arrow_up: up backend deps --- packages/backend/package.json | 64 +-- pnpm-lock.yaml | 1004 ++++++++++++++++++++++----------- 2 files changed, 696 insertions(+), 372 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index ec6451f61..e249b5d3f 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -25,16 +25,16 @@ "@tensorflow/tfjs-node": "3.21.1" }, "dependencies": { - "@bull-board/api": "5.2.0", - "@bull-board/koa": "5.2.0", - "@bull-board/ui": "5.2.0", + "@bull-board/api": "5.6.0", + "@bull-board/koa": "5.6.0", + "@bull-board/ui": "5.6.0", "@discordapp/twemoji": "14.1.2", "@elastic/elasticsearch": "7.17.0", "@koa/cors": "3.4.3", "@koa/multer": "3.0.2", "@koa/router": "9.0.1", "@peertube/http-signature": "1.7.0", - "@redocly/openapi-core": "1.0.0-beta.120", + "@redocly/openapi-core": "1.0.0-beta.131", "@sinonjs/fake-timers": "9.1.2", "@syuilo/aiscript": "0.11.1", "@tensorflow/tfjs": "^4.2.0", @@ -45,17 +45,17 @@ "autobind-decorator": "2.4.0", "autolinker": "4.0.0", "autwh": "0.1.0", - "aws-sdk": "2.1277.0", + "aws-sdk": "2.1413.0", "axios": "^1.4.0", "bcryptjs": "2.4.3", - "blurhash": "1.1.5", + "blurhash": "2.0.5", "bull": "4.10.4", "cacheable-lookup": "7.0.0", "calckey-js": "workspace:*", "cbor": "8.1.0", - "chalk": "5.2.0", + "chalk": "5.3.0", "chalk-template": "0.4.0", - "chokidar": "3.5.3", + "chokidar": "^3.5.3", "cli-highlight": "2.1.11", "color-convert": "2.0.1", "content-disposition": "0.5.4", @@ -68,15 +68,15 @@ "got": "12.5.3", "hpagent": "0.1.2", "ioredis": "5.3.2", - "ip-cidr": "3.0.11", + "ip-cidr": "3.1.0", "is-svg": "4.3.2", "js-yaml": "4.1.0", "jsdom": "20.0.3", "jsonld": "8.2.0", - "jsrsasign": "10.6.1", - "koa": "2.13.4", + "jsrsasign": "10.8.6", + "koa": "2.14.2", "koa-body": "^6.0.1", - "koa-bodyparser": "4.3.0", + "koa-bodyparser": "4.4.1", "koa-favicon": "2.1.0", "koa-json-body": "5.3.0", "koa-logger": "3.2.1", @@ -98,9 +98,9 @@ "nsfwjs": "2.4.2", "oauth": "^0.10.0", "os-utils": "0.0.14", - "otpauth": "^9.1.2", + "otpauth": "^9.1.3", "parse5": "7.1.2", - "pg": "8.11.0", + "pg": "8.11.1", "private-ip": "2.3.4", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", @@ -110,7 +110,7 @@ "qs": "6.11.2", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.19.0", + "re2": "1.19.1", "redis-lock": "0.1.4", "redis-semaphore": "5.3.1", "reflect-metadata": "0.1.13", @@ -119,7 +119,7 @@ "rss-parser": "3.13.0", "sanitize-html": "2.10.0", "seedrandom": "^3.0.5", - "semver": "7.5.1", + "semver": "7.5.4", "sharp": "0.32.1", "sonic-channel": "^1.3.1", "stringz": "2.1.0", @@ -130,27 +130,26 @@ "tinycolor2": "1.5.2", "tmp": "0.2.1", "twemoji-parser": "14.0.0", - "typeorm": "0.3.11", + "typeorm": "0.3.17", "ulid": "2.3.0", "uuid": "9.0.0", - "web-push": "3.6.1", + "web-push": "3.6.3", "websocket": "1.0.34", "xev": "3.0.2" }, "devDependencies": { "@swc/cli": "^0.1.62", - "@swc/core": "^1.3.62", + "@swc/core": "^1.3.68", "@types/adm-zip": "^0.5.0", "@types/bcryptjs": "2.4.2", - "@types/bull": "3.15.9", "@types/cbor": "6.0.0", "@types/escape-regexp": "0.0.1", - "@types/fluent-ffmpeg": "2.1.20", + "@types/fluent-ffmpeg": "2.1.21", "@types/js-yaml": "4.0.5", - "@types/jsdom": "20.0.1", - "@types/jsonld": "1.5.8", - "@types/jsrsasign": "10.5.4", - "@types/koa": "2.13.5", + "@types/jsdom": "21.1.1", + "@types/jsonld": "1.5.9", + "@types/jsrsasign": "10.5.8", + "@types/koa": "2.13.6", "@types/koa-bodyparser": "4.3.10", "@types/koa-cors": "0.0.2", "@types/koa-favicon": "2.0.21", @@ -169,7 +168,7 @@ "@types/probe-image-size": "^7.2.0", "@types/pug": "2.0.6", "@types/punycode": "2.1.0", - "@types/qrcode": "1.5.0", + "@types/qrcode": "1.5.1", "@types/qs": "6.9.7", "@types/random-seed": "0.3.3", "@types/ratelimiter": "3.4.4", @@ -177,17 +176,16 @@ "@types/rename": "1.0.4", "@types/sanitize-html": "2.9.0", "@types/semver": "7.5.0", - "@types/sharp": "0.31.1", "@types/sinonjs__fake-timers": "8.1.2", "@types/tinycolor2": "1.4.3", "@types/tmp": "0.2.3", - "@types/uuid": "8.3.4", + "@types/uuid": "9.0.2", "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", - "@types/ws": "8.5.4", + "@types/ws": "8.5.5", "autobind-decorator": "2.4.0", "cross-env": "7.0.3", - "eslint": "^8.42.0", + "eslint": "^8.44.0", "execa": "6.1.0", "json5": "2.2.3", "json5-loader": "4.0.1", @@ -195,11 +193,11 @@ "pug": "3.0.2", "strict-event-emitter-types": "2.0.0", "swc-loader": "^0.2.3", - "ts-loader": "9.4.3", + "ts-loader": "9.4.4", "ts-node": "10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "5.1.3", - "webpack": "^5.85.1", + "typescript": "5.1.6", + "webpack": "^5.88.1", "ws": "8.13.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8285d327c..4b4695f3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,14 +82,14 @@ importers: packages/backend: dependencies: '@bull-board/api': - specifier: 5.2.0 - version: 5.2.0(@bull-board/ui@5.2.0) + specifier: 5.6.0 + version: 5.6.0(@bull-board/ui@5.6.0) '@bull-board/koa': - specifier: 5.2.0 - version: 5.2.0(@types/koa@2.13.5)(pug@3.0.2) + specifier: 5.6.0 + version: 5.6.0(@types/koa@2.13.6)(pug@3.0.2) '@bull-board/ui': - specifier: 5.2.0 - version: 5.2.0 + specifier: 5.6.0 + version: 5.6.0 '@discordapp/twemoji': specifier: 14.1.2 version: 14.1.2 @@ -109,8 +109,8 @@ importers: specifier: 1.7.0 version: 1.7.0 '@redocly/openapi-core': - specifier: 1.0.0-beta.120 - version: 1.0.0-beta.120 + specifier: 1.0.0-beta.131 + version: 1.0.0-beta.131 '@sinonjs/fake-timers': specifier: 9.1.2 version: 9.1.2 @@ -142,8 +142,8 @@ importers: specifier: 0.1.0 version: 0.1.0 aws-sdk: - specifier: 2.1277.0 - version: 2.1277.0 + specifier: 2.1413.0 + version: 2.1413.0 axios: specifier: ^1.4.0 version: 1.4.0 @@ -151,8 +151,8 @@ importers: specifier: 2.4.3 version: 2.4.3 blurhash: - specifier: 1.1.5 - version: 1.1.5 + specifier: 2.0.5 + version: 2.0.5 bull: specifier: 4.10.4 version: 4.10.4 @@ -166,14 +166,14 @@ importers: specifier: 8.1.0 version: 8.1.0 chalk: - specifier: 5.2.0 - version: 5.2.0 + specifier: 5.3.0 + version: 5.3.0 chalk-template: specifier: 0.4.0 version: 0.4.0 chokidar: specifier: ^3.3.1 - version: 3.3.1 + version: 3.5.3 cli-highlight: specifier: 2.1.11 version: 2.1.11 @@ -211,8 +211,8 @@ importers: specifier: 5.3.2 version: 5.3.2 ip-cidr: - specifier: 3.0.11 - version: 3.0.11 + specifier: 3.1.0 + version: 3.1.0 is-svg: specifier: 4.3.2 version: 4.3.2 @@ -226,17 +226,17 @@ importers: specifier: 8.2.0 version: 8.2.0 jsrsasign: - specifier: 10.6.1 - version: 10.6.1 + specifier: 10.8.6 + version: 10.8.6 koa: - specifier: 2.13.4 - version: 2.13.4 + specifier: 2.14.2 + version: 2.14.2 koa-body: specifier: ^6.0.1 version: 6.0.1 koa-bodyparser: - specifier: 4.3.0 - version: 4.3.0 + specifier: 4.4.1 + version: 4.4.1 koa-favicon: specifier: 2.1.0 version: 2.1.0 @@ -260,7 +260,7 @@ importers: version: 2.1.0 koa-views: specifier: 7.0.2 - version: 7.0.2(@types/koa@2.13.5)(ejs@3.1.9)(pug@3.0.2) + version: 7.0.2(@types/koa@2.13.6)(ejs@3.1.9)(pug@3.0.2) megalodon: specifier: workspace:* version: link:../megalodon @@ -301,14 +301,14 @@ importers: specifier: 0.0.14 version: 0.0.14 otpauth: - specifier: ^9.1.2 - version: 9.1.2 + specifier: ^9.1.3 + version: 9.1.3 parse5: specifier: 7.1.2 version: 7.1.2 pg: - specifier: 8.11.0 - version: 8.11.0 + specifier: 8.11.1 + version: 8.11.1 private-ip: specifier: 2.3.4 version: 2.3.4 @@ -337,8 +337,8 @@ importers: specifier: 3.4.1 version: 3.4.1 re2: - specifier: 1.19.0 - version: 1.19.0 + specifier: 1.19.1 + version: 1.19.1 redis-lock: specifier: 0.1.4 version: 0.1.4 @@ -364,8 +364,8 @@ importers: specifier: ^3.0.5 version: 3.0.5 semver: - specifier: 7.5.1 - version: 7.5.1 + specifier: 7.5.4 + version: 7.5.4 sharp: specifier: 0.32.1 version: 0.32.1 @@ -386,7 +386,7 @@ importers: version: 5.17.17 tesseract.js: specifier: ^3.0.3 - version: 3.0.3(eslint@8.42.0) + version: 3.0.3(eslint@8.44.0) tinycolor2: specifier: 1.5.2 version: 1.5.2 @@ -397,8 +397,8 @@ importers: specifier: 14.0.0 version: 14.0.0 typeorm: - specifier: 0.3.11 - version: 0.3.11(ioredis@5.3.2)(pg@8.11.0)(ts-node@10.9.1) + specifier: 0.3.17 + version: 0.3.17(ioredis@5.3.2)(pg@8.11.1)(ts-node@10.9.1) ulid: specifier: 2.3.0 version: 2.3.0 @@ -406,8 +406,8 @@ importers: specifier: 9.0.0 version: 9.0.0 web-push: - specifier: 3.6.1 - version: 3.6.1 + specifier: 3.6.3 + version: 3.6.3 websocket: specifier: 1.0.34 version: 1.0.34 @@ -424,19 +424,16 @@ importers: devDependencies: '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) + version: 0.1.62(@swc/core@1.3.68)(chokidar@3.5.3) '@swc/core': - specifier: ^1.3.62 - version: 1.3.62 + specifier: ^1.3.68 + version: 1.3.68 '@types/adm-zip': specifier: ^0.5.0 version: 0.5.0 '@types/bcryptjs': specifier: 2.4.2 version: 2.4.2 - '@types/bull': - specifier: 3.15.9 - version: 3.15.9 '@types/cbor': specifier: 6.0.0 version: 6.0.0 @@ -444,23 +441,23 @@ importers: specifier: 0.0.1 version: 0.0.1 '@types/fluent-ffmpeg': - specifier: 2.1.20 - version: 2.1.20 + specifier: 2.1.21 + version: 2.1.21 '@types/js-yaml': specifier: 4.0.5 version: 4.0.5 '@types/jsdom': - specifier: 20.0.1 - version: 20.0.1 + specifier: 21.1.1 + version: 21.1.1 '@types/jsonld': - specifier: 1.5.8 - version: 1.5.8 + specifier: 1.5.9 + version: 1.5.9 '@types/jsrsasign': - specifier: 10.5.4 - version: 10.5.4 + specifier: 10.5.8 + version: 10.5.8 '@types/koa': - specifier: 2.13.5 - version: 2.13.5 + specifier: 2.13.6 + version: 2.13.6 '@types/koa-bodyparser': specifier: 4.3.10 version: 4.3.10 @@ -481,7 +478,7 @@ importers: version: 4.1.3 '@types/koa-views': specifier: 7.0.0 - version: 7.0.0(@types/koa@2.13.5)(pug@3.0.2) + version: 7.0.0(@types/koa@2.13.6)(pug@3.0.2) '@types/koa__cors': specifier: 3.3.0 version: 3.3.0 @@ -516,8 +513,8 @@ importers: specifier: 2.1.0 version: 2.1.0 '@types/qrcode': - specifier: 1.5.0 - version: 1.5.0 + specifier: 1.5.1 + version: 1.5.1 '@types/qs': specifier: 6.9.7 version: 6.9.7 @@ -539,9 +536,6 @@ importers: '@types/semver': specifier: 7.5.0 version: 7.5.0 - '@types/sharp': - specifier: 0.31.1 - version: 0.31.1 '@types/sinonjs__fake-timers': specifier: 8.1.2 version: 8.1.2 @@ -552,8 +546,8 @@ importers: specifier: 0.2.3 version: 0.2.3 '@types/uuid': - specifier: 8.3.4 - version: 8.3.4 + specifier: 9.0.2 + version: 9.0.2 '@types/web-push': specifier: 3.3.2 version: 3.3.2 @@ -561,14 +555,14 @@ importers: specifier: 1.0.5 version: 1.0.5 '@types/ws': - specifier: 8.5.4 - version: 8.5.4 + specifier: 8.5.5 + version: 8.5.5 cross-env: specifier: 7.0.3 version: 7.0.3 eslint: - specifier: ^8.42.0 - version: 8.42.0 + specifier: ^8.44.0 + version: 8.44.0 execa: specifier: 6.1.0 version: 6.1.0 @@ -577,7 +571,7 @@ importers: version: 2.2.3 json5-loader: specifier: 4.0.1 - version: 4.0.1(webpack@5.85.1) + version: 4.0.1(webpack@5.88.1) mocha: specifier: 10.2.0 version: 10.2.0 @@ -589,22 +583,22 @@ importers: version: 2.0.0 swc-loader: specifier: ^0.2.3 - version: 0.2.3(@swc/core@1.3.62)(webpack@5.85.1) + version: 0.2.3(@swc/core@1.3.68)(webpack@5.88.1) ts-loader: - specifier: 9.4.3 - version: 9.4.3(typescript@5.1.3)(webpack@5.85.1) + specifier: 9.4.4 + version: 9.4.4(typescript@5.1.6)(webpack@5.88.1) ts-node: specifier: 10.9.1 - version: 10.9.1(@swc/core@1.3.62)(@types/node@18.11.18)(typescript@5.1.3) + version: 10.9.1(@swc/core@1.3.68)(@types/node@18.11.18)(typescript@5.1.6) tsconfig-paths: specifier: 4.2.0 version: 4.2.0 typescript: - specifier: 5.1.3 - version: 5.1.3 + specifier: 5.1.6 + version: 5.1.6 webpack: - specifier: ^5.85.1 - version: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) + specifier: ^5.88.1 + version: 5.88.1(@swc/core@1.3.68) ws: specifier: 8.13.0 version: 8.13.0 @@ -642,7 +636,7 @@ importers: version: 7.36.0(@types/node@20.3.1) '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) + version: 0.1.62(@swc/core@1.3.62) '@swc/core': specifier: ^1.3.62 version: 1.3.62 @@ -789,7 +783,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b + version: github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -1051,7 +1045,7 @@ importers: devDependencies: '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62)(chokidar@3.3.1) + version: 0.1.62(@swc/core@1.3.62) '@swc/core': specifier: ^1.3.62 version: 1.3.62 @@ -1076,8 +1070,8 @@ importers: packages: - /@aashutoshrathi/word-wrap@1.2.5: - resolution: {integrity: sha512-plhoNEfSVdHMKXQyAxvH0Zyv3/4NL8r6pwgMQdmHR2vBUXn2t74PN2pBRppqKUa6RMT0yldyvOHG5Dbjwy2mBQ==} + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} /@ampproject/remapping@2.2.1: @@ -1120,7 +1114,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -1177,7 +1171,7 @@ packages: '@babel/helper-validator-option': 7.22.5 browserslist: 4.21.9 lru-cache: 5.1.1 - semver: 6.3.0 + semver: 6.3.1 /@babel/helper-compilation-targets@7.22.6(@babel/core@7.22.8): resolution: {integrity: sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==} @@ -1541,15 +1535,6 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@bull-board/api@5.2.0(@bull-board/ui@5.2.0): - resolution: {integrity: sha512-1HGF2EF/4zI3+Cj414nQzwFprLXOJTlVdqXUf5UEBS4HtYafWv93mGIwkrD8S4Bpz4VSvM87adF6tQPJ7Ewt+w==} - peerDependencies: - '@bull-board/ui': 5.2.0 - dependencies: - '@bull-board/ui': 5.2.0 - redis-info: 3.1.0 - dev: false - /@bull-board/api@5.6.0(@bull-board/ui@5.6.0): resolution: {integrity: sha512-a2O15p5oEm+/E/0I2l2nE2NKK0dkgNNTaamu+0gGyfUxWoCS3fCGX6LLEyl3jgOz0IC3GKRnwtVgbZFzk42sGQ==} peerDependencies: @@ -1559,17 +1544,17 @@ packages: redis-info: 3.1.0 dev: false - /@bull-board/koa@5.2.0(@types/koa@2.13.5)(pug@3.0.2): - resolution: {integrity: sha512-jntDAl/POouD0PS/iiKXBNl26SuUf7Y5uL3EgpDN7isvwFcpKhvdk0VdBypjrkRHN6rPaEJJPkEtK30qv01XYw==} + /@bull-board/koa@5.6.0(@types/koa@2.13.6)(pug@3.0.2): + resolution: {integrity: sha512-unzvUQQwzDF4GBcBjMTKjLtZa6D1QQIQws1hEG+xZ+/cr3LqZbcsJ7A1828XcK6GLPVtbgH0dm2/gZMS4+7Maw==} dependencies: - '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) - '@bull-board/ui': 5.2.0 + '@bull-board/api': 5.6.0(@bull-board/ui@5.6.0) + '@bull-board/ui': 5.6.0 ejs: 3.1.9 - koa: 2.13.4 + koa: 2.14.2 koa-mount: 4.0.0 koa-router: 10.1.1 koa-static: 5.0.0 - koa-views: 7.0.2(@types/koa@2.13.5)(ejs@3.1.9)(pug@3.0.2) + koa-views: 7.0.2(@types/koa@2.13.6)(ejs@3.1.9)(pug@3.0.2) transitivePeerDependencies: - '@types/koa' - arc-templates @@ -1627,12 +1612,6 @@ packages: - whiskers dev: false - /@bull-board/ui@5.2.0: - resolution: {integrity: sha512-f2sgs7AjOVch7tFhbmlVCkhZjJWboxwNxWEfAsIUd1WidUC+Ef5J02tpQvu7apzRtu5zcn8IiJtI5HFO6oKaCA==} - dependencies: - '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) - dev: false - /@bull-board/ui@5.6.0: resolution: {integrity: sha512-mc9T+kijDX5ZJMJCzeKPk9uLfOtcuefdDLPqWi961EiiNKfkDex+Gh41DAfcyrNjYsAkBsphvgBgcvundHPGIw==} dependencies: @@ -2027,6 +2006,16 @@ packages: dependencies: eslint: 8.42.0 eslint-visitor-keys: 3.4.1 + dev: 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.1 /@eslint-community/regexpp@4.5.1: resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} @@ -2047,10 +2036,32 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color + dev: true + + /@eslint/eslintrc@2.1.0: + resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4(supports-color@8.1.1) + espree: 9.6.0 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color /@eslint/js@8.42.0: resolution: {integrity: sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@eslint/js@8.44.0: + resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -2081,6 +2092,7 @@ packages: /@ioredis/commands@1.2.0: resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + dev: false /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -2613,7 +2625,7 @@ packages: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.5.1 + semver: 7.5.4 tar: 6.1.15 transitivePeerDependencies: - encoding @@ -2631,7 +2643,7 @@ packages: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.5.1 + semver: 7.5.4 tar: 6.1.15 transitivePeerDependencies: - encoding @@ -2791,7 +2803,7 @@ packages: resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.5.1 + semver: 7.5.4 dev: false /@nsfw-filter/gif-frames@1.0.2: @@ -2895,8 +2907,8 @@ packages: uri-js: 4.4.1 dev: false - /@redocly/openapi-core@1.0.0-beta.120: - resolution: {integrity: sha512-BvasunpVWm5O9F/mW6JmxUqat4XFU5zNnKJkMY6GJ9UYH2UxgKnGaMLWXKtbJEOBnMT12S/p9yeqrQHnk8rGhQ==} + /@redocly/openapi-core@1.0.0-beta.131: + resolution: {integrity: sha512-Dri3Oad3NwcyKgtkYz6hyJO+bAD531ppPrPxNo9Xfqza9LkUtJ6Vi2E6OSRGTWb94iTyEkhrJPbJE56/PbaKhQ==} engines: {node: '>=12.0.0'} dependencies: '@redocly/ajv': 8.11.0 @@ -2906,7 +2918,7 @@ packages: js-yaml: 4.1.0 lodash.isequal: 4.5.0 minimatch: 5.1.6 - node-fetch: 2.6.11 + node-fetch: 2.6.12 pluralize: 8.0.0 yaml-ast-parser: 0.0.43 transitivePeerDependencies: @@ -3098,7 +3110,7 @@ packages: resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} dev: false - /@swc/cli@0.1.62(@swc/core@1.3.62)(chokidar@3.3.1): + /@swc/cli@0.1.62(@swc/core@1.3.62): resolution: {integrity: sha512-kOFLjKY3XH1DWLfXL1/B5MizeNorHR8wHKEi92S/Zi9Md/AK17KSqR8MgyRJ6C1fhKHvbBCl8wboyKAFXStkYw==} engines: {node: '>= 12.13'} hasBin: true @@ -3111,10 +3123,30 @@ packages: dependencies: '@mole-inc/bin-wrapper': 8.0.1 '@swc/core': 1.3.62 - chokidar: 3.3.1 commander: 7.2.0 fast-glob: 3.2.12 - semver: 7.5.1 + semver: 7.5.4 + slash: 3.0.0 + source-map: 0.7.4 + dev: true + + /@swc/cli@0.1.62(@swc/core@1.3.68)(chokidar@3.5.3): + resolution: {integrity: sha512-kOFLjKY3XH1DWLfXL1/B5MizeNorHR8wHKEi92S/Zi9Md/AK17KSqR8MgyRJ6C1fhKHvbBCl8wboyKAFXStkYw==} + engines: {node: '>= 12.13'} + hasBin: true + peerDependencies: + '@swc/core': ^1.2.66 + chokidar: ^3.5.1 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + '@mole-inc/bin-wrapper': 8.0.1 + '@swc/core': 1.3.68 + chokidar: 3.5.3 + commander: 7.2.0 + fast-glob: 3.2.12 + semver: 7.5.4 slash: 3.0.0 source-map: 0.7.4 dev: true @@ -3134,6 +3166,15 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-arm64@1.3.68: + resolution: {integrity: sha512-Z5pNxeuP2NxpOHTzDQkJs0wAPLnTlglZnR3WjObijwvdwT/kw1Y5EPDKM/BVSIeG40SPMkDLBbI0aj0qyXzrBA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true optional: true /@swc/core-darwin-x64@1.3.62: @@ -3142,6 +3183,15 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-x64@1.3.68: + resolution: {integrity: sha512-ZHl42g6yXhfX4PzAQ0BNvBXpt/OcbAHfubWRN6eXELK3fiNnxL7QBW1if7iizlq6iA+Mj1pwHyyUit1pz0+fgA==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true optional: true /@swc/core-linux-arm-gnueabihf@1.3.62: @@ -3150,6 +3200,15 @@ packages: cpu: [arm] os: [linux] requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm-gnueabihf@1.3.68: + resolution: {integrity: sha512-Mk8f6KCOQ2CNAR4PtWajIjS6XKSSR7ZYDOCf1GXRxhS3qEyQH7V8elWvqWYqHcT4foO60NUmxA/NOM/dQrdO1A==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true optional: true /@swc/core-linux-arm64-gnu@1.3.62: @@ -3158,6 +3217,15 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-gnu@1.3.68: + resolution: {integrity: sha512-RhBllggh9t9sIxaRgRcGrVaS7fDk6KsIqR6b9+dwU5OyDr4ZyHWw1ZaH/1/HAebuXYhNBjoNUiRtca6lKRIPgQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true optional: true /@swc/core-linux-arm64-musl@1.3.62: @@ -3166,6 +3234,15 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-musl@1.3.68: + resolution: {integrity: sha512-8K3zjU+tFgn6yGDEeD343gkKaHU9dhz77NiVkI1VzwRaT/Ag5pwl5eMQ1yStm8koNFzn3zq6rGjHfI5g2yI5Wg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true optional: true /@swc/core-linux-x64-gnu@1.3.62: @@ -3174,6 +3251,15 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-gnu@1.3.68: + resolution: {integrity: sha512-4xAnvsBOyeTL0AB8GWlRKDM/hsysJ5jr5qvdKKI3rZfJgnnxl/xSX6TJKPsJ8gygfUJ3BmfCbmUmEyeDZ3YPvA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true optional: true /@swc/core-linux-x64-musl@1.3.62: @@ -3182,6 +3268,15 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-musl@1.3.68: + resolution: {integrity: sha512-RCpaBo1fcpy1EFdjF+I7N4lfzOaHXVV0iMw/ABM+0PD6tp3V/9pxsguaZyeAHyEiUlDA6PZ4TfXv5zfnXEgW4Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true optional: true /@swc/core-win32-arm64-msvc@1.3.62: @@ -3190,6 +3285,15 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-arm64-msvc@1.3.68: + resolution: {integrity: sha512-v2WZvXrSslYEpY1nqpItyamL4DyaJinmOkXvM8Bc1LLKU5rGuvmBdjUYg/5Y+o0AUynuiWubpgHNOkBWiCvfqw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true optional: true /@swc/core-win32-ia32-msvc@1.3.62: @@ -3198,6 +3302,15 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-ia32-msvc@1.3.68: + resolution: {integrity: sha512-HH5NJrIdzkJs+1xxprie0qSCMBeL9yeEhcC1yZTzYv8bwmabOUSdtKIqS55iYP/2hLWn9CTbvKPmLOIhCopW3Q==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true optional: true /@swc/core-win32-x64-msvc@1.3.62: @@ -3206,6 +3319,15 @@ packages: cpu: [x64] os: [win32] requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-x64-msvc@1.3.68: + resolution: {integrity: sha512-9HZVtLQUgK8r/yXQdwe0VBexbIcrY6+fBROhs7AAPWdewpaUeLkwQEJk6TbYr9CQuHw26FFGg6SjwAiqXF+kgQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true optional: true /@swc/core@1.3.62: @@ -3228,6 +3350,28 @@ packages: '@swc/core-win32-arm64-msvc': 1.3.62 '@swc/core-win32-ia32-msvc': 1.3.62 '@swc/core-win32-x64-msvc': 1.3.62 + dev: true + + /@swc/core@1.3.68: + resolution: {integrity: sha512-njGQuJO+Wy06dEayt70cf0c/KI3HGjm4iW9LLViVLBuYNzJ4SSdNfzejludzufu6im+dsDJ0i3QjgWhAIcVHMQ==} + engines: {node: '>=10'} + requiresBuild: true + peerDependencies: + '@swc/helpers': ^0.5.0 + peerDependenciesMeta: + '@swc/helpers': + optional: true + optionalDependencies: + '@swc/core-darwin-arm64': 1.3.68 + '@swc/core-darwin-x64': 1.3.68 + '@swc/core-linux-arm-gnueabihf': 1.3.68 + '@swc/core-linux-arm64-gnu': 1.3.68 + '@swc/core-linux-arm64-musl': 1.3.68 + '@swc/core-linux-x64-gnu': 1.3.68 + '@swc/core-linux-x64-musl': 1.3.68 + '@swc/core-win32-arm64-msvc': 1.3.68 + '@swc/core-win32-ia32-msvc': 1.3.68 + '@swc/core-win32-x64-msvc': 1.3.68 /@swc/wasm@1.2.130: resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==} @@ -3332,7 +3476,7 @@ packages: '@types/webgl-ext': 0.0.30 '@webgpu/types': 0.1.16 long: 4.0.0 - node-fetch: 2.6.11 + node-fetch: 2.6.12 seedrandom: 3.0.5 transitivePeerDependencies: - encoding @@ -3348,7 +3492,7 @@ packages: '@types/webgl-ext': 0.0.30 '@webgpu/types': 0.1.21 long: 4.0.0 - node-fetch: 2.6.11 + node-fetch: 2.6.12 seedrandom: 3.0.5 transitivePeerDependencies: - encoding @@ -3362,7 +3506,7 @@ packages: dependencies: '@tensorflow/tfjs-core': 3.21.0 '@types/node-fetch': 2.6.4 - node-fetch: 2.6.11 + node-fetch: 2.6.12 seedrandom: 3.0.5 string_decoder: 1.3.0 transitivePeerDependencies: @@ -3377,7 +3521,7 @@ packages: dependencies: '@tensorflow/tfjs-core': 4.2.0 '@types/node-fetch': 2.6.4 - node-fetch: 2.6.11 + node-fetch: 2.6.12 seedrandom: 3.0.5 string_decoder: 1.3.0 transitivePeerDependencies: @@ -3547,15 +3691,6 @@ packages: '@types/connect': 3.4.35 '@types/node': 18.11.18 - /@types/bull@3.15.9: - resolution: {integrity: sha512-MPUcyPPQauAmynoO3ezHAmCOhbB0pWmYyijr/5ctaCqhbKWsjW0YCod38ZcLzUBprosfZ9dPqfYIcfdKjk7RNQ==} - dependencies: - '@types/ioredis': 5.0.0 - '@types/redis': 2.8.32 - transitivePeerDependencies: - - supports-color - dev: true - /@types/cacheable-request@6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: @@ -3609,7 +3744,7 @@ packages: /@types/eslint-scope@3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} dependencies: - '@types/eslint': 8.40.2 + '@types/eslint': 8.44.0 '@types/estree': 1.0.1 dev: true @@ -3620,8 +3755,8 @@ packages: '@types/json-schema': 7.0.12 dev: true - /@types/eslint@8.40.2: - resolution: {integrity: sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==} + /@types/eslint@8.44.0: + resolution: {integrity: sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==} dependencies: '@types/estree': 1.0.1 '@types/json-schema': 7.0.12 @@ -3655,8 +3790,8 @@ packages: '@types/qs': 6.9.7 '@types/serve-static': 1.15.2 - /@types/fluent-ffmpeg@2.1.20: - resolution: {integrity: sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==} + /@types/fluent-ffmpeg@2.1.21: + resolution: {integrity: sha512-+n3dy/Tegt6n+YwGZUiGq6i8Jrnt8+MoyPiW1L6J5EWUl7GSt18a/VyReecfCsvTTNBXNMIKOMHDstiQM8nJLA==} dependencies: '@types/node': 18.11.18 dev: true @@ -3719,15 +3854,6 @@ packages: /@types/http-errors@2.0.1: resolution: {integrity: sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==} - /@types/ioredis@5.0.0: - resolution: {integrity: sha512-zJbJ3FVE17CNl5KXzdeSPtdltc4tMT3TzC6fxQS0sQngkbFZ6h+0uTafsRqu+eSLIugf6Yb0Ea0SUuRr42Nk9g==} - deprecated: This is a stub types definition. ioredis provides its own type definitions, so you do not need this installed. - dependencies: - ioredis: 5.3.2 - transitivePeerDependencies: - - supports-color - dev: true - /@types/istanbul-lib-coverage@2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: true @@ -3762,8 +3888,8 @@ packages: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true - /@types/jsdom@20.0.1: - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + /@types/jsdom@21.1.1: + resolution: {integrity: sha512-cZFuoVLtzKP3gmq9eNosUL1R50U+USkbLtUQ1bYVgl/lKp0FZM7Cq4aIHAL8oIvQ17uSHi7jXPtfDOdjPwBE7A==} dependencies: '@types/node': 18.11.18 '@types/tough-cookie': 4.0.2 @@ -3778,12 +3904,12 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true - /@types/jsonld@1.5.8: - resolution: {integrity: sha512-4l5t/jDnJpqZ+i7CLTTgPcT5BYXnAnwJupb07aAokPufCV0SjDHcwctUkSTuhIuSU9yHok+WOOngIGCtpL96gw==} + /@types/jsonld@1.5.9: + resolution: {integrity: sha512-K76ImkErPYL2wGPZpNFSKp6wE+h/APecZLJrU7UfDaGqt/f+D9Rrg1aR7VdRrQ6k5DUNRZ2vn9yACwmpOr9QcA==} dev: true - /@types/jsrsasign@10.5.4: - resolution: {integrity: sha512-05S2f4lGaWgCwFHsa3OEirc4VJf/sJRfhofzxUbuFbmm6NbffPXZrnJqquQAtS3g4C8Z0L9NHgW0znmtDxNoTQ==} + /@types/jsrsasign@10.5.8: + resolution: {integrity: sha512-1oZ3TbarAhKtKUpyrCIqXpbx3ZAfoSulleJs6/UzzyYty0ut+kjRX7zHLAaHwVIuw8CBjIymwW4J2LK944HoHQ==} dev: true /@types/katex@0.16.0: @@ -3801,49 +3927,49 @@ packages: /@types/koa-bodyparser@4.3.10: resolution: {integrity: sha512-6ae05pjhmrmGhUR8GYD5qr5p9LTEMEGfGXCsK8VaSL+totwigm8+H/7MHW7K4854CMeuwRAubT8qcc/EagaeIA==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa-compose@3.2.5: resolution: {integrity: sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 /@types/koa-cors@0.0.2: resolution: {integrity: sha512-uNaDY26HUVO+2C6arK8ZFODs9mBjYprD8mlvkVe2bYdX9wzEeKtycVXPafXpUkePhMh4sffIMkhRDyedokG/QA==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa-favicon@2.0.21: resolution: {integrity: sha512-paH1nheVhijx/VduoR/RCD/qTCiX+OI/6fHLi3mZae053Ts+gUBOrKtzl3pMTDbdEBqdLolfLje3PZbb6jW0jQ==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa-logger@3.1.2: resolution: {integrity: sha512-sioTA1xlKYiIgryANWPRHBkG3XGbWftw9slWADUPC+qvPIY/yRLSrhvX7zkJwMrntub5dPO0GuAoyGGf0yitfQ==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa-mount@4.0.2: resolution: {integrity: sha512-XnuGwV8bzw22nv2WqOs5a8wCHR2VgSnLLLuBQPzNTmhyiAvH0O6c+994rQVbMaBuwQJKefUInkvKoKuk+21uew==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa-send@4.1.3: resolution: {integrity: sha512-daaTqPZlgjIJycSTNjKpHYuKhXYP30atFc1pBcy6HHqB9+vcymDgYTguPdx9tO4HMOqNyz6bz/zqpxt5eLR+VA==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true - /@types/koa-views@7.0.0(@types/koa@2.13.5)(pug@3.0.2): + /@types/koa-views@7.0.0(@types/koa@2.13.6)(pug@3.0.2): resolution: {integrity: sha512-AB/NB+oFHcLOZJYFv3bG5Af8YbwYCD9/zK0WcKALsbjI/FRKrcXTUTC64RebDrkyOkBm3bpCgpGndhAH/3YQ2Q==} deprecated: This is a stub types definition. koa-views provides its own type definitions, so you do not need this installed. dependencies: - koa-views: 7.0.2(@types/koa@2.13.5)(ejs@3.1.9)(pug@3.0.2) + koa-views: 7.0.2(@types/koa@2.13.6)(ejs@3.1.9)(pug@3.0.2) transitivePeerDependencies: - '@types/koa' - arc-templates @@ -3902,8 +4028,8 @@ packages: - whiskers dev: true - /@types/koa@2.13.5: - resolution: {integrity: sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==} + /@types/koa@2.13.6: + resolution: {integrity: sha512-diYUfp/GqfWBAiwxHtYJ/FQYIXhlEhlyaU7lB/bWQrx4Il9lCET5UwpFy3StOAohfsxxvEQ11qIJgT1j2tfBvw==} dependencies: '@types/accepts': 1.3.5 '@types/content-disposition': 0.5.5 @@ -3917,19 +4043,19 @@ packages: /@types/koa__cors@3.3.0: resolution: {integrity: sha512-FUN8YxcBakIs+walVe3+HcNP+Bxd0SB8BJHBWkglZ5C1XQWljlKcEFDG/dPiCIqwVCUbc5X0nYDlH62uEhdHMA==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa__multer@2.0.4: resolution: {integrity: sha512-WRkshXhE5rpYFUbbtAjyMhdOOSdbu1XX+2AQlRNM6AZtgxd0/WXMU4lrP7e9tk5HWVTWbx8DOOsVBmfHjSGJ4w==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/koa__router@8.0.11: resolution: {integrity: sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==} dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 dev: true /@types/long@4.0.2: @@ -3967,7 +4093,7 @@ packages: /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 20.4.1 + '@types/node': 18.11.18 form-data: 3.0.1 dev: false @@ -3990,6 +4116,7 @@ packages: /@types/node@20.4.1: resolution: {integrity: sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==} + dev: true /@types/nodemailer@6.4.8: resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==} @@ -4045,8 +4172,8 @@ packages: resolution: {integrity: sha512-PG5aLpW6PJOeV2fHRslP4IOMWn+G+Uq8CfnyJ+PDS8ndCbU+soO+fB3NKCKo0p/Jh2Y4aPaiQZsrOXFdzpcA6g==} dev: true - /@types/qrcode@1.5.0: - resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==} + /@types/qrcode@1.5.1: + resolution: {integrity: sha512-HpSN675K0PmxIDRpjMI3Mc2GiKo3dNu+X/F5SoItiaDS1lVfgC6Wac1c5lQDfKWbTJUSHWiHKzpJpBZG7k9gaA==} dependencies: '@types/node': 18.11.18 dev: true @@ -4065,12 +4192,6 @@ packages: resolution: {integrity: sha512-GSMb93iSA8KKFDgVL2Wzs/kqrHMJcU8xhLdwI5omoACcj7K18SacklLtY1C4G02HC5drd6GygtsIaGbfxJSe0g==} dev: true - /@types/redis@2.8.32: - resolution: {integrity: sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==} - dependencies: - '@types/node': 18.11.18 - dev: true - /@types/redis@4.0.11: resolution: {integrity: sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==} deprecated: This is a stub types definition. redis provides its own type definitions, so you do not need this installed. @@ -4118,12 +4239,6 @@ packages: '@types/mime': 3.0.1 '@types/node': 18.11.18 - /@types/sharp@0.31.1: - resolution: {integrity: sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==} - dependencies: - '@types/node': 18.11.18 - dev: true - /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} dev: true @@ -4182,6 +4297,10 @@ packages: resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} dev: true + /@types/uuid@9.0.2: + resolution: {integrity: sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==} + dev: true + /@types/vinyl-fs@3.0.2: resolution: {integrity: sha512-ctNcmmzbMIKooXjRkyyUCOu2Z4AyqibL+RhXoF3pb7K7j+ezItnakmpm31LymkYHSIM5ey0tjIFzTvFOTSBCGw==} dependencies: @@ -4221,6 +4340,13 @@ packages: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} dependencies: '@types/node': 18.11.18 + dev: false + + /@types/ws@8.5.5: + resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} + dependencies: + '@types/node': 18.11.18 + dev: true /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} @@ -4266,7 +4392,7 @@ packages: ignore: 5.2.4 natural-compare-lite: 1.4.0 regexpp: 3.2.0 - semver: 7.5.1 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.9.4) typescript: 4.9.4 transitivePeerDependencies: @@ -4340,7 +4466,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.1 + semver: 7.5.4 tsutils: 3.21.0(typescript@4.9.4) typescript: 4.9.4 transitivePeerDependencies: @@ -4361,7 +4487,7 @@ packages: eslint: 8.42.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.42.0) - semver: 7.5.1 + semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript @@ -4671,6 +4797,14 @@ packages: acorn-walk: 8.2.0 dev: false + /acorn-import-assertions@1.9.0(acorn@8.10.0): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.10.0 + dev: true + /acorn-import-assertions@1.9.0(acorn@8.9.0): resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} peerDependencies: @@ -4679,12 +4813,12 @@ packages: acorn: 8.9.0 dev: true - /acorn-jsx@5.3.2(acorn@8.9.0): + /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.9.0 + acorn: 8.10.0 /acorn-walk@7.2.0: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} @@ -4700,6 +4834,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + /acorn@8.9.0: resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} engines: {node: '>=0.4.0'} @@ -4726,6 +4865,15 @@ packages: transitivePeerDependencies: - supports-color + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + dev: false + /agentkeepalive@4.3.0: resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} engines: {node: '>= 8.0.0'} @@ -5227,8 +5375,8 @@ packages: arrify: 3.0.0 callsites: 4.0.0 cbor: 8.1.0 - chalk: 5.2.0 - chokidar: 3.3.1 + chalk: 5.3.0 + chokidar: 3.5.3 chunkd: 2.0.1 ci-info: 3.8.0 ci-parallel-vars: 1.0.1 @@ -5273,8 +5421,8 @@ packages: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - /aws-sdk@2.1277.0: - resolution: {integrity: sha512-cEZ0rg0j3STtLX6rba5tHMrV/KrhXKLtSleleF2IdTFzUjqRvxI54Pqc51w2D7tgAPUgEhMB4Q/ruKPqB8w+2Q==} + /aws-sdk@2.1413.0: + resolution: {integrity: sha512-vKpjC7iRwOhgv7P0xw90mVGO//2rqVPJKyYIs7uxLzSV0JzriVD+yqktOu/Hz6/phOmAd1cMIeFgpEC9ynrppg==} engines: {node: '>= 10.0.0'} dependencies: buffer: 4.9.2 @@ -5286,7 +5434,7 @@ packages: url: 0.10.3 util: 0.12.5 uuid: 8.0.0 - xml2js: 0.4.19 + xml2js: 0.5.0 dev: false /aws-sign2@0.7.0: @@ -5298,7 +5446,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: false @@ -5324,14 +5472,14 @@ packages: /axios@1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug dev: false - /babel-eslint@10.1.0(eslint@8.42.0): + /babel-eslint@10.1.0(eslint@8.44.0): resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==} engines: {node: '>=6'} deprecated: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. @@ -5342,7 +5490,7 @@ packages: '@babel/parser': 7.22.5 '@babel/traverse': 7.22.5 '@babel/types': 7.22.5 - eslint: 8.42.0 + eslint: 8.44.0 eslint-visitor-keys: 1.3.0 resolve: 1.22.2 transitivePeerDependencies: @@ -5531,7 +5679,7 @@ packages: engines: {node: '>=12'} dependencies: bin-version: 6.0.0 - semver: 7.5.3 + semver: 7.5.4 semver-truncate: 3.0.0 dev: true @@ -5571,13 +5719,8 @@ packages: resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} dev: true - /blurhash@1.1.5: - resolution: {integrity: sha512-a+LO3A2DfxTaTztsmkbLYmUzUeApi0LZuKalwbNmqAHR6HhJGMt1qSV/R3wc+w4DL28holjqO3Bg74aUGavGjg==} - dev: false - /blurhash@2.0.5: resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} - dev: true /bmp-js@0.1.0: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} @@ -5658,9 +5801,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001509 - electron-to-chromium: 1.4.442 - node-releases: 2.0.12 + caniuse-lite: 1.0.30001514 + electron-to-chromium: 1.4.455 + node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) /bs-logger@0.2.6: @@ -5735,7 +5878,7 @@ packages: ioredis: 5.3.2 lodash: 4.17.21 msgpackr: 1.9.5 - semver: 7.5.1 + semver: 7.5.4 uuid: 8.3.2 transitivePeerDependencies: - supports-color @@ -5884,8 +6027,8 @@ packages: resolution: {integrity: sha512-Gf3pFp97loixG5w83NVb09DMI+WzkVXLn4H2abxv7DXxHUyKYbZc5qpEqAQy/mDFO6bAnNQh4hZ8lLeGlPTZQg==} dev: true - /caniuse-lite@1.0.30001509: - resolution: {integrity: sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==} + /caniuse-lite@1.0.30001514: + resolution: {integrity: sha512-ENcIpYBmwAAOm/V2cXgM7rZUrKKaqisZl4ZAI520FIkqGXUxJjmaIssbRW5HVVR5tyV6ygTLIm15aU8LUmQSaQ==} /canonicalize@1.0.8: resolution: {integrity: sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==} @@ -5940,8 +6083,8 @@ packages: ansi-styles: 4.3.0 supports-color: 7.2.0 - /chalk@5.2.0: - resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} /char-regex@1.0.2: @@ -6026,20 +6169,6 @@ packages: lodash.some: 4.6.0 dev: false - /chokidar@3.3.1: - resolution: {integrity: sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.3.0 - optionalDependencies: - fsevents: 2.1.3 - /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -6053,7 +6182,6 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 - dev: true /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -6467,7 +6595,7 @@ packages: js-string-escape: 1.0.1 lodash: 4.17.21 md5-hex: 3.0.1 - semver: 7.5.1 + semver: 7.5.4 well-known-symbols: 2.0.0 dev: true @@ -6938,7 +7066,7 @@ packages: pretty-bytes: 5.6.0 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.5.1 + semver: 7.5.4 supports-color: 8.1.1 tmp: 0.2.1 untildify: 4.0.0 @@ -7009,6 +7137,17 @@ packages: dependencies: ms: 2.0.0 + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -7019,6 +7158,7 @@ packages: dependencies: ms: 2.1.3 supports-color: 8.1.1 + dev: true /debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} @@ -7185,6 +7325,7 @@ packages: /denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} + dev: false /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} @@ -7386,7 +7527,7 @@ packages: dependencies: commander: 2.20.3 lru-cache: 4.1.5 - semver: 5.7.1 + semver: 5.7.2 sigmund: 1.0.1 /ee-first@1.1.1: @@ -7402,6 +7543,10 @@ packages: /electron-to-chromium@1.4.442: resolution: {integrity: sha512-RkrZF//Ya+0aJq2NM3OdisNh5ZodZq1rdXOS96G8DdDgpDKqKE81yTbbQ3F/4CKm1JBPsGu1Lp/akkna2xO06Q==} + dev: true + + /electron-to-chromium@1.4.455: + resolution: {integrity: sha512-8tgdX0Odl24LtmLwxotpJCVjIndN559AvaOtd67u+2mo+IDsgsTF580NB+uuDCqsHw8yFg53l5+imFV9Fw3cbA==} /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -7793,7 +7938,7 @@ packages: minimatch: 3.1.2 object.values: 1.1.6 resolve: 1.22.2 - semver: 6.3.0 + semver: 6.3.1 tsconfig-paths: 3.14.2 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -7813,7 +7958,7 @@ packages: ignore: 5.2.4 minimatch: 3.1.2 resolve: 1.22.2 - semver: 6.3.0 + semver: 6.3.1 dev: true /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.42.0)(prettier@2.8.8): @@ -7946,13 +8091,70 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color + 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.5.1 + '@eslint/eslintrc': 2.1.0 + '@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.0 + eslint-visitor-keys: 3.4.1 + espree: 9.6.0 + 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 /espree@9.5.2: resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.9.0 - acorn-jsx: 5.3.2(acorn@8.9.0) + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.1 + dev: true + + /espree@9.6.0: + resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) eslint-visitor-keys: 3.4.1 /esprima@2.7.3: @@ -8540,6 +8742,16 @@ packages: tabbable: 6.2.0 dev: true + /follow-redirects@1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -8711,20 +8923,11 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@2.1.3: - resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - deprecated: '"Please update to latest v2.3 or v2.2"' - requiresBuild: true - optional: true - /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /fulcon@1.0.2: @@ -8930,7 +9133,7 @@ packages: dependencies: anymatch: 2.0.0 async-done: 1.3.2 - chokidar: 3.3.1 + chokidar: 3.5.3 is-negated-glob: 1.0.0 just-debounce: 1.1.0 normalize-path: 3.0.0 @@ -8946,7 +9149,7 @@ packages: dependencies: foreground-child: 3.1.1 jackspeak: 2.2.1 - minimatch: 9.0.2 + minimatch: 9.0.3 minipass: 5.0.0 path-scurry: 1.10.1 dev: false @@ -9490,7 +9693,7 @@ packages: engines: {node: '>= 4.5.0'} dependencies: agent-base: 4.3.0 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 transitivePeerDependencies: - supports-color dev: false @@ -9505,6 +9708,16 @@ packages: transitivePeerDependencies: - supports-color + /https-proxy-agent@7.0.1: + resolution: {integrity: sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==} + 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'} @@ -9689,6 +9902,7 @@ packages: standard-as-callback: 2.1.0 transitivePeerDependencies: - supports-color + dev: false /iota-array@1.0.0: resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} @@ -9702,8 +9916,8 @@ packages: sprintf-js: 1.1.2 dev: false - /ip-cidr@3.0.11: - resolution: {integrity: sha512-6pf3APV0cRWy7vk0ealQt7UeWPqpT4RQM0bR0miVY/XRiBV8hIkPSkEHctv1+GAUPIwT9qpUL57deYlYca9UEA==} + /ip-cidr@3.1.0: + resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==} engines: {node: '>=10.0.0'} dependencies: ip-address: 7.1.0 @@ -10184,7 +10398,7 @@ packages: '@babel/parser': 7.22.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: true @@ -10997,7 +11211,7 @@ packages: jest-util: 29.6.0 natural-compare: 1.4.0 pretty-format: 29.6.0 - semver: 7.5.3 + semver: 7.5.4 transitivePeerDependencies: - supports-color dev: true @@ -11090,7 +11304,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.3.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -11265,7 +11479,7 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.9.0 + acorn: 8.10.0 acorn-globals: 6.0.0 cssom: 0.4.4 cssstyle: 2.3.0 @@ -11366,7 +11580,7 @@ packages: /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - /json5-loader@4.0.1(webpack@5.85.1): + /json5-loader@4.0.1(webpack@5.88.1): resolution: {integrity: sha512-c9viNZlZTz0MTIcf/4qvek5Dz1/PU3DNCB4PwUhlEZIV3qb1bSD6vQQymlV17/Wm6ncra1aCvmIPsuRj+KfEEg==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -11375,7 +11589,7 @@ packages: json5: 2.2.3 loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68) dev: true /json5@1.0.2: @@ -11446,8 +11660,8 @@ packages: verror: 1.10.0 dev: true - /jsrsasign@10.6.1: - resolution: {integrity: sha512-emiQ05haY9CRj1Ho/LiuCqr/+8RgJuWdiHYNglIg2Qjfz0n+pnUq9I2QHplXuOMO2EnAW1oCGC1++aU5VoWSlw==} + /jsrsasign@10.8.6: + resolution: {integrity: sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==} dev: false /jssha@3.3.0: @@ -11531,18 +11745,19 @@ packages: dependencies: '@types/co-body': 6.1.0 '@types/formidable': 2.0.6 - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 co-body: 6.1.0 formidable: 2.1.2 zod: 3.21.4 dev: false - /koa-bodyparser@4.3.0: - resolution: {integrity: sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==} + /koa-bodyparser@4.4.1: + resolution: {integrity: sha512-kBH3IYPMb+iAXnrxIhXnW+gXV8OTzCu8VPDqvcDHW9SQrbkHmqPQtiZwrltNmSq6/lpipHnT7k7PsjlVD7kK0w==} engines: {node: '>=8.0.0'} dependencies: co-body: 6.1.0 copy-to: 2.0.1 + type-is: 1.6.18 dev: false /koa-compose@4.1.0: @@ -11629,13 +11844,13 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 koa-send: 5.0.1 transitivePeerDependencies: - supports-color dev: false - /koa-views@7.0.2(@types/koa@2.13.5)(ejs@3.1.9)(pug@3.0.2): + /koa-views@7.0.2(@types/koa@2.13.6)(ejs@3.1.9)(pug@3.0.2): resolution: {integrity: sha512-dvx3mdVeSVuIPEaKAoGbxLcenudvhl821xxyuRbcoA+bOJ2dvN8wlGjkLu0ZFMlkCscXZV6lzxy28rafeazI/w==} deprecated: This package is deprecated, please use the new fork @ladjs/koa-views. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/koa-views for updates and release changelog peerDependencies: @@ -11644,7 +11859,7 @@ packages: '@types/koa': optional: true dependencies: - '@types/koa': 2.13.5 + '@types/koa': 2.13.6 consolidate: 0.16.0(ejs@3.1.9)(pug@3.0.2) debug: 4.3.4(supports-color@8.1.1) get-paths: 0.0.7 @@ -11711,6 +11926,37 @@ packages: /koa@2.13.4: resolution: {integrity: sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} + dependencies: + accepts: 1.3.8 + cache-content-type: 1.0.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookies: 0.8.0 + debug: 4.3.3 + delegates: 1.0.0 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + fresh: 0.5.2 + http-assert: 1.5.0 + http-errors: 1.8.1 + is-generator-function: 1.0.10 + koa-compose: 4.1.0 + koa-convert: 2.0.0 + on-finished: 2.4.1 + only: 0.0.2 + parseurl: 1.3.3 + statuses: 1.5.0 + type-is: 1.6.18 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /koa@2.14.2: + resolution: {integrity: sha512-VFI2bpJaodz6P7x2uyLiX6RLYpZmOJqNmoCst/Yyd7hQlszyPwG/I9CQJ63nOtKSxpt5M7NH67V6nJL2BwCl7g==} + engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} dependencies: accepts: 1.3.8 cache-content-type: 1.0.1 @@ -11914,6 +12160,7 @@ packages: /lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + dev: false /lodash.difference@4.5.0: resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} @@ -11937,6 +12184,7 @@ packages: /lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + dev: false /lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} @@ -12073,7 +12321,7 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} dependencies: - semver: 6.3.0 + semver: 6.3.1 /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -12334,8 +12582,8 @@ packages: dependencies: brace-expansion: 2.0.1 - /minimatch@9.0.2: - resolution: {integrity: sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==} + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 @@ -12458,6 +12706,12 @@ packages: hasBin: true dev: false + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + /mocha@10.2.0: resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} engines: {node: '>= 14.0.0'} @@ -12465,7 +12719,7 @@ packages: dependencies: ansi-colors: 4.1.1 browser-stdout: 1.3.1 - chokidar: 3.3.1 + chokidar: 3.5.3 debug: 4.3.4(supports-color@8.1.1) diff: 5.0.0 escape-string-regexp: 4.0.0 @@ -12637,7 +12891,7 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.2.4 transitivePeerDependencies: @@ -12669,7 +12923,7 @@ packages: resolution: {integrity: sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==} engines: {node: '>=10'} dependencies: - semver: 7.5.1 + semver: 7.5.4 dev: false /node-addon-api@5.1.0: @@ -12700,6 +12954,18 @@ packages: dependencies: whatwg-url: 5.0.0 + /node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + /node-fetch@3.3.1: resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -12732,7 +12998,7 @@ packages: nopt: 6.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.5.1 + semver: 7.5.4 tar: 6.1.15 which: 2.0.2 transitivePeerDependencies: @@ -12743,8 +13009,8 @@ packages: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: true - /node-releases@2.0.12: - resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} /nodemailer@6.9.3: resolution: {integrity: sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==} @@ -12775,7 +13041,7 @@ packages: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.2 - semver: 5.7.1 + semver: 5.7.2 validate-npm-package-license: 3.0.4 dev: true @@ -13058,7 +13324,7 @@ packages: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} dependencies: - '@aashutoshrathi/word-wrap': 1.2.5 + '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 @@ -13093,8 +13359,8 @@ packages: resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} dev: true - /otpauth@9.1.2: - resolution: {integrity: sha512-iI5nlVvMFP3aTPdjG/fnC4mhVJ/KZOSnBrvo/VnYHUwlTp9jVLjAe2B3i3pyCH+3/E5jYQRSvuHk/8oas3870g==} + /otpauth@9.1.3: + resolution: {integrity: sha512-lWy9GE2ASTgOwhH1dQsZwOIcVl2HopXNnTTtBXuhO4VZJ9AXT8Zx1ifTGaFUiXVFOzbHD/W4hDqMd/ZRDLkJEw==} dependencies: jssha: 3.3.0 dev: false @@ -13410,12 +13676,12 @@ packages: engines: {node: '>=4.0.0'} dev: false - /pg-pool@3.6.1(pg@8.11.0): + /pg-pool@3.6.1(pg@8.11.1): resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==} peerDependencies: pg: '>=8.0' dependencies: - pg: 8.11.0 + pg: 8.11.1 dev: false /pg-protocol@1.6.0: @@ -13433,8 +13699,8 @@ packages: postgres-interval: 1.2.0 dev: false - /pg@8.11.0: - resolution: {integrity: sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==} + /pg@8.11.1: + resolution: {integrity: sha512-utdq2obft07MxaDg0zBJI+l/M3mBRfIpEN3iSemsz0G5F2/VXx+XzqF4oxrbIZXQxt2AZzIUzyVg/YM6xOP/WQ==} engines: {node: '>= 8.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -13445,7 +13711,7 @@ packages: buffer-writer: 2.0.0 packet-reader: 1.0.0 pg-connection-string: 2.6.1 - pg-pool: 3.6.1(pg@8.11.0) + pg-pool: 3.6.1(pg@8.11.1) pg-protocol: 1.6.0 pg-types: 2.2.0 pgpass: 1.0.5 @@ -14273,8 +14539,8 @@ packages: setimmediate: 1.0.5 dev: false - /re2@1.19.0: - resolution: {integrity: sha512-y0LcLZgBF3L7mDtNfbghb7dCmChYQO2QsUGklNueAJUH+HAZO8UZUubgNsf6OxRTAQpeE4KMPR7vcpK3+Q+GiA==} + /re2@1.19.1: + resolution: {integrity: sha512-pML2LZvGdjESWAsufwlFwF+TBauIx7ItgcPIL0KiiZ9GrJ5OU3aJEc/EZvygB32nhjrRxe6QQFbie79QhT7gVA==} requiresBuild: true dependencies: install-artifact-from-github: 1.3.3 @@ -14368,18 +14634,11 @@ packages: minimatch: 5.1.6 dev: false - /readdirp@3.3.0: - resolution: {integrity: sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 - dev: true /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} @@ -14410,6 +14669,7 @@ packages: /redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} + dev: false /redis-info@3.1.0: resolution: {integrity: sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg==} @@ -14427,6 +14687,7 @@ packages: engines: {node: '>=4'} dependencies: redis-errors: 1.2.0 + dev: false /redis-semaphore@5.3.1(ioredis@5.3.2): resolution: {integrity: sha512-oUpxxfxSbh5eT0mvVpz2d4Qlg2CsaoQkeo80/v6CU2l97zO0u6NPgc9/zQZa9KGR3/93b0igtSct3hEFh8Ei8w==} @@ -14885,15 +15146,15 @@ packages: resolution: {integrity: sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==} engines: {node: '>=12'} dependencies: - semver: 7.5.1 + semver: 7.5.4 dev: true - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true /semver@7.3.8: @@ -14911,13 +15172,12 @@ packages: dependencies: lru-cache: 6.0.0 - /semver@7.5.3: - resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 - dev: true /serialize-error@7.0.1: resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} @@ -14992,7 +15252,7 @@ packages: detect-libc: 2.0.1 node-addon-api: 6.1.0 prebuild-install: 7.1.1 - semver: 7.5.1 + semver: 7.5.4 simple-get: 4.0.1 tar-fs: 2.1.1 tunnel-agent: 0.6.0 @@ -15317,6 +15577,7 @@ packages: /standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + dev: false /start-server-and-test@1.15.2: resolution: {integrity: sha512-t5xJX04Hg7hqxiKHMJBz/n4zIMsE6G7hpAcerFAH+4Vh9le/LeyFcJERJM7WLiPygWF9TOg33oroJF1XOzJtYQ==} @@ -15655,6 +15916,16 @@ packages: webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) dev: true + /swc-loader@0.2.3(@swc/core@1.3.68)(webpack@5.88.1): + resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} + peerDependencies: + '@swc/core': ^1.2.147 + webpack: '>=2' + dependencies: + '@swc/core': 1.3.68 + webpack: 5.88.1(@swc/core@1.3.68) + dev: true + /swiper@10.0.4: resolution: {integrity: sha512-DlNR3KiaVkPep6RraZ2tNr7lvyuzELuR+4NZr4wO42t0UworIO3DxDlz8b5Q3uUioh7cJad99EdRJLkPF+r8Ag==} engines: {node: '>= 4.7.0'} @@ -15774,6 +16045,31 @@ packages: webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) dev: true + /terser-webpack-plugin@5.3.9(@swc/core@1.3.68)(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.18 + '@swc/core': 1.3.68 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.18.2 + webpack: 5.88.1(@swc/core@1.3.68) + dev: true + /terser@5.18.2: resolution: {integrity: sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==} engines: {node: '>=10'} @@ -15789,11 +16085,11 @@ packages: resolution: {integrity: sha512-2fD76ka9nO/C616R0fq+M9Zu91DA3vEfyozp0jlxaJOBmpfeprtgRP3cqVweZh2darE1kK/DazoxZ65g7WU99Q==} dev: false - /tesseract.js@3.0.3(eslint@8.42.0): + /tesseract.js@3.0.3(eslint@8.44.0): resolution: {integrity: sha512-eZ1+OGWvF5IMExAzIwnDf3S3kf2FeC+i4qrMTRvBSlZeHc3ONy0vCmaKmBQz6scjB6C1W2w2x0r4lCEh95qBnw==} requiresBuild: true dependencies: - babel-eslint: 10.1.0(eslint@8.42.0) + babel-eslint: 10.1.0(eslint@8.44.0) bmp-js: 0.1.0 file-type: 12.4.2 idb-keyval: 3.2.0 @@ -16093,13 +16389,13 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.5.1 + semver: 7.5.4 typescript: 4.9.4 yargs-parser: 21.1.1 dev: true - /ts-loader@9.4.3(typescript@5.1.3)(webpack@5.85.1): - resolution: {integrity: sha512-n3hBnm6ozJYzwiwt5YRiJZkzktftRpMiBApHaJPoWLA+qetQBAXkHqCLM6nwSdRDimqVtA5ocIkcTRLMTt7yzA==} + /ts-loader@9.4.4(typescript@5.1.6)(webpack@5.88.1): + resolution: {integrity: sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==} engines: {node: '>=12.0.0'} peerDependencies: typescript: '*' @@ -16108,9 +16404,9 @@ packages: chalk: 4.1.2 enhanced-resolve: 5.15.0 micromatch: 4.0.5 - semver: 7.5.1 - typescript: 5.1.3 - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) + semver: 7.5.4 + typescript: 5.1.6 + webpack: 5.88.1(@swc/core@1.3.68) dev: true /ts-node@10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3): @@ -16144,7 +16440,7 @@ packages: yn: 3.1.1 dev: true - /ts-node@10.9.1(@swc/core@1.3.62)(@types/node@18.11.18)(typescript@5.1.3): + /ts-node@10.9.1(@swc/core@1.3.68)(@types/node@18.11.18)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -16159,7 +16455,7 @@ packages: optional: true dependencies: '@cspotcode/source-map-support': 0.8.1 - '@swc/core': 1.3.62 + '@swc/core': 1.3.68 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 @@ -16171,7 +16467,7 @@ packages: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.1.3 + typescript: 5.1.6 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 @@ -16341,8 +16637,8 @@ packages: typescript: 4.9.4 dev: true - /typeorm@0.3.11(ioredis@5.3.2)(pg@8.11.0)(ts-node@10.9.1): - resolution: {integrity: sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==} + /typeorm@0.3.17(ioredis@5.3.2)(pg@8.11.1)(ts-node@10.9.1): + resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==} engines: {node: '>= 12.9.0'} hasBin: true peerDependencies: @@ -16351,9 +16647,9 @@ packages: better-sqlite3: ^7.1.2 || ^8.0.0 hdb-pool: ^0.1.6 ioredis: ^5.0.4 - mongodb: ^3.6.0 - mssql: ^7.3.0 - mysql2: ^2.2.5 + mongodb: ^5.2.0 + mssql: ^9.1.1 + mysql2: ^2.2.5 || ^3.0.1 oracledb: ^5.1.0 pg: ^8.5.1 pg-native: ^3.0.0 @@ -16407,17 +16703,15 @@ packages: date-fns: 2.30.0 debug: 4.3.4(supports-color@8.1.1) dotenv: 16.3.1 - glob: 7.2.3 + glob: 8.1.0 ioredis: 5.3.2 - js-yaml: 4.1.0 - mkdirp: 1.0.4 - pg: 8.11.0 + mkdirp: 2.1.6 + pg: 8.11.1 reflect-metadata: 0.1.13 sha.js: 2.4.11 - ts-node: 10.9.1(@swc/core@1.3.62)(@types/node@18.11.18)(typescript@5.1.3) + ts-node: 10.9.1(@swc/core@1.3.68)(@types/node@18.11.18)(typescript@5.1.6) tslib: 2.6.0 - uuid: 8.3.2 - xml2js: 0.4.23 + uuid: 9.0.0 yargs: 17.7.2 transitivePeerDependencies: - supports-color @@ -16438,12 +16732,12 @@ packages: resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} engines: {node: '>=14.17'} hasBin: true + dev: true /typescript@5.1.6: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} engines: {node: '>=14.17'} hasBin: true - dev: true /ulid@2.3.0: resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} @@ -16633,7 +16927,7 @@ packages: is-arguments: 1.1.1 is-generator-function: 1.0.10 is-typed-array: 1.1.10 - which-typed-array: 1.1.9 + which-typed-array: 1.1.10 dev: false /uuid@3.4.0: @@ -16942,17 +17236,16 @@ packages: graceful-fs: 4.2.11 dev: true - /web-push@3.6.1: - resolution: {integrity: sha512-+eN2/4Ybu+nkRgXqlPXUzqeA5BgQ7J4StYJM/e2uJpsSIGhkZJFrTlCx+ow9sD0mn+4jgbo2FkFoMBKftl49ZQ==} - engines: {node: '>= 6'} + /web-push@3.6.3: + resolution: {integrity: sha512-3RlA0lRmLcwlHCRR94Tz+Fw6wPtm0lFm8oyukQunlEIarANxE84Ox9XBgF4+jNlXgO40DIwblOiC43oR46helA==} + engines: {node: '>= 16'} hasBin: true dependencies: asn1.js: 5.4.1 http_ece: 1.1.0 - https-proxy-agent: 5.0.1 + https-proxy-agent: 7.0.1 jws: 4.0.0 minimist: 1.2.8 - urlsafe-base64: 1.0.0 transitivePeerDependencies: - supports-color dev: false @@ -17066,6 +17359,46 @@ packages: - uglify-js dev: true + /webpack@5.88.1(@swc/core@1.3.68): + 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.9 + 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.68)(webpack@5.88.1) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + /websocket@1.0.34: resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} engines: {node: '>=4.0.0'} @@ -17153,6 +17486,18 @@ packages: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} dev: false + /which-typed-array@1.1.10: + resolution: {integrity: sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + dev: false + /which-typed-array@1.1.9: resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} engines: {node: '>= 0.4'} @@ -17163,6 +17508,7 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 is-typed-array: 1.1.10 + dev: true /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} @@ -17323,21 +17669,6 @@ packages: engines: {node: '>=12'} dev: false - /xml2js@0.4.19: - resolution: {integrity: sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==} - dependencies: - sax: 1.2.1 - xmlbuilder: 9.0.7 - dev: false - - /xml2js@0.4.23: - resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} - engines: {node: '>=4.0.0'} - dependencies: - sax: 1.2.4 - xmlbuilder: 11.0.1 - dev: false - /xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} @@ -17351,11 +17682,6 @@ packages: engines: {node: '>=4.0'} dev: false - /xmlbuilder@9.0.7: - resolution: {integrity: sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==} - engines: {node: '>=4.0'} - dev: false - /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -17562,8 +17888,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/15fd9504f943763a057ff803ee2009ec0524c96b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/15fd9504f943763a057ff803ee2009ec0524c96b} + github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b} name: emojilib version: 3.0.10 dev: true From 89c1ddd27c4a9f0fc5a9dd4e9d5eb14f49faf21f Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 21:35:20 -0700 Subject: [PATCH 041/162] docs: :memo: join server --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 2e6907e30..18b37ae02 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,14 @@ # 🌠 Getting started +Want to just join a Calckey server? View the list here, pick one, and join: + +### https://calckey.org/join + +--- + +Want to make your own? Keep reading! + This guide will work for both **starting from scratch** and **migrating from Misskey**. ## 🔰 Easy installers From 46dbd33b4ee86eb0cb0d3085bb4bf435299f8ac1 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Mon, 10 Jul 2023 22:34:04 -0700 Subject: [PATCH 042/162] chore: vite conf changes --- packages/client/vite.config.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index 6c644660e..592628e83 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -23,9 +23,9 @@ const extensions = [ ]; export default defineConfig(({ command, mode }) => { - fs.mkdirSync(__dirname + "/../../built", { recursive: true }); + fs.mkdirSync(`${__dirname}/../../built`, { recursive: true }); fs.writeFileSync( - __dirname + "/../../built/meta.json", + `${__dirname}/../../built/meta.json`, JSON.stringify({ version: meta.version }), "utf-8", ); @@ -40,15 +40,16 @@ export default defineConfig(({ command, mode }) => { pluginJson5(), viteCompression({ algorithm: "brotliCompress", + verbose: false, }), ], resolve: { extensions, alias: { - "@/": __dirname + "/src/", - "/client-assets/": __dirname + "/assets/", - "/static-assets/": __dirname + "/../backend/assets/", + "@/": `${__dirname}/src/`, + "/client-assets/": `${__dirname}/assets/`, + "/static-assets/": `${__dirname}/../backend/assets/`, }, }, @@ -82,7 +83,7 @@ export default defineConfig(({ command, mode }) => { }, cssCodeSplit: true, assetsInlineLimit: 0, - outDir: __dirname + "/../../built/_client_dist_", + outDir: `${__dirname}/../../built/_client_dist_`, assetsDir: ".", emptyOutDir: false, sourcemap: process.env.NODE_ENV === "development", @@ -94,5 +95,7 @@ export default defineConfig(({ command, mode }) => { optimizeDeps: { auto: true, }, + + logLevel: 'warn', }; }); From f34161f6cd430fe8e43d4828e93e7aba807b542c Mon Sep 17 00:00:00 2001 From: DVD <zjdavid.2003@gmail.com> Date: Tue, 11 Jul 2023 21:27:10 +0800 Subject: [PATCH 043/162] Fixes image cropper ui --- packages/client/src/components/MkCropperDialog.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkCropperDialog.vue b/packages/client/src/components/MkCropperDialog.vue index b7d25bd35..3d8ea46e8 100644 --- a/packages/client/src/components/MkCropperDialog.vue +++ b/packages/client/src/components/MkCropperDialog.vue @@ -13,7 +13,7 @@ <template #default="{ width, height }"> <div class="mk-cropper-dialog" - :style="`--vw: ${width}px; --vh: ${height}px;`" + :style="`--vw: ${width ? `${width}px` : '100%'}; --vh: ${height ? `${height}px` : '100%'};`" > <Transition name="fade"> <div v-if="loading" class="loading"> From 22cc5a5953b8d34201d8b4a1b3989feae3f106ff Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 15:05:43 -0700 Subject: [PATCH 044/162] docs: :memo: FoundKey migration docs Co-authored-by: Jeder <jeder@noreply.codeberg.org> Superscedes #10471 --- CALCKEY.md | 2 +- CHANGELOG.md | 2 +- README.md | 4 ++-- docs/migrate.md | 16 +++++++++------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CALCKEY.md b/CALCKEY.md index 5a8bbd8ff..619155238 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -137,7 +137,7 @@ - 👍 also triggers generic like/favorite - [Add additional background for acrylic popups if backdrop-filter is unsupported](https://github.com/misskey-dev/misskey/pull/8671) - [Add parameters to MFM rotate](https://github.com/misskey-dev/misskey/pull/8549) -- Many changes from [Foundkey](https://akkoma.dev/FoundKeyGang/Foundkey) +- Many changes from [FoundKey](https://akkoma.dev/FoundKeyGang/FoundKey) - https://akkoma.dev/FoundKeyGang/FoundKey/commit/0ece67b04c3f0365057624c1068808276ccab981: refactor pages/auth.form.vue to composition API - https://akkoma.dev/FoundKeyGang/FoundKey/commit/4bc9610d8bf5af736b5e89e4782395705de45d7d: remove unnecessary joins - https://akkoma.dev/FoundKeyGang/FoundKey/commit/9ee609d70082f7a6dc119a5d83c0e7c5e1208676: enhance privacy of notes diff --git a/CHANGELOG.md b/CHANGELOG.md index 988156a72..b9a998f62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2704,7 +2704,7 @@ Co-committed-by: naskya <naskya@noreply.codeberg.org> Passwords will be automatically re-hashed on sign-in. All new password hashes will be argon2 by default. This uses argon2id and is not configurable. In the very unlikely case someone has more specific needs, a fork is recommended. ChangeLog: Added Co-authored-by: Chloe Kudryavtsev <code@toast.bunkerlabs.net> -Breaks Calckey -> Misskey migration, but fixes Foundkey -> Calckey migration +Breaks Calckey -> Misskey migration, but fixes FoundKey -> Calckey migration - Add argon diff --git a/README.md b/README.md index 18b37ae02..a2465cc09 100644 --- a/README.md +++ b/README.md @@ -216,9 +216,9 @@ Please don't use ElasticSearch unless you already have an ElasticSearch setup an - Edit `.config/default.yml`, making sure to fill out required fields. - Also copy and edit `.config/docker_example.env` to `.config/docker.env` if you're using Docker. -## 🚚 Migrating from Misskey to Calckey +## 🚚 Migrating from Misskey/FoundKey to Calckey -For migrating from Misskey v13, Misskey v12, and Foundkey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md). +For migrating from Misskey v13, Misskey v12, and FoundKey, read [this document](https://codeberg.org/calckey/calckey/src/branch/develop/docs/migrate.md). ## 🌐 Web proxy diff --git a/docs/migrate.md b/docs/migrate.md index ae7df286a..7d5c5639f 100644 --- a/docs/migrate.md +++ b/docs/migrate.md @@ -1,10 +1,11 @@ -# 🚚 Migrating from Misskey to Calckey +# 🚚 Migrating from Misskey/FoundKey to Calckey -The following procedure may not work depending on your environment and version of Misskey. +All the guides below assume you're starting in the root of the repo directory. -**Make sure you** -- **stopped all master and worker processes of Misskey.** -- **have backups of the database before performing any commands.** +### Before proceeding + +- **Ensure you have stopped all master and worker processes of Misskey.** +- **Ensure you have backups of the database before performing any commands.** ## Misskey v13 and above @@ -77,10 +78,11 @@ NODE_ENV=production pnpm run migrate # build using prefered method ``` -## Foundkey +## FoundKey ```sh cd packages/backend +sed -i '12s/^/\/\//' ./migration/1663399074403-resize-comments-drive-file.js LINE_NUM="$(npx typeorm migration:show -d ormconfig.js | grep -n uniformThemecolor1652859567549 | cut -d ':' -f 1)" NUM_MIGRATIONS="$(npx typeorm migration:show -d ormconfig.js | tail -n+"$LINE_NUM" | grep '\[X\]' | wc -l)" @@ -100,4 +102,4 @@ NODE_ENV=production pnpm run migrate ## Reverse -You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to Foundkey, though. +You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to FoundKey, though. From 3b394c74bad18ea3cbcd99231149dde8fdcadd8d Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 15:45:28 -0700 Subject: [PATCH 045/162] chore: :page_facing_up: LICENSE for configuration directories Closes #10470 --- COPYING | 27 ++++++++++++++++++++------- custom/assets/LICENSE | 13 +++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 custom/assets/LICENSE diff --git a/COPYING b/COPYING index fb483b523..387515b06 100644 --- a/COPYING +++ b/COPYING @@ -1,15 +1,24 @@ -Unless otherwise stated this repository is -Copyright © 2014-2022 syuilo and contributers -Copyright © 2022 thatonecalculator and contributers +Unless specified otherwise, the entirety of this repository is subject to the following: +Copyright © 2014-2023 syuilo and contributors +Copyright © 2022-2023 Kainoa Kanter and contributors And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. +--- -Calckey includes several third-party Open-Source softwares. +These specific configuration directories: -Emoji keywords for Unicode 11 and below by Mu-An Chiou -License: MIT -https://github.com/muan/emojilib/blob/master/LICENSE +- .config/ +- custom/assets/ + +and their contents are +Copyright © 2022-2023 Kainoa Kanter and contributors + +And are distributed under The Apache License, Version 2.0, you should have received a copy of the license file as LICENSE in each specified directory. + +--- + +Calckey includes several third-party open-source softwares and software libraries. RsaSignature2017 implementation by Transmute Industries Inc License: MIT @@ -18,3 +27,7 @@ https://github.com/transmute-industries/RsaSignature2017/blob/master/LICENSE Machine learning model for sensitive images by Infinite Red, Inc. License: MIT https://github.com/infinitered/nsfwjs/blob/master/LICENSE + +Licenses for all softwares and software libraries installed via the Node Package Manager ("npm") can be found by running the following shell command in the root directory of this repository: + +pnpm licenses list diff --git a/custom/assets/LICENSE b/custom/assets/LICENSE new file mode 100644 index 000000000..342509dec --- /dev/null +++ b/custom/assets/LICENSE @@ -0,0 +1,13 @@ +Copyright 2023 Calckey + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. From cdd38b5bc3daec74351e0ecb38dc937b5ed87140 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 15:46:41 -0700 Subject: [PATCH 046/162] fix: :page_facing_up: don't gitignore .config license Follow-up #10470 --- .config/LICENSE | 13 +++++++++++++ .gitignore | 1 + 2 files changed, 14 insertions(+) create mode 100644 .config/LICENSE diff --git a/.config/LICENSE b/.config/LICENSE new file mode 100644 index 000000000..342509dec --- /dev/null +++ b/.config/LICENSE @@ -0,0 +1,13 @@ +Copyright 2023 Calckey + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/.gitignore b/.gitignore index 29377540d..6bf2ea1b1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ coverage !/.config/devenv.yml !/.config/docker_example.env !/.config/helm_values_example.yml +!/.config/LICENSE #docker dev config /dev/docker-compose.yml From aa92dbf967246ef429341974075da3f497c4b7e6 Mon Sep 17 00:00:00 2001 From: Namekuji <nmkj@waah.day> Date: Tue, 11 Jul 2023 20:48:38 -0400 Subject: [PATCH 047/162] chore: change account --- packages/client/src/pages/about-calckey.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/about-calckey.vue b/packages/client/src/pages/about-calckey.vue index 6899c4de0..fb508239b 100644 --- a/packages/client/src/pages/about-calckey.vue +++ b/packages/client/src/pages/about-calckey.vue @@ -101,8 +101,9 @@ ><Mfm :text="'@freeplay@calckey.social (UI/UX)'" /></FormLink> - <FormLink to="/@nmkj@calckey.jp" - ><Mfm :text="'@nmkj@calckey.jp (Backend)'" + <FormLink to="/@namekuji@calckey.social" + ><Mfm + :text="'@namekuji@calckey.social (Backend)'" /></FormLink> <FormLink to="/@dev@post.naskya.net" ><Mfm :text="'@dev@post.naskya.net (Backend)'" From 6d47313434a19462b424d15a204b6c63be58fde2 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 18:26:53 -0700 Subject: [PATCH 048/162] fix: :bug: fix draggable Use vue-draggable-plus instead of vuedraggable: https://github.com/SortableJS/vue.draggable.next/issues/216 Closes #10467 --- packages/client/package.json | 4 +- .../client/src/components/MkCropperDialog.vue | 4 +- .../src/components/MkPostFormAttaches.vue | 9 ++- packages/client/src/components/MkWidgets.vue | 7 +-- .../pages/page-editor/page-editor.blocks.vue | 9 ++- .../src/pages/page-editor/page-editor.vue | 9 +-- .../client/src/pages/settings/reaction.vue | 6 +- packages/client/vite.config.ts | 2 +- pnpm-lock.yaml | 60 ++++++------------- 9 files changed, 40 insertions(+), 70 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 81c252d66..95fb9f9b2 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -87,9 +87,9 @@ "vite": "4.4.2", "vite-plugin-compression": "^0.5.1", "vue": "3.3.4", + "vue-draggable-plus": "^0.2.2", "vue-isyourpasswordsafe": "^2.0.0", "vue-plyr": "^7.0.0", - "vue-prism-editor": "2.0.0-alpha.2", - "vuedraggable": "4.1.0" + "vue-prism-editor": "2.0.0-alpha.2" } } diff --git a/packages/client/src/components/MkCropperDialog.vue b/packages/client/src/components/MkCropperDialog.vue index 3d8ea46e8..748132fbc 100644 --- a/packages/client/src/components/MkCropperDialog.vue +++ b/packages/client/src/components/MkCropperDialog.vue @@ -13,7 +13,9 @@ <template #default="{ width, height }"> <div class="mk-cropper-dialog" - :style="`--vw: ${width ? `${width}px` : '100%'}; --vh: ${height ? `${height}px` : '100%'};`" + :style="`--vw: ${width ? `${width}px` : '100%'}; --vh: ${ + height ? `${height}px` : '100%' + };`" > <Transition name="fade"> <div v-if="loading" class="loading"> diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index 41997b0f7..8517d6969 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -1,6 +1,6 @@ <template> <div v-show="files.length != 0" class="skeikyzd"> - <XDraggable + <VueDraggable v-model="_files" class="files" item-key="id" @@ -25,22 +25,21 @@ </div> </div> </template> - </XDraggable> + </VueDraggable> <p class="remain">{{ 16 - files.length }}/16</p> </div> </template> <script lang="ts"> import { defineComponent, defineAsyncComponent } from "vue"; +import { VueDraggable } from "vue-draggable-plus"; import MkDriveFileThumbnail from "@/components/MkDriveFileThumbnail.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; export default defineComponent({ components: { - XDraggable: defineAsyncComponent(() => - import("vuedraggable").then((x) => x.default), - ), + VueDraggable, MkDriveFileThumbnail, }, diff --git a/packages/client/src/components/MkWidgets.vue b/packages/client/src/components/MkWidgets.vue index a5e56c075..4e40aeec3 100644 --- a/packages/client/src/components/MkWidgets.vue +++ b/packages/client/src/components/MkWidgets.vue @@ -28,7 +28,7 @@ i18n.ts.close }}</MkButton> </header> - <XDraggable + <VueDraggable v-model="widgets_" item-key="id" handle=".handle" @@ -59,7 +59,7 @@ </div> </div> </template> - </XDraggable> + </VueDraggable> </template> <component :is="`mkw-${widget.name}`" @@ -78,14 +78,13 @@ <script lang="ts" setup> import { defineAsyncComponent, reactive, ref, computed } from "vue"; import { v4 as uuid } from "uuid"; +import { VueDraggable } from "vue-draggable-plus"; import MkSelect from "@/components/form/select.vue"; import MkButton from "@/components/MkButton.vue"; import { widgets as widgetDefs } from "@/widgets"; import * as os from "@/os"; import { i18n } from "@/i18n"; -const XDraggable = defineAsyncComponent(() => import("vuedraggable")); - type Widget = { name: string; id: string; diff --git a/packages/client/src/pages/page-editor/page-editor.blocks.vue b/packages/client/src/pages/page-editor/page-editor.blocks.vue index 72594ae1a..a2ef65b15 100644 --- a/packages/client/src/pages/page-editor/page-editor.blocks.vue +++ b/packages/client/src/pages/page-editor/page-editor.blocks.vue @@ -1,5 +1,5 @@ <template> - <XDraggable + <VueDraggable v-model="blocks" tag="div" item-key="id" @@ -17,11 +17,12 @@ @remove="() => removeItem(element)" /> </template> - </XDraggable> + </VueDraggable> </template> <script lang="ts"> import { defineComponent, defineAsyncComponent } from "vue"; +import { VueDraggable } from "vue-draggable-plus"; import XSection from "./els/page-editor.el.section.vue"; import XText from "./els/page-editor.el.text.vue"; import XTextarea from "./els/page-editor.el.textarea.vue"; @@ -41,9 +42,7 @@ import * as os from "@/os"; export default defineComponent({ components: { - XDraggable: defineAsyncComponent(() => - import("vuedraggable").then((x) => x.default), - ), + VueDraggable, XSection, XText, XImage, diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue index c679e5efa..c8b2f47bd 100644 --- a/packages/client/src/pages/page-editor/page-editor.vue +++ b/packages/client/src/pages/page-editor/page-editor.vue @@ -118,7 +118,7 @@ <div v-else-if="tab === 'variables'"> <div class="qmuvgica"> - <XDraggable + <VueDraggable v-show="variables.length > 0" v-model="variables" tag="div" @@ -140,7 +140,7 @@ @remove="() => removeVariable(element)" /> </template> - </XDraggable> + </VueDraggable> <MkButton v-if="!readonly" @@ -174,6 +174,7 @@ import { blockDefs } from "@/scripts/hpml/index"; import { HpmlTypeChecker } from "@/scripts/hpml/type-checker"; import { url } from "@/config"; import { collectPageVars } from "@/scripts/collect-page-vars"; +import { VueDraggable } from "vue-draggable-plus"; import * as os from "@/os"; import { selectFile } from "@/scripts/select-file"; import { mainRouter } from "@/router"; @@ -181,10 +182,6 @@ import { i18n } from "@/i18n"; import { definePageMetadata } from "@/scripts/page-metadata"; import { $i } from "@/account"; -const XDraggable = defineAsyncComponent(() => - import("vuedraggable").then((x) => x.default), -); - const props = defineProps<{ initPageId?: string; initPageName?: string; diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index 992900486..b748b0ce0 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -10,7 +10,7 @@ i18n.ts.reactionSettingDescription }}</template> <div v-panel style="border-radius: 6px"> - <XDraggable + <VueDraggable v-model="reactions" class="zoaiodol" :item-key="(item) => item" @@ -35,7 +35,7 @@ <i class="ph-plus ph-bold ph-lg"></i> </button> </template> - </XDraggable> + </VueDraggable> </div> <template #caption >{{ i18n.ts.reactionSettingDescription2 }} @@ -124,7 +124,7 @@ <script lang="ts" setup> import { defineAsyncComponent, watch } from "vue"; -import XDraggable from "vuedraggable"; +import { VueDraggable } from "vue-draggable-plus"; import FormInput from "@/components/form/input.vue"; import FormRadios from "@/components/form/radios.vue"; import FromSlot from "@/components/form/slot.vue"; diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index 592628e83..1b6bdfe59 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -96,6 +96,6 @@ export default defineConfig(({ command, mode }) => { auto: true, }, - logLevel: 'warn', + logLevel: "warn", }; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b4695f3f..1189c2343 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -910,6 +910,9 @@ importers: vue: specifier: 3.3.4 version: 3.3.4 + vue-draggable-plus: + specifier: ^0.2.2 + version: 0.2.2 vue-isyourpasswordsafe: specifier: ^2.0.0 version: 2.0.0 @@ -919,9 +922,6 @@ importers: vue-prism-editor: specifier: 2.0.0-alpha.2 version: 2.0.0-alpha.2(vue@3.3.4) - vuedraggable: - specifier: 4.1.0 - version: 4.1.0(vue@3.3.4) packages/megalodon: dependencies: @@ -5446,7 +5446,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) transitivePeerDependencies: - debug dev: false @@ -5472,7 +5472,7 @@ packages: /axios@1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -7137,17 +7137,6 @@ packages: dependencies: ms: 2.0.0 - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: false - /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -7158,7 +7147,6 @@ packages: dependencies: ms: 2.1.3 supports-color: 8.1.1 - dev: true /debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} @@ -8742,16 +8730,6 @@ packages: tabbable: 6.2.0 dev: true - /follow-redirects@1.15.2: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -9693,7 +9671,7 @@ packages: engines: {node: '>= 4.5.0'} dependencies: agent-base: 4.3.0 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -11844,7 +11822,7 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) koa-send: 5.0.1 transitivePeerDependencies: - supports-color @@ -12891,7 +12869,7 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) iconv-lite: 0.4.24 sax: 1.2.4 transitivePeerDependencies: @@ -15438,10 +15416,6 @@ packages: is-plain-obj: 1.1.0 dev: true - /sortablejs@1.14.0: - resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==} - dev: true - /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} @@ -17135,6 +17109,15 @@ packages: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} dev: true + /vue-draggable-plus@0.2.2: + resolution: {integrity: sha512-Mp9T7FK/N8anWr1Bi3RKQ3GETRu/pCHz+upvd0CTHY9Rq4sITfVtpoKsMUkasg55svx5sw8B+yeQob3WfaqqzQ==} + peerDependencies: + '@vue/composition-api': '*' + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dev: true + /vue-isyourpasswordsafe@2.0.0: resolution: {integrity: sha512-j3ORj18R9AgFiP2UOM35KuZbSeJAUiwCSyeRBFN3CGFYTJSKsxqU9qGqOHOz6OhLAYKMTin8JOmqugAbF9O+Bg==} dependencies: @@ -17174,15 +17157,6 @@ packages: '@vue/shared': 3.3.4 dev: true - /vuedraggable@4.1.0(vue@3.3.4): - resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==} - peerDependencies: - vue: ^3.0.1 - dependencies: - sortablejs: 1.14.0 - vue: 3.3.4 - dev: true - /w3c-hr-time@1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} deprecated: Use your platform's native performance.now() and performance.timeOrigin. From 68bade8532035108d946fdada7f47df910605ce5 Mon Sep 17 00:00:00 2001 From: DVD <zjdavid.2003@gmail.com> Date: Wed, 12 Jul 2023 09:26:15 +0800 Subject: [PATCH 049/162] Disable signature check --- packages/client/src/pages/settings/import-export.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/pages/settings/import-export.vue b/packages/client/src/pages/settings/import-export.vue index b2ac12cad..4a9286748 100644 --- a/packages/client/src/pages/settings/import-export.vue +++ b/packages/client/src/pages/settings/import-export.vue @@ -222,7 +222,7 @@ const importPosts = async (ev) => { const file = await selectFile(ev.currentTarget ?? ev.target); os.api("i/import-posts", { fileId: file.id, - signatureCheck: importType.value === "mastodon" ? true : false, + signatureCheck: false, }) .then(onImportSuccess) .catch(onError); From 8b837d3d90f5df1366959bd9c8751e25933ee231 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 18:28:23 -0700 Subject: [PATCH 050/162] dev63 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f14400cf..8e54bcd50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev60", + "version": "14.0.0-dev63", "codename": "aqua", "repository": { "type": "git", From f58cf72e939c9118b752faddb759af17d171c888 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 18:55:24 -0700 Subject: [PATCH 051/162] fix? --- packages/client/src/pages/settings/reaction.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index b748b0ce0..a76745d5f 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -11,6 +11,7 @@ }}</template> <div v-panel style="border-radius: 6px"> <VueDraggable + ref="el" v-model="reactions" class="zoaiodol" :item-key="(item) => item" From b9ddd5b569ea80b20cccdcb985c9588c946e3f19 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:08:47 -0700 Subject: [PATCH 052/162] fix --- .../client/src/pages/settings/reaction.vue | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index a76745d5f..c407e6f94 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -11,26 +11,25 @@ }}</template> <div v-panel style="border-radius: 6px"> <VueDraggable - ref="el" v-model="reactions" class="zoaiodol" - :item-key="(item) => item" animation="150" delay="100" + @end="save" delay-on-touch-only="true" > - <template #item="{ element }"> <button + v-for="item in reactions" + :key="item" class="_button item" - @click="remove(element, $event)" + @click="remove(item, $event)" > <MkEmoji - :emoji="element" + :emoji="item" style="height: 1.7em" class="emoji" /> </button> - </template> <template #footer> <button class="_button add" @click="chooseEmoji"> <i class="ph-plus ph-bold ph-lg"></i> @@ -226,16 +225,6 @@ function chooseEmoji(ev: MouseEvent) { }); } -watch( - $$(reactions), - () => { - save(); - }, - { - deep: true, - }, -); - watch(enableEmojiReactions, async () => { await reloadAsk(); }); From 2c019bc347e6695c1b00c816f2d0cfaf6033e712 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:20:58 -0700 Subject: [PATCH 053/162] fix --- .../src/components/MkPostFormAttaches.vue | 33 +++++++++---------- packages/client/src/components/MkWidgets.vue | 8 +++-- .../pages/page-editor/page-editor.blocks.vue | 5 ++- .../src/pages/page-editor/page-editor.vue | 5 ++- .../client/src/pages/settings/reaction.vue | 4 +-- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index 8517d6969..cb3a9901b 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -3,28 +3,27 @@ <VueDraggable v-model="_files" class="files" - item-key="id" animation="150" delay="100" delay-on-touch-only="true" > - <template #item="{ element }"> - <div - class="file" - @click="showFileMenu(element, $event)" - @contextmenu.prevent="showFileMenu(element, $event)" - > - <MkDriveFileThumbnail - :data-id="element.id" - class="thumbnail" - :file="element" - fit="cover" - /> - <div v-if="element.isSensitive" class="sensitive"> - <i class="ph-warning ph-bold ph-lg icon"></i> - </div> + <div + class="file" + v-for="element in _files" + :key="element.id" + @click="showFileMenu(element, $event)" + @contextmenu.prevent="showFileMenu(element, $event)" + > + <MkDriveFileThumbnail + :data-id="element.id" + class="thumbnail" + :file="element" + fit="cover" + /> + <div v-if="element.isSensitive" class="sensitive"> + <i class="ph-warning ph-bold ph-lg icon"></i> </div> - </template> + </div> </VueDraggable> <p class="remain">{{ 16 - files.length }}/16</p> </div> diff --git a/packages/client/src/components/MkWidgets.vue b/packages/client/src/components/MkWidgets.vue index 4e40aeec3..4274b255d 100644 --- a/packages/client/src/components/MkWidgets.vue +++ b/packages/client/src/components/MkWidgets.vue @@ -30,11 +30,13 @@ </header> <VueDraggable v-model="widgets_" - item-key="id" handle=".handle" animation="150" > - <template #item="{ element }"> + <div + v-for="element in widgets_" + :key="element.id" + > <div class="customize-container"> <button class="config _button" @@ -58,7 +60,7 @@ /> </div> </div> - </template> + </div> </VueDraggable> </template> <component diff --git a/packages/client/src/pages/page-editor/page-editor.blocks.vue b/packages/client/src/pages/page-editor/page-editor.blocks.vue index a2ef65b15..c7a7b8152 100644 --- a/packages/client/src/pages/page-editor/page-editor.blocks.vue +++ b/packages/client/src/pages/page-editor/page-editor.blocks.vue @@ -2,21 +2,20 @@ <VueDraggable v-model="blocks" tag="div" - item-key="id" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150" swap-threshold="0.5" > - <template #item="{ element }"> <component + v-for="element in blocks" + :key="element" :is="'x-' + element.type" :value="element" :hpml="hpml" @update:value="updateItem" @remove="() => removeItem(element)" /> - </template> </VueDraggable> </template> diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue index c8b2f47bd..772bc9ca5 100644 --- a/packages/client/src/pages/page-editor/page-editor.vue +++ b/packages/client/src/pages/page-editor/page-editor.vue @@ -123,14 +123,14 @@ v-model="variables" tag="div" class="variables" - item-key="name" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5" > - <template #item="{ element }"> <XVariable + v-for="element in variables" + :key="element.name" :model-value="element" :removable="true" :hpml="hpml" @@ -139,7 +139,6 @@ :draggable="true" @remove="() => removeVariable(element)" /> - </template> </VueDraggable> <MkButton diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index c407e6f94..2ce7fffb6 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -18,7 +18,7 @@ @end="save" delay-on-touch-only="true" > - <button + <div v-for="item in reactions" :key="item" class="_button item" @@ -29,7 +29,7 @@ style="height: 1.7em" class="emoji" /> - </button> + </div> <template #footer> <button class="_button add" @click="chooseEmoji"> <i class="ph-plus ph-bold ph-lg"></i> From f8e57968b56f5d4bd3632f2545f47d6e2ec3935a Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:21:52 -0700 Subject: [PATCH 054/162] chore: :art: format --- packages/client/src/components/MkWidgets.vue | 11 ++------- .../pages/page-editor/page-editor.blocks.vue | 18 +++++++------- .../src/pages/page-editor/page-editor.vue | 22 ++++++++--------- .../client/src/pages/settings/reaction.vue | 24 +++++++++---------- 4 files changed, 34 insertions(+), 41 deletions(-) diff --git a/packages/client/src/components/MkWidgets.vue b/packages/client/src/components/MkWidgets.vue index 4274b255d..272ba1404 100644 --- a/packages/client/src/components/MkWidgets.vue +++ b/packages/client/src/components/MkWidgets.vue @@ -28,15 +28,8 @@ i18n.ts.close }}</MkButton> </header> - <VueDraggable - v-model="widgets_" - handle=".handle" - animation="150" - > - <div - v-for="element in widgets_" - :key="element.id" - > + <VueDraggable v-model="widgets_" handle=".handle" animation="150"> + <div v-for="element in widgets_" :key="element.id"> <div class="customize-container"> <button class="config _button" diff --git a/packages/client/src/pages/page-editor/page-editor.blocks.vue b/packages/client/src/pages/page-editor/page-editor.blocks.vue index c7a7b8152..25e35a487 100644 --- a/packages/client/src/pages/page-editor/page-editor.blocks.vue +++ b/packages/client/src/pages/page-editor/page-editor.blocks.vue @@ -7,15 +7,15 @@ animation="150" swap-threshold="0.5" > - <component - v-for="element in blocks" - :key="element" - :is="'x-' + element.type" - :value="element" - :hpml="hpml" - @update:value="updateItem" - @remove="() => removeItem(element)" - /> + <component + v-for="element in blocks" + :key="element" + :is="'x-' + element.type" + :value="element" + :hpml="hpml" + @update:value="updateItem" + @remove="() => removeItem(element)" + /> </VueDraggable> </template> diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue index 772bc9ca5..7fda39303 100644 --- a/packages/client/src/pages/page-editor/page-editor.vue +++ b/packages/client/src/pages/page-editor/page-editor.vue @@ -128,17 +128,17 @@ animation="150" swap-threshold="0.5" > - <XVariable - v-for="element in variables" - :key="element.name" - :model-value="element" - :removable="true" - :hpml="hpml" - :name="element.name" - :title="element.name" - :draggable="true" - @remove="() => removeVariable(element)" - /> + <XVariable + v-for="element in variables" + :key="element.name" + :model-value="element" + :removable="true" + :hpml="hpml" + :name="element.name" + :title="element.name" + :draggable="true" + @remove="() => removeVariable(element)" + /> </VueDraggable> <MkButton diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index 2ce7fffb6..2b2e69973 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -18,18 +18,18 @@ @end="save" delay-on-touch-only="true" > - <div - v-for="item in reactions" - :key="item" - class="_button item" - @click="remove(item, $event)" - > - <MkEmoji - :emoji="item" - style="height: 1.7em" - class="emoji" - /> - </div> + <div + v-for="item in reactions" + :key="item" + class="_button item" + @click="remove(item, $event)" + > + <MkEmoji + :emoji="item" + style="height: 1.7em" + class="emoji" + /> + </div> <template #footer> <button class="_button add" @click="chooseEmoji"> <i class="ph-plus ph-bold ph-lg"></i> From d3a6e31415b63d964c57c91d7cc7b76533b4117a Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:24:24 -0700 Subject: [PATCH 055/162] save on delete --- packages/client/src/pages/settings/reaction.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index 2b2e69973..a7ceb9612 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -184,6 +184,7 @@ function remove(reaction, ev: MouseEvent) { text: i18n.ts.remove, action: () => { reactions = reactions.filter((x) => x !== reaction); + save(); }, }, ], From 9a6b38aa1a76488602e353fa8e1f025c5ce0fbb8 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:38:49 -0700 Subject: [PATCH 056/162] refactor: :recycle: MkPostFormAttachees setup syntax --- .../src/components/MkPostFormAttaches.vue | 271 ++++++++---------- 1 file changed, 127 insertions(+), 144 deletions(-) diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index cb3a9901b..7224122a0 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -29,156 +29,139 @@ </div> </template> -<script lang="ts"> -import { defineComponent, defineAsyncComponent } from "vue"; +<script lang="ts" setup> +import { defineAsyncComponent, ref, computed } from "vue"; import { VueDraggable } from "vue-draggable-plus"; import MkDriveFileThumbnail from "@/components/MkDriveFileThumbnail.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; -export default defineComponent({ - components: { - VueDraggable, - MkDriveFileThumbnail, +const props = defineProps({ + files: { + type: Array, + required: true, }, - - props: { - files: { - type: Array, - required: true, - }, - detachMediaFn: { - type: Function, - required: false, - }, - }, - - emits: ["updated", "detach", "changeSensitive", "changeName"], - - data() { - return { - menu: null as Promise<null> | null, - i18n, - }; - }, - - computed: { - _files: { - get() { - return this.files; - }, - set(value) { - this.$emit("updated", value); - }, - }, - }, - - methods: { - detachMedia(id) { - if (this.detachMediaFn) { - this.detachMediaFn(id); - } else { - this.$emit("detach", id); - } - }, - toggleSensitive(file) { - os.api("drive/files/update", { - fileId: file.id, - isSensitive: !file.isSensitive, - }).then(() => { - this.$emit("changeSensitive", file, !file.isSensitive); - }); - }, - async rename(file) { - const { canceled, result } = await os.inputText({ - title: i18n.ts.enterFileName, - default: file.name, - allowEmpty: false, - }); - if (canceled) return; - os.api("drive/files/update", { - fileId: file.id, - name: result, - }).then(() => { - this.$emit("changeName", file, result); - file.name = result; - }); - }, - - async describe(file) { - os.popup( - defineAsyncComponent( - () => import("@/components/MkMediaCaption.vue"), - ), - { - title: i18n.ts.describeFile, - input: { - placeholder: i18n.ts.inputNewDescription, - default: file.comment !== null ? file.comment : "", - }, - image: file, - }, - { - done: (result) => { - if (!result || result.canceled) return; - let comment = - result.result.length === 0 ? null : result.result; - os.api("drive/files/update", { - fileId: file.id, - comment: comment, - }).then(() => { - file.comment = comment; - }); - }, - }, - "closed", - ); - }, - - showFileMenu(file, ev: MouseEvent) { - if (this.menu) return; - this.menu = os - .popupMenu( - [ - { - text: i18n.ts.renameFile, - icon: "ph-cursor-text ph-bold ph-lg", - action: () => { - this.rename(file); - }, - }, - { - text: file.isSensitive - ? i18n.ts.unmarkAsSensitive - : i18n.ts.markAsSensitive, - icon: file.isSensitive - ? "ph-eye ph-bold ph-lg" - : "ph-eye-slash ph-bold ph-lg", - action: () => { - this.toggleSensitive(file); - }, - }, - { - text: i18n.ts.describeFile, - icon: "ph-subtitles ph-bold ph-lg", - action: () => { - this.describe(file); - }, - }, - { - text: i18n.ts.attachCancel, - icon: "ph-x ph-bold ph-lg", - action: () => { - this.detachMedia(file.id); - }, - }, - ], - ev.currentTarget ?? ev.target, - ) - .then(() => (this.menu = null)); - }, + detachMediaFn: { + type: Function, + required: false, }, }); + +const emits = defineEmits([ + "updated", + "detach", + "changeSensitive", + "changeName", +]); + +let menu = ref<Promise<any> | null>(null); + +const _files = computed({ + get: () => props.files, + set: (value) => emits("updated", value), +}); + +const detachMedia = (id) => { + if (props.detachMediaFn) { + props.detachMediaFn(id); + } else { + emits("detach", id); + } +}; + +function toggleSensitive(file) { + os.api("drive/files/update", { + fileId: file.id, + isSensitive: !file.isSensitive, + }).then(() => { + emits("changeSensitive", file, !file.isSensitive); + }); +} + +async function rename(file) { + const { canceled, result } = await os.inputText({ + title: i18n.ts.enterFileName, + default: file.name, + }); + if (canceled) return; + os.api("drive/files/update", { + fileId: file.id, + name: result, + }).then(() => { + emits("changeName", file, result); + file.name = result; + }); +} + +async function describe(file) { + os.popup( + defineAsyncComponent(() => import("@/components/MkMediaCaption.vue")), + { + title: i18n.ts.describeFile, + input: { + placeholder: i18n.ts.inputNewDescription, + default: file.comment !== null ? file.comment : "", + }, + image: file, + }, + { + done: (result) => { + if (!result || result.canceled) return; + let comment = result.result.length === 0 ? null : result.result; + os.api("drive/files/update", { + fileId: file.id, + comment: comment, + }).then(() => { + file.comment = comment; + }); + }, + }, + "closed", + ); +} + +function showFileMenu(file, ev: MouseEvent) { + if (menu) return; + menu = os + .popupMenu( + [ + { + text: i18n.ts.renameFile, + icon: "ph-cursor-text ph-bold ph-lg", + action: () => { + rename(file); + }, + }, + { + text: file.isSensitive + ? i18n.ts.unmarkAsSensitive + : i18n.ts.markAsSensitive, + icon: file.isSensitive + ? "ph-eye ph-bold ph-lg" + : "ph-eye-slash ph-bold ph-lg", + action: () => { + toggleSensitive(file); + }, + }, + { + text: i18n.ts.describeFile, + icon: "ph-subtitles ph-bold ph-lg", + action: () => { + describe(file); + }, + }, + { + text: i18n.ts.attachCancel, + icon: "ph-x ph-bold ph-lg", + action: () => { + detachMedia(file.id); + }, + }, + ], + ev.currentTarget ?? ev.target, + ) + .then(() => (menu = null)); +} </script> <style lang="scss" scoped> @@ -217,8 +200,8 @@ export default defineComponent({ top: 0; left: 0; z-index: 2; - background: rgba(17, 17, 17, 0.7); - color: #fff; + background: var(--header); + color: var(--fg); > .icon { margin: auto; From 446fc9830c98e1b5d744bac8de88e14a00777533 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 19:44:00 -0700 Subject: [PATCH 057/162] fix popup menu --- .../src/components/MkPostFormAttaches.vue | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index 7224122a0..6da744ccf 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -54,8 +54,6 @@ const emits = defineEmits([ "changeName", ]); -let menu = ref<Promise<any> | null>(null); - const _files = computed({ get: () => props.files, set: (value) => emits("updated", value), @@ -121,46 +119,45 @@ async function describe(file) { } function showFileMenu(file, ev: MouseEvent) { - if (menu) return; - menu = os - .popupMenu( - [ - { - text: i18n.ts.renameFile, - icon: "ph-cursor-text ph-bold ph-lg", - action: () => { - rename(file); - }, + os.popupMenu( + [ + { + text: i18n.ts.renameFile, + icon: "ph-cursor-text ph-bold ph-lg", + action: () => { + rename(file); }, - { - text: file.isSensitive - ? i18n.ts.unmarkAsSensitive - : i18n.ts.markAsSensitive, - icon: file.isSensitive - ? "ph-eye ph-bold ph-lg" - : "ph-eye-slash ph-bold ph-lg", - action: () => { - toggleSensitive(file); - }, + }, + { + text: file.isSensitive + ? i18n.ts.unmarkAsSensitive + : i18n.ts.markAsSensitive, + icon: file.isSensitive + ? "ph-eye ph-bold ph-lg" + : "ph-eye-slash ph-bold ph-lg", + action: () => { + toggleSensitive(file); }, - { - text: i18n.ts.describeFile, - icon: "ph-subtitles ph-bold ph-lg", - action: () => { - describe(file); - }, + }, + { + text: i18n.ts.describeFile, + icon: "ph-subtitles ph-bold ph-lg", + action: () => { + describe(file); }, - { - text: i18n.ts.attachCancel, - icon: "ph-x ph-bold ph-lg", - action: () => { - detachMedia(file.id); - }, + }, + { + text: i18n.ts.attachCancel, + icon: "ph-x ph-bold ph-lg", + action: () => { + detachMedia(file.id); }, - ], - ev.currentTarget ?? ev.target, - ) - .then(() => (menu = null)); + }, + ], + (ev.currentTarget ?? ev.target ?? undefined) as + | HTMLElement + | undefined, + ); } </script> From 0097ab33bd35942cee0204e6d49d8ce7a57c421c Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:30:31 -0700 Subject: [PATCH 058/162] fix: :bug: plus button for reactions --- .../src/components/MkPostFormAttaches.vue | 4 +--- .../client/src/pages/settings/reaction.vue | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index 6da744ccf..a1cb191de 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -154,9 +154,7 @@ function showFileMenu(file, ev: MouseEvent) { }, }, ], - (ev.currentTarget ?? ev.target ?? undefined) as - | HTMLElement - | undefined, + (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined, ); } </script> diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index a7ceb9612..57f8a0d4e 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -12,7 +12,7 @@ <div v-panel style="border-radius: 6px"> <VueDraggable v-model="reactions" - class="zoaiodol" + :class="$style.root" animation="150" delay="100" @end="save" @@ -30,11 +30,13 @@ class="emoji" /> </div> - <template #footer> - <button class="_button add" @click="chooseEmoji"> - <i class="ph-plus ph-bold ph-lg"></i> - </button> - </template> + <button + :draggable="false" + class="_button add" + @click="chooseEmoji" + > + <i class="ph-plus ph-bold ph-lg"></i> + </button> </VueDraggable> </div> <template #caption @@ -251,8 +253,8 @@ definePageMetadata({ }); </script> -<style lang="scss" scoped> -.zoaiodol { +<style lang="scss" module> +.root { padding: 12px; font-size: 1.1em; From 788f9c7265381f052ff2b42f62202e89be720aed Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:31:26 -0700 Subject: [PATCH 059/162] dev67 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e54bcd50..7e853fb45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev63", + "version": "14.0.0-dev67", "codename": "aqua", "repository": { "type": "git", From eb49999d9c2ad2eca78661a53ed6987d3a7d6f93 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:36:15 -0700 Subject: [PATCH 060/162] fix: :bug: plus button in reaction settings --- package.json | 2 +- .../src/components/MkPostFormAttaches.vue | 4 +--- .../client/src/pages/settings/reaction.vue | 22 ++++++++----------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 8e54bcd50..7d79fc709 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev63", + "version": "14.0.0-dev68", "codename": "aqua", "repository": { "type": "git", diff --git a/packages/client/src/components/MkPostFormAttaches.vue b/packages/client/src/components/MkPostFormAttaches.vue index 6da744ccf..a1cb191de 100644 --- a/packages/client/src/components/MkPostFormAttaches.vue +++ b/packages/client/src/components/MkPostFormAttaches.vue @@ -154,9 +154,7 @@ function showFileMenu(file, ev: MouseEvent) { }, }, ], - (ev.currentTarget ?? ev.target ?? undefined) as - | HTMLElement - | undefined, + (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined, ); } </script> diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index a7ceb9612..953c39c5f 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -30,12 +30,10 @@ class="emoji" /> </div> - <template #footer> - <button class="_button add" @click="chooseEmoji"> - <i class="ph-plus ph-bold ph-lg"></i> - </button> - </template> </VueDraggable> + <button class="_button add" @click="chooseEmoji"> + <i class="ph-plus ph-bold ph-lg"></i> + </button> </div> <template #caption >{{ i18n.ts.reactionSettingDescription2 }} @@ -244,10 +242,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.reaction, icon: "ph-smiley ph-bold ph-lg", - action: { - icon: "ph-eye ph-bold ph-lg", - handler: preview, - }, }); </script> @@ -261,10 +255,12 @@ definePageMetadata({ padding: 8px; cursor: move; } +} - > .add { - display: inline-block; - padding: 8px; - } +.add { + display: inline-block; + padding: 8px; + margin-left: 12px; + margin-bottom: 12px; } </style> From 6d461c788a9ac5b344dad1e7f6dfb408fffb2fed Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:56:40 -0700 Subject: [PATCH 061/162] feat: :sparkles: don't close emoji picker if shift is held down, like Discord https://snug.moe/notes/9h1p04dqytz2qfsz --- .../src/components/MkEmojiPickerDialog.vue | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index fcd2f26a3..95000b353 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -12,7 +12,7 @@ :transparent-bg="true" :manual-showing="manualShowing" :src="src" - @click="modal?.close()" + @click="checkForShift" @opening="opening" @close="emit('close')" @closed="emit('closed')" @@ -31,7 +31,7 @@ </template> <script lang="ts" setup> -import { ref } from "vue"; +import { ref, onMounted, onBeforeUnmount } from "vue"; import MkModal from "@/components/MkModal.vue"; import MkEmojiPicker from "@/components/MkEmojiPicker.vue"; import { defaultStore } from "@/store"; @@ -58,20 +58,49 @@ const emit = defineEmits<{ const modal = ref<InstanceType<typeof MkModal>>(); const picker = ref<InstanceType<typeof MkEmojiPicker>>(); +const isShiftKeyPressed = ref(false); -function chosen(emoji: any) { +const keydownHandler = (e) => { + if (e.key === "Shift") { + isShiftKeyPressed.value = true; + } +}; + +const keyupHandler = (e) => { + if (e.key === "Shift") { + isShiftKeyPressed.value = false; + } +}; + +function checkForShift(ev?: MouseEvent) { + if (!isShiftKeyPressed.value) { + modal.value?.close(ev); + } +} + +function chosen(emoji: any, ev: MouseEvent) { emit("done", emoji); - modal.value?.close(); + checkForShift(ev); } function opening() { try { picker.value?.reset(); } catch (e) { - console.error(`Something's wrong with restting the emoji picker: ${e}`); + console.error("Something's wrong with resetting the emoji picker", e); } picker.value?.focus(); } + +onMounted(() => { + window.addEventListener("keydown", keydownHandler); + window.addEventListener("keyup", keyupHandler); +}); + +onBeforeUnmount(() => { + window.removeEventListener("keydown", keydownHandler); + window.removeEventListener("keyup", keyupHandler); +}); </script> <style lang="scss" scoped> From 2d6d0947d8a0f519daf903525bc40edd5efe40db Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:57:28 -0700 Subject: [PATCH 062/162] fix --- packages/client/src/components/MkEmojiPickerDialog.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index 95000b353..28cc1d215 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -78,9 +78,9 @@ function checkForShift(ev?: MouseEvent) { } } -function chosen(emoji: any, ev: MouseEvent) { +function chosen(emoji: any) { emit("done", emoji); - checkForShift(ev); + checkForShift(); } function opening() { From 5e559fe48245c2f13895c84cc9cb127de4962310 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 20:58:33 -0700 Subject: [PATCH 063/162] dev69 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d79fc709..ef2cd9e70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev68", + "version": "14.0.0-dev69", "codename": "aqua", "repository": { "type": "git", From 1a00e1c8e43c147b44a05048a7a43301cfa5bbab Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 21:01:31 -0700 Subject: [PATCH 064/162] fix: :bug: save reactions if added --- locales/en-US.yml | 1 + packages/client/src/pages/settings/reaction.vue | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index b7248e033..219ff42a1 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -644,6 +644,7 @@ useBlurEffectForModal: "Use blur effect for modals" useFullReactionPicker: "Use full-size reaction picker" width: "Width" height: "Height" +xl: "XL" large: "Big" medium: "Medium" small: "Small" diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index 953c39c5f..29f14fd48 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -83,7 +83,7 @@ <option :value="1">{{ i18n.ts.small }}</option> <option :value="2">{{ i18n.ts.medium }}</option> <option :value="3">{{ i18n.ts.large }}</option> - <option :value="4">{{ i18n.ts.large }}+</option> + <option :value="4">{{ i18n.ts.xl }}</option> </FormRadios> <FormSwitch @@ -123,7 +123,6 @@ <script lang="ts" setup> import { defineAsyncComponent, watch } from "vue"; import { VueDraggable } from "vue-draggable-plus"; -import FormInput from "@/components/form/input.vue"; import FormRadios from "@/components/form/radios.vue"; import FromSlot from "@/components/form/slot.vue"; import FormButton from "@/components/MkButton.vue"; @@ -220,6 +219,7 @@ function chooseEmoji(ev: MouseEvent) { }).then((emoji) => { if (!reactions.includes(emoji)) { reactions.push(emoji); + save(); } }); } From 1f2a29c203980affba038de981c4226c91602b07 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 21:07:32 -0700 Subject: [PATCH 065/162] docs: :memo: FoundKey EOL disclaimer --- docs/migrate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migrate.md b/docs/migrate.md index 7d5c5639f..3c43af809 100644 --- a/docs/migrate.md +++ b/docs/migrate.md @@ -102,4 +102,4 @@ NODE_ENV=production pnpm run migrate ## Reverse -You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to FoundKey, though. +You ***cannot*** migrate back to Misskey from Calckey due to re-hashing passwords on signin with argon2. You can migrate from Calckey to FoundKey, although this is not recommended due to FoundKey being end-of-life. From 7f497d3e6724644f894f8a35c8363ca0aa7743f8 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 23:23:44 -0700 Subject: [PATCH 066/162] feat: :sparkles: Donation pop-up with optional admin link Co-authored-by: Syuilo <syuilotan@yahoo.co.jp> --- locales/en-US.yml | 5 + .../migration/1689136347561-donation-link.js | 15 ++ packages/backend/src/models/entities/meta.ts | 6 + .../src/server/api/endpoints/admin/meta.ts | 6 + packages/client/src/components/MkDonation.vue | 131 ++++++++++++++++++ packages/client/src/init.ts | 23 +++ packages/client/src/pages/admin/settings.vue | 17 +++ packages/client/src/pages/settings/2fa.vue | 2 +- 8 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 packages/backend/migration/1689136347561-donation-link.js create mode 100644 packages/client/src/components/MkDonation.vue diff --git a/locales/en-US.yml b/locales/en-US.yml index 219ff42a1..08eb2a62f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1118,6 +1118,7 @@ enableIdenticonGeneration: "Enable Identicon generation" showPopup: "Notify users with popup" showWithSparkles: "Show with sparkles" youHaveUnreadAnnouncements: "You have unread announcements" +donationLink: "Link to donation page" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing @@ -1216,6 +1217,10 @@ _aboutMisskey: source: "Source code" translation: "Translate Calckey" donate: "Donate to Calckey" + donateTitle: "Enjoying Calckey?" + pleaseDonateToCalckey: "Please consider donating to Calckey to support its development." + pleaseDonateToHost: "Please also consider donating to your honme server, {host}, to help support its operation costs." + donateHost: "Donate to {host}" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" patrons: "Calckey patrons" diff --git a/packages/backend/migration/1689136347561-donation-link.js b/packages/backend/migration/1689136347561-donation-link.js new file mode 100644 index 000000000..dbe0ed7c8 --- /dev/null +++ b/packages/backend/migration/1689136347561-donation-link.js @@ -0,0 +1,15 @@ +export class DonationLink1689136347561 { + name = "DonationLink1689136347561"; + + async up(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" ADD "donationLink" character varying(256)`, + ); + } + + async down(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`, + ); + } +} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 200ef5055..d3de7ba53 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -556,4 +556,10 @@ export class Meta { default: true, }) public enableIdenticonGeneration: boolean; + + @Column("varchar", { + length: 256, + nullable: true, + }) + public donationLink: string | null; } diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 50317d4a8..6c3bb5041 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -491,6 +491,11 @@ export const meta = { optional: false, nullable: false, }, + donationLink: { + type: "string", + optional: true, + nullable: true, + } }, }, } as const; @@ -604,5 +609,6 @@ export default define(meta, paramDef, async (ps, me) => { experimentalFeatures: instance.experimentalFeatures, enableServerMachineStats: instance.enableServerMachineStats, enableIdenticonGeneration: instance.enableIdenticonGeneration, + donationLink: instance.donationLink, }; }); diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue new file mode 100644 index 000000000..beaeef2d2 --- /dev/null +++ b/packages/client/src/components/MkDonation.vue @@ -0,0 +1,131 @@ +<template> + <div class="_panel _shadow" :class="$style.root"> + <div :class="$style.icon"> + <i class="ph-hand-heart ph-bold ph-6x" /> + </div> + <div :class="$style.main"> + <div :class="$style.title"> + {{ i18n.ts._aboutMisskey.donateTitle }} + </div> + <div :class="$style.text"> + {{ i18n.ts._aboutMisskey.pleaseDonateToCalckey }} + <p v-if="instance.donationLink"> + {{ + i18n.t("_aboutMisskey.pleaseDonateToHost", { + host: hostname, + }) + }} + </p> + </div> + <div class="_flexList"> + <MkButton primary @click="openCalckeyDonation">{{ + i18n.ts._aboutMisskey.donate + }}</MkButton> + <MkButton v-if="instance.donationLink" primary @click="openExternalDonation">{{ + i18n.t("_aboutMisskey.donateHost", { + host: hostname, + }) + }}</MkButton> + </div> + <div class="_flexList"> + <MkButton @click="close">{{ i18n.ts.remindMeLater }}</MkButton> + <MkButton @click="neverShow">{{ i18n.ts.neverShow }}</MkButton> + </div> + </div> + <button class="_button" :class="$style.close" @click="close"> + <i class="ph-x ph-bold ph-lg"></i> + </button> + </div> +</template> + +<script lang="ts" setup> +import MkButton from "@/components/MkButton.vue"; +import { host } from "@/config"; +import { i18n } from "@/i18n"; +import * as os from "@/os"; +import { instance } from "@/instance"; + +const emit = defineEmits<{ + (ev: "closed"): void; +}>(); + +const hostname = instance.name?.length <= 20 ? instance.name : host; + +const zIndex = os.claimZIndex("low"); + +function close() { + localStorage.setItem("latestDonationInfoShownAt", Date.now().toString()); + emit("closed"); +} + +function neverShow() { + localStorage.setItem("neverShowDonationInfo", "true"); + close(); +} + +function openCalckeyDonation() { + window.open("https://opencollective.com/calckey", "_blank"); +} + +function openExternalDonation() { + let link = instance.donationLink; + if (!/^https?:\/\//i.test(link)) { + link = `http://${link}`; + } + window.open(link, "_blank"); +} +</script> + +<style lang="scss" module> +.root { + position: fixed; + z-index: v-bind(zIndex); + bottom: var(--margin); + left: 0; + right: 0; + margin: auto; + box-sizing: border-box; + width: calc(100% - (var(--margin) * 2)); + max-width: 500px; + display: flex; +} + +.icon { + text-align: center; + padding-top: 25px; + width: 100px; + color: var(--accent); +} + +@media (max-width: 500px) { + .icon { + width: 80px; + } +} + +@media (max-width: 450px) { + .icon { + width: 70px; + } +} + +.main { + padding: 25px 25px 25px 0; + flex: 1; +} + +.close { + position: absolute; + top: 8px; + right: 8px; + padding: 8px; +} + +.title { + font-weight: bold; +} + +.text { + margin: 0.7em 0 1em 0; +} +</style> diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts index 11b9a2eda..66be0430d 100644 --- a/packages/client/src/init.ts +++ b/packages/client/src/init.ts @@ -450,6 +450,29 @@ function checkForSplash() { } localStorage.setItem("lastUsed", Date.now().toString()); + const latestDonationInfoShownAt = localStorage.getItem( + "latestDonationInfoShownAt", + ); + const neverShowDonationInfo = localStorage.getItem("neverShowDonationInfo"); + if ( + neverShowDonationInfo !== "true" && + new Date($i.createdAt).getTime() < Date.now() - 1000 * 60 * 60 * 24 * 3 && + !location.pathname.startsWith("/miauth") + ) { + if ( + latestDonationInfoShownAt == null || + new Date(latestDonationInfoShownAt).getTime() < + Date.now() - 1000 * 60 * 60 * 24 * 30 + ) { + popup( + defineAsyncComponent(() => import("@/components/MkDonation.vue")), + {}, + {}, + "closed", + ); + } + } + if ("Notification" in window) { // 許可を得ていなかったらリクエスト if (Notification.permission === "default") { diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index b03a98ae5..4920a82fa 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -53,6 +53,20 @@ i18n.ts.maintainerEmail }}</template> </FormInput> + + <FormInput + v-model="donationLink" + class="_formBlock" + > + <template #prefix + ><i + class="ph-hand-heart ph-bold ph-lg" + ></i + ></template> + <template #label>{{ + i18n.ts.donationLink + }}</template> + </FormInput> </FormSplit> <FormTextarea v-model="pinnedUsers" class="_formBlock"> @@ -435,6 +449,7 @@ let description: string | null = $ref(null); let tosUrl: string | null = $ref(null); let maintainerName: string | null = $ref(null); let maintainerEmail: string | null = $ref(null); +let donationLink: string | null = $ref(null); let iconUrl: string | null = $ref(null); let bannerUrl: string | null = $ref(null); let logoImageUrl: string | null = $ref(null); @@ -481,6 +496,7 @@ async function init() { defaultDarkTheme = meta.defaultDarkTheme; maintainerName = meta.maintainerName; maintainerEmail = meta.maintainerEmail; + donationLink = meta.donationLink; enableLocalTimeline = !meta.disableLocalTimeline; enableGlobalTimeline = !meta.disableGlobalTimeline; enableRecommendedTimeline = !meta.disableRecommendedTimeline; @@ -527,6 +543,7 @@ function save() { defaultDarkTheme: defaultDarkTheme === "" ? null : defaultDarkTheme, maintainerName, maintainerEmail, + donationLink, disableLocalTimeline: !enableLocalTimeline, disableGlobalTimeline: !enableGlobalTimeline, disableRecommendedTimeline: !enableRecommendedTimeline, diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue index e8c616493..4a1598e16 100644 --- a/packages/client/src/pages/settings/2fa.vue +++ b/packages/client/src/pages/settings/2fa.vue @@ -82,7 +82,7 @@ <p> {{ `${i18n.ts.lastUsedDate}: ${key.lastUsed}` }} </p> - <div class="_buttons _flexList"> + <div class="_flexList"> <MkButton @click="renameKey(key)" ><i class="ph-pencil-line ph-bold ph-lg" From 1eb3d4e8662629a093b488ea64f344713086e611 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Tue, 11 Jul 2023 23:42:59 -0700 Subject: [PATCH 067/162] refactor: :recycle: donation link logic, add link to /about, fix typo --- locales/en-US.yml | 2 +- .../server/api/endpoints/admin/update-meta.ts | 18 ++++++++++++++++++ packages/client/src/components/MkDonation.vue | 14 +++----------- packages/client/src/pages/about.vue | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 08eb2a62f..d8a26b1f2 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1219,7 +1219,7 @@ _aboutMisskey: donate: "Donate to Calckey" donateTitle: "Enjoying Calckey?" pleaseDonateToCalckey: "Please consider donating to Calckey to support its development." - pleaseDonateToHost: "Please also consider donating to your honme server, {host}, to help support its operation costs." + pleaseDonateToHost: "Please also consider donating to your home server, {host}, to help support its operation costs." donateHost: "Donate to {host}" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index cf22c6c48..16e49a85a 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -177,6 +177,9 @@ export const paramDef = { postImports: { type: "boolean" }, }, }, + enableServerMachineStats: { type: "boolean" }, + enableIdenticonGeneration: { type: "boolean" }, + donationLink: { type: "string", nullable: true }, }, required: [], } as const; @@ -568,6 +571,21 @@ export default define(meta, paramDef, async (ps, me) => { set.experimentalFeatures = ps.experimentalFeatures || undefined; } + if (ps.enableServerMachineStats !== undefined) { + set.enableServerMachineStats = ps.enableServerMachineStats; + } + + if (ps.enableIdenticonGeneration !== undefined) { + set.enableIdenticonGeneration = ps.enableIdenticonGeneration; + } + + if (ps.donationLink !== undefined) { + set.donationLink = ps.donationLink; + if (set.donationLink && !/^https?:\/\//i.test(set.donationLink)) { + set.donationLink = `https://${set.donationLink}`; + } + } + await db.transaction(async (transactionalEntityManager) => { const metas = await transactionalEntityManager.find(Meta, { order: { diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index beaeef2d2..367ec7b58 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -18,10 +18,10 @@ </p> </div> <div class="_flexList"> - <MkButton primary @click="openCalckeyDonation">{{ + <MkButton primary @click="openExternal('https://opencollective.com/calckey')">{{ i18n.ts._aboutMisskey.donate }}</MkButton> - <MkButton v-if="instance.donationLink" primary @click="openExternalDonation">{{ + <MkButton v-if="instance.donationLink" primary @click="openExternal(instance.donationLink)">{{ i18n.t("_aboutMisskey.donateHost", { host: hostname, }) @@ -63,15 +63,7 @@ function neverShow() { close(); } -function openCalckeyDonation() { - window.open("https://opencollective.com/calckey", "_blank"); -} - -function openExternalDonation() { - let link = instance.donationLink; - if (!/^https?:\/\//i.test(link)) { - link = `http://${link}`; - } +function openExternal(link) { window.open(link, "_blank"); } </script> diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue index 88ed1add2..bbc340fe2 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -93,6 +93,21 @@ external >{{ i18n.ts.tos }}</FormLink > + <FormLink + v-if="$instance.donationLink" + :to="$instance.donationLink" + external + > + <template #icon + ><i class="ph-money ph-bold ph-lg"></i + ></template> + {{ + i18n.t("_aboutMisskey.donateHost", { + host: $instance.name || host, + }) + }} + <template #suffix>Donate</template> + </FormLink> </FormSection> <FormSuspense :p="initStats"> From b9c76a8174ca9504e3efcafd3ed39edbf70bcaeb Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:13:39 -0700 Subject: [PATCH 068/162] dev70 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef2cd9e70..15d7b2ab0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev69", + "version": "14.0.0-dev70", "codename": "aqua", "repository": { "type": "git", From bc6acd7efb9ac4326de022217abe9c61edcf141b Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:23:54 -0700 Subject: [PATCH 069/162] fix: :lipstick: locales, transition for MkDonation --- locales/en-US.yml | 2 + locales/ja-JP.yml | 2 + packages/client/src/components/MkDonation.vue | 107 ++++++++++++------ 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index d8a26b1f2..c61b573ba 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1119,6 +1119,8 @@ showPopup: "Notify users with popup" showWithSparkles: "Show with sparkles" youHaveUnreadAnnouncements: "You have unread announcements" donationLink: "Link to donation page" +neverShow: "Don't show again" +remindMeLater: "Maybe later" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 95fb7bcf8..fe03d1f41 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -983,6 +983,8 @@ enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にす showPopup: "ポップアップを表示してユーザーに知らせる" showWithSparkles: "タイトルをキラキラさせる" youHaveUnreadAnnouncements: "未読のお知らせがあります" +neverShow: "今後表示しない" +remindMeLater: "また後で" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。" diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 367ec7b58..9ec99a6ec 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -1,50 +1,68 @@ <template> - <div class="_panel _shadow" :class="$style.root"> - <div :class="$style.icon"> - <i class="ph-hand-heart ph-bold ph-6x" /> + <transition name="slide-fade"> + <div v-if="show" class="_panel _shadow" :class="$style.root"> + <div :class="$style.icon"> + <i class="ph-hand-heart ph-bold ph-5x" /> + </div> + <div :class="$style.main"> + <div :class="$style.title"> + {{ i18n.ts._aboutMisskey.donateTitle }} + </div> + <div :class="$style.text"> + {{ i18n.ts._aboutMisskey.pleaseDonateToCalckey }} + <p v-if="instance.donationLink"> + {{ + i18n.t("_aboutMisskey.pleaseDonateToHost", { + host: hostname, + }) + }} + </p> + </div> + <div class="_flexList"> + <MkButton + primary + @click=" + openExternal('https://opencollective.com/calckey') + " + >{{ i18n.ts._aboutMisskey.donate }}</MkButton + > + <MkButton + v-if="instance.donationLink" + primary + @click="openExternal(instance.donationLink)" + >{{ + i18n.t("_aboutMisskey.donateHost", { + host: hostname, + }) + }}</MkButton + > + </div> + <div class="_flexList" style="margin-top: 0.6rem"> + <MkButton @click="close">{{ + i18n.ts.remindMeLater + }}</MkButton> + <MkButton @click="neverShow">{{ + i18n.ts.neverShow + }}</MkButton> + </div> + </div> + <button class="_button" :class="$style.close" @click="close"> + <i class="ph-x ph-bold ph-lg"></i> + </button> </div> - <div :class="$style.main"> - <div :class="$style.title"> - {{ i18n.ts._aboutMisskey.donateTitle }} - </div> - <div :class="$style.text"> - {{ i18n.ts._aboutMisskey.pleaseDonateToCalckey }} - <p v-if="instance.donationLink"> - {{ - i18n.t("_aboutMisskey.pleaseDonateToHost", { - host: hostname, - }) - }} - </p> - </div> - <div class="_flexList"> - <MkButton primary @click="openExternal('https://opencollective.com/calckey')">{{ - i18n.ts._aboutMisskey.donate - }}</MkButton> - <MkButton v-if="instance.donationLink" primary @click="openExternal(instance.donationLink)">{{ - i18n.t("_aboutMisskey.donateHost", { - host: hostname, - }) - }}</MkButton> - </div> - <div class="_flexList"> - <MkButton @click="close">{{ i18n.ts.remindMeLater }}</MkButton> - <MkButton @click="neverShow">{{ i18n.ts.neverShow }}</MkButton> - </div> - </div> - <button class="_button" :class="$style.close" @click="close"> - <i class="ph-x ph-bold ph-lg"></i> - </button> - </div> + </transition> </template> <script lang="ts" setup> +import { ref } from "vue"; import MkButton from "@/components/MkButton.vue"; import { host } from "@/config"; import { i18n } from "@/i18n"; import * as os from "@/os"; import { instance } from "@/instance"; +let show = ref(true); + const emit = defineEmits<{ (ev: "closed"): void; }>(); @@ -56,6 +74,7 @@ const zIndex = os.claimZIndex("low"); function close() { localStorage.setItem("latestDonationInfoShownAt", Date.now().toString()); emit("closed"); + show.value = false; } function neverShow() { @@ -116,8 +135,22 @@ function openExternal(link) { .title { font-weight: bold; } - .text { margin: 0.7em 0 1em 0; } + +.slide-fade-enter { + opacity: 1; + transform: translateY(0); +} +.slide-fade-enter-active { + transition: opacity 0.5s, transform 0.5s; +} +.slide-fade-leave-to { + opacity: 0; + transform: translateY(100%); +} +.slide-fade-leave-active { + transition: opacity 0.5s, transform 0.5s; +} </style> From f8f977425c22842477b5eba3c777862fa4485e7b Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:24:04 -0700 Subject: [PATCH 070/162] dev71 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15d7b2ab0..a0bb72c8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev70", + "version": "14.0.0-dev71", "codename": "aqua", "repository": { "type": "git", From b9791ac7f439c72dbc28e2642f4d0280c84fca26 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:36:24 -0700 Subject: [PATCH 071/162] fix: :lipstick: scope transition style --- packages/client/src/components/MkDonation.vue | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 9ec99a6ec..5d3960799 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -1,6 +1,6 @@ <template> <transition name="slide-fade"> - <div v-if="show" class="_panel _shadow" :class="$style.root"> + <div v-if="show" class="_panel _shadow _acrylic" :class="$style.root"> <div :class="$style.icon"> <i class="ph-hand-heart ph-bold ph-5x" /> </div> @@ -87,13 +87,30 @@ function openExternal(link) { } </script> +<style lang="scss" scoped> +.slide-fade-enter { + opacity: 1; + transform: translateY(0); +} +.slide-fade-enter-active { + transition: opacity 0.5s, transform 0.5s; +} +.slide-fade-leave-to { + opacity: 0; + transform: translateY(100%); +} +.slide-fade-leave-active { + transition: opacity 0.5s, transform 0.5s; +} +</style> + <style lang="scss" module> .root { position: fixed; z-index: v-bind(zIndex); bottom: var(--margin); - left: 0; - right: 0; + left: 2%; + bottom: 2%; margin: auto; box-sizing: border-box; width: calc(100% - (var(--margin) * 2)); @@ -138,19 +155,4 @@ function openExternal(link) { .text { margin: 0.7em 0 1em 0; } - -.slide-fade-enter { - opacity: 1; - transform: translateY(0); -} -.slide-fade-enter-active { - transition: opacity 0.5s, transform 0.5s; -} -.slide-fade-leave-to { - opacity: 0; - transform: translateY(100%); -} -.slide-fade-leave-active { - transition: opacity 0.5s, transform 0.5s; -} </style> From 80b07350548e5aa28789a5d13948a1415fcbc660 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:45:53 -0700 Subject: [PATCH 072/162] feat: :lipstick: fly in as well --- packages/client/src/components/MkDonation.vue | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 5d3960799..b368b3e4e 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -88,20 +88,33 @@ function openExternal(link) { </script> <style lang="scss" scoped> -.slide-fade-enter { - opacity: 1; - transform: translateY(0); -} -.slide-fade-enter-active { - transition: opacity 0.5s, transform 0.5s; -} -.slide-fade-leave-to { +.slide-fade-enter-from { opacity: 0; transform: translateY(100%); } + +.slide-fade-enter-active { + transition: opacity 0.5s, transform 0.5s; +} + +.slide-fade-enter-to { + opacity: 1; + transform: translateY(0); +} + +.slide-fade-leave-from { + opacity: 1; + transform: translateY(0); +} + .slide-fade-leave-active { transition: opacity 0.5s, transform 0.5s; } + +.slide-fade-leave-to { + opacity: 0; + transform: translateY(100%); +} </style> <style lang="scss" module> From ae00ff0bb28bcf8a68ea22154298da1d6483a32e Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:48:07 -0700 Subject: [PATCH 073/162] fix: :bug: properly show instance's link --- packages/client/src/components/MkDonation.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index b368b3e4e..a67e5b9d4 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -10,7 +10,7 @@ </div> <div :class="$style.text"> {{ i18n.ts._aboutMisskey.pleaseDonateToCalckey }} - <p v-if="instance.donationLink"> + <p v-if="$instance.donationLink"> {{ i18n.t("_aboutMisskey.pleaseDonateToHost", { host: hostname, @@ -27,9 +27,9 @@ >{{ i18n.ts._aboutMisskey.donate }}</MkButton > <MkButton - v-if="instance.donationLink" + v-if="$instance.donationLink" primary - @click="openExternal(instance.donationLink)" + @click="openExternal($instance.donationLink)" >{{ i18n.t("_aboutMisskey.donateHost", { host: hostname, From 733d7d438a0d4d1df03bf2ac10ddc9780efbeb75 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:54:28 -0700 Subject: [PATCH 074/162] fix: :bug: give donation link in non-admin meta --- packages/backend/src/server/api/endpoints/meta.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 673a0266c..dfb589a43 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -389,6 +389,11 @@ export const meta = { nullable: false, default: "⭐", }, + donationLink: { + type: "string", + optional: "true", + nullable: true, + } }, }, } as const; @@ -491,6 +496,7 @@ export default define(meta, paramDef, async (ps, me) => { translatorAvailable: instance.deeplAuthKey != null || instance.libreTranslateApiUrl != null, defaultReaction: instance.defaultReaction, + donationLink: instance.donationLink, ...(ps.detail ? { From 762f499ef2e1fc0515c56c682fd21038de022088 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:56:40 -0700 Subject: [PATCH 075/162] fix: :lipstick: properly slide in --- packages/client/src/components/MkDonation.vue | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index a67e5b9d4..6d9e3d847 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -54,14 +54,14 @@ </template> <script lang="ts" setup> -import { ref } from "vue"; +import { ref, nextTick } from "vue"; import MkButton from "@/components/MkButton.vue"; import { host } from "@/config"; import { i18n } from "@/i18n"; import * as os from "@/os"; import { instance } from "@/instance"; -let show = ref(true); +let show = ref(false); const emit = defineEmits<{ (ev: "closed"): void; @@ -71,6 +71,15 @@ const hostname = instance.name?.length <= 20 ? instance.name : host; const zIndex = os.claimZIndex("low"); +function slideIn() { + show.value = false; + nextTick(() => { + show.value = true; + }); +} + +slideIn(); + function close() { localStorage.setItem("latestDonationInfoShownAt", Date.now().toString()); emit("closed"); From 67b979c3a1a03d5b237dc2860c0350dc56398fc6 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 00:58:09 -0700 Subject: [PATCH 076/162] fix: :lipstick: ease-out transitions --- packages/client/src/components/MkDonation.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 6d9e3d847..371b2e2a9 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -103,7 +103,7 @@ function openExternal(link) { } .slide-fade-enter-active { - transition: opacity 0.5s, transform 0.5s; + transition: opacity 0.5s, transform 0.5s ease-out; } .slide-fade-enter-to { @@ -117,7 +117,7 @@ function openExternal(link) { } .slide-fade-leave-active { - transition: opacity 0.5s, transform 0.5s; + transition: opacity 0.5s, transform 0.5s ease-out; } .slide-fade-leave-to { From e7c6e17c38306f9b8ca56f5a8d7c45b196804dac Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 01:01:05 -0700 Subject: [PATCH 077/162] gap --- packages/client/src/components/MkDonation.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 371b2e2a9..a2352a4e4 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -18,7 +18,7 @@ }} </p> </div> - <div class="_flexList"> + <div class="_flexList" style="gap: 0.6rem;"> <MkButton primary @click=" From 96e65c74b08ee010e1aea5c22c52b655d7a421b8 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 01:05:16 -0700 Subject: [PATCH 078/162] refactor: :lipstick: max instance name length 37, gradate specific server dono button --- packages/client/src/components/MkDonation.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index a2352a4e4..6b575f30b 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -28,7 +28,7 @@ > <MkButton v-if="$instance.donationLink" - primary + gradate @click="openExternal($instance.donationLink)" >{{ i18n.t("_aboutMisskey.donateHost", { @@ -67,7 +67,7 @@ const emit = defineEmits<{ (ev: "closed"): void; }>(); -const hostname = instance.name?.length <= 20 ? instance.name : host; +const hostname = instance.name?.length < 38 ? instance.name : host; const zIndex = os.claimZIndex("low"); From 85f6ee223121c06c7051ee4de134b8d5e999ab58 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Wed, 12 Jul 2023 13:26:36 -0400 Subject: [PATCH 079/162] fix: match custom emoji size to Misskey's resolves #10438 --- packages/client/src/components/global/MkEmoji.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/global/MkEmoji.vue b/packages/client/src/components/global/MkEmoji.vue index 3e899823a..5da567a0f 100644 --- a/packages/client/src/components/global/MkEmoji.vue +++ b/packages/client/src/components/global/MkEmoji.vue @@ -69,7 +69,7 @@ const alt = computed(() => vertical-align: -0.25em; &.custom { - height: 2.5em; + height: 2em; vertical-align: middle; transition: transform 0.2s ease; From 6e94df51987c81701731f653bbabae63cf532f8d Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Thu, 13 Jul 2023 00:45:26 +0000 Subject: [PATCH 080/162] chore: forgot to remove a debug print stmt? --- packages/backend/src/server/api/stream/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index e778c4946..72dce1951 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -247,7 +247,7 @@ export default class Connection { for (const obj of objs) { const { type, body } = obj; - console.log(type, body); + // console.log(type, body); switch (type) { case "readNotification": this.onReadNotification(body); From 49d599144f7fc9cc3119ddc449fbdc56a0455326 Mon Sep 17 00:00:00 2001 From: DVD <zjdavid.2003@gmail.com> Date: Thu, 13 Jul 2023 09:05:38 +0800 Subject: [PATCH 081/162] Fix CW Import --- packages/backend/src/queue/processors/db/import-masto-post.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/queue/processors/db/import-masto-post.ts b/packages/backend/src/queue/processors/db/import-masto-post.ts index 317ba7b1b..efa4adf3f 100644 --- a/packages/backend/src/queue/processors/db/import-masto-post.ts +++ b/packages/backend/src/queue/processors/db/import-masto-post.ts @@ -50,7 +50,7 @@ export async function importMastoPost( text: text || undefined, reply, renote: null, - cw: post.sensitive, + cw: post.object.sensitive ? post.object.summary : undefined, localOnly: false, visibility: "hidden", visibleUsers: [], From 555bd6c079a6c2c989cd7d9d34935d011faeda10 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 06:11:37 +0200 Subject: [PATCH 082/162] chore: Added translation using Weblate (Galician) --- locales/gl.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 locales/gl.yml diff --git a/locales/gl.yml b/locales/gl.yml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/locales/gl.yml @@ -0,0 +1 @@ +{} From af35eca9f55fdb88cb276ebe005d1a068f3a715e Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:08:41 -0700 Subject: [PATCH 083/162] refactor: :recycle: simplify shift key logic --- .../src/components/MkEmojiPickerDialog.vue | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index 28cc1d215..c168bafd2 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -31,7 +31,7 @@ </template> <script lang="ts" setup> -import { ref, onMounted, onBeforeUnmount } from "vue"; +import { ref } from "vue"; import MkModal from "@/components/MkModal.vue"; import MkEmojiPicker from "@/components/MkEmojiPicker.vue"; import { defaultStore } from "@/store"; @@ -58,22 +58,9 @@ const emit = defineEmits<{ const modal = ref<InstanceType<typeof MkModal>>(); const picker = ref<InstanceType<typeof MkEmojiPicker>>(); -const isShiftKeyPressed = ref(false); - -const keydownHandler = (e) => { - if (e.key === "Shift") { - isShiftKeyPressed.value = true; - } -}; - -const keyupHandler = (e) => { - if (e.key === "Shift") { - isShiftKeyPressed.value = false; - } -}; function checkForShift(ev?: MouseEvent) { - if (!isShiftKeyPressed.value) { + if (ev?.shiftKey) { modal.value?.close(ev); } } @@ -91,16 +78,6 @@ function opening() { } picker.value?.focus(); } - -onMounted(() => { - window.addEventListener("keydown", keydownHandler); - window.addEventListener("keyup", keyupHandler); -}); - -onBeforeUnmount(() => { - window.removeEventListener("keydown", keydownHandler); - window.removeEventListener("keyup", keyupHandler); -}); </script> <style lang="scss" scoped> From b608e5052962de56a0a2d28f77606dcbe07b1ca2 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:11:36 -0700 Subject: [PATCH 084/162] fix: :lipstick: scoped style fix --- packages/client/src/pages/settings/reaction.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index db1ecbe52..29f14fd48 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -12,7 +12,7 @@ <div v-panel style="border-radius: 6px"> <VueDraggable v-model="reactions" - :class="$style.root" + class="zoaiodol" animation="150" delay="100" @end="save" @@ -245,8 +245,8 @@ definePageMetadata({ }); </script> -<style lang="scss" module> -.root { +<style lang="scss" scoped> +.zoaiodol { padding: 12px; font-size: 1.1em; From 1262f074196b53093c178424e95eaa0fe38894d2 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:22:58 -0700 Subject: [PATCH 085/162] refactor: :wheelchair: add aria labels to buttons --- locales/en-US.yml | 3 ++ .../src/server/api/endpoints/admin/meta.ts | 2 +- .../backend/src/server/api/endpoints/meta.ts | 2 +- packages/client/src/components/MkDonation.vue | 36 ++++++++++--------- packages/client/src/components/MkInfo.vue | 1 + .../src/components/MkModalPageWindow.vue | 2 +- .../client/src/components/MkPollEditor.vue | 2 +- packages/client/src/components/MkPostForm.vue | 6 ++-- packages/client/src/components/MkWidgets.vue | 1 + packages/client/src/pages/admin/settings.vue | 4 +-- packages/client/src/pages/follow-requests.vue | 2 ++ packages/client/src/pages/gallery/edit.vue | 1 + packages/client/src/pages/my-groups/group.vue | 1 + packages/client/src/pages/my-lists/list.vue | 1 + 14 files changed, 38 insertions(+), 26 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index c61b573ba..415d87230 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1121,6 +1121,9 @@ youHaveUnreadAnnouncements: "You have unread announcements" donationLink: "Link to donation page" neverShow: "Don't show again" remindMeLater: "Maybe later" +removeQuote: "Remove quote" +removeRecipient: "Remove recipient" +removeMember: "Remove member" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 6c3bb5041..9abb57b1b 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -495,7 +495,7 @@ export const meta = { type: "string", optional: true, nullable: true, - } + }, }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index dfb589a43..03b0da401 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -393,7 +393,7 @@ export const meta = { type: "string", optional: "true", nullable: true, - } + }, }, }, } as const; diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 6b575f30b..d6f6d4801 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -18,7 +18,7 @@ }} </p> </div> - <div class="_flexList" style="gap: 0.6rem;"> + <div class="_flexList" style="gap: 0.6rem"> <MkButton primary @click=" @@ -46,7 +46,7 @@ }}</MkButton> </div> </div> - <button class="_button" :class="$style.close" @click="close"> + <button class="_button" :class="$style.close" @click="close" :aria-label="i18n.t('close')"> <i class="ph-x ph-bold ph-lg"></i> </button> </div> @@ -72,10 +72,10 @@ const hostname = instance.name?.length < 38 ? instance.name : host; const zIndex = os.claimZIndex("low"); function slideIn() { - show.value = false; - nextTick(() => { - show.value = true; - }); + show.value = false; + nextTick(() => { + show.value = true; + }); } slideIn(); @@ -98,31 +98,35 @@ function openExternal(link) { <style lang="scss" scoped> .slide-fade-enter-from { - opacity: 0; - transform: translateY(100%); + opacity: 0; + transform: translateY(100%); } .slide-fade-enter-active { - transition: opacity 0.5s, transform 0.5s ease-out; + transition: + opacity 0.5s, + transform 0.5s ease-out; } .slide-fade-enter-to { - opacity: 1; - transform: translateY(0); + opacity: 1; + transform: translateY(0); } .slide-fade-leave-from { - opacity: 1; - transform: translateY(0); + opacity: 1; + transform: translateY(0); } .slide-fade-leave-active { - transition: opacity 0.5s, transform 0.5s ease-out; + transition: + opacity 0.5s, + transform 0.5s ease-out; } .slide-fade-leave-to { - opacity: 0; - transform: translateY(100%); + opacity: 0; + transform: translateY(100%); } </style> diff --git a/packages/client/src/components/MkInfo.vue b/packages/client/src/components/MkInfo.vue index ba3a606ab..0a9373885 100644 --- a/packages/client/src/components/MkInfo.vue +++ b/packages/client/src/components/MkInfo.vue @@ -12,6 +12,7 @@ v-tooltip="i18n.ts.close" class="_buttonIcon close" @click.stop="close" + :aria-label="i18n.t('close')" > <i class="ph-x ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/components/MkModalPageWindow.vue b/packages/client/src/components/MkModalPageWindow.vue index bf4d8d0bc..e35c6952b 100644 --- a/packages/client/src/components/MkModalPageWindow.vue +++ b/packages/client/src/components/MkModalPageWindow.vue @@ -26,7 +26,7 @@ ></i> <span>{{ pageMetadata?.value.title }}</span> </span> - <button class="_button" @click="$refs.modal.close()"> + <button class="_button" @click="$refs.modal.close()" :aria-label="i18n.t('close')"> <i class="ph-x ph-bold ph-lg"></i> </button> </div> diff --git a/packages/client/src/components/MkPollEditor.vue b/packages/client/src/components/MkPollEditor.vue index e0474ac71..6215e6f2d 100644 --- a/packages/client/src/components/MkPollEditor.vue +++ b/packages/client/src/components/MkPollEditor.vue @@ -14,7 +14,7 @@ @update:modelValue="onInput(i, $event)" > </MkInput> - <button class="_button" @click="remove(i)"> + <button class="_button" @click="remove(i)" :aria-label="i18n.t('remove')"> <i class="ph-x ph-bold ph-lg"></i> </button> </li> diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index ab110b14d..98fc00851 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -11,7 +11,7 @@ > <header> <button v-if="!fixed" class="cancel _button" @click="cancel"> - <i class="ph-x ph-bold ph-lg"></i> + <i class="ph-x ph-bold ph-lg" :aria-label="i18n.t('close')"></i> </button> <button v-if="$props.editId == null" @@ -84,7 +84,7 @@ <div v-if="quoteId" class="with-quote"> <i class="ph-quotes ph-bold ph-lg"></i> {{ i18n.ts.quoteAttached - }}<button class="_button" @click="quoteId = null"> + }}<button class="_button" @click="quoteId = null" :aria-label="i18n.t('removeQuote')"> <i class="ph-x ph-bold ph-lg"></i> </button> </div> @@ -93,7 +93,7 @@ <div class="visibleUsers"> <span v-for="u in visibleUsers" :key="u.id"> <MkAcct :user="u" /> - <button class="_button" @click="removeVisibleUser(u)"> + <button class="_button" @click="removeVisibleUser(u)" :aria-label="i18n.t('removeRecipient')"> <i class="ph-x ph-bold ph-lg"></i> </button> </span> diff --git a/packages/client/src/components/MkWidgets.vue b/packages/client/src/components/MkWidgets.vue index 272ba1404..f6241512f 100644 --- a/packages/client/src/components/MkWidgets.vue +++ b/packages/client/src/components/MkWidgets.vue @@ -40,6 +40,7 @@ <button class="remove _button" @click.prevent.stop="removeWidget(element)" + :aria-label="i18n.t('close')" > <i class="ph-x ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index 4920a82fa..a33335089 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -59,9 +59,7 @@ class="_formBlock" > <template #prefix - ><i - class="ph-hand-heart ph-bold ph-lg" - ></i + ><i class="ph-hand-heart ph-bold ph-lg"></i ></template> <template #label>{{ i18n.ts.donationLink diff --git a/packages/client/src/pages/follow-requests.vue b/packages/client/src/pages/follow-requests.vue index b0f8cd5b1..d6afcf456 100644 --- a/packages/client/src/pages/follow-requests.vue +++ b/packages/client/src/pages/follow-requests.vue @@ -60,12 +60,14 @@ <button class="_button" @click="accept(req.follower)" + :aria-label="i18n.t('accept')" > <i class="ph-check ph-bold ph-lg"></i> </button> <button class="_button" @click="reject(req.follower)" + :aria-label="i18n.t('reject')" > <i class="ph-x ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/pages/gallery/edit.vue b/packages/client/src/pages/gallery/edit.vue index a98e643b3..72da912ea 100644 --- a/packages/client/src/pages/gallery/edit.vue +++ b/packages/client/src/pages/gallery/edit.vue @@ -29,6 +29,7 @@ v-tooltip="i18n.ts.remove" class="remove _button" @click="remove(file)" + :aria-label="i18n.t('remove')" > <i class="ph-x ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/pages/my-groups/group.vue b/packages/client/src/pages/my-groups/group.vue index 30aa0d830..d77751e8d 100644 --- a/packages/client/src/pages/my-groups/group.vue +++ b/packages/client/src/pages/my-groups/group.vue @@ -23,6 +23,7 @@ <button class="_button" @click="removeUser(user)" + :aria-label="i18n.t('removeMember')" > <i class="ph-x ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/pages/my-lists/list.vue b/packages/client/src/pages/my-lists/list.vue index 43b18dac5..fe02c2ddd 100644 --- a/packages/client/src/pages/my-lists/list.vue +++ b/packages/client/src/pages/my-lists/list.vue @@ -50,6 +50,7 @@ <button class="_button" @click="removeUser(user)" + :aria-label="i18n.t('removeMember')" > <i class="ph-x ph-bold ph-lg"></i> </button> From 6cf6ce7bb97909dff8784034407a6fd4f79c9589 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:23:09 -0700 Subject: [PATCH 086/162] dev72 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0bb72c8f..b4b7ba646 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev71", + "version": "14.0.0-dev72", "codename": "aqua", "repository": { "type": "git", From d7d4e4358b3576866c2bb5a1620e338c997be572 Mon Sep 17 00:00:00 2001 From: jolupa <jolupameister@gmail.com> Date: Wed, 12 Jul 2023 10:22:03 +0000 Subject: [PATCH 087/162] chore: Translated using Weblate (Catalan) Currently translated at 100.0% (1827 of 1827 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ca/ --- locales/ca-ES.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 1f291ac22..f855f6732 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1603,6 +1603,12 @@ _aboutMisskey: patrons: Mecenes de Calckey patronsList: Llistats cronològicament, no per la quantitat donada. Fes una donació amb l'enllaç de dalt per veure el teu nom aquí! + donateTitle: T'agrada Calckey? + pleaseDonateToCalckey: Penseu en fer una donació a Calckey per donar suport al seu + desenvolupament. + pleaseDonateToHost: Penseu també en fer una donació a la vostre instància, {host}, + per ajudar-lo a suportar els costos de funcionament. + donateHost: Fes una donació a {host} unknown: Desconegut pageLikesCount: Nombre de pàgines amb M'agrada youAreRunningUpToDateClient: Estás fent servir la versió del client més nova. @@ -2147,3 +2153,7 @@ enableServerMachineStats: Habilitar les estadístiques del maquinari del servido showPopup: Notificar els usuaris amb una finestra emergent showWithSparkles: Mostra amb espurnes youHaveUnreadAnnouncements: Tens anuncis sense llegir +xl: XL +donationLink: Enllaç a la pàgina de donacions +neverShow: No tornis a mostrar +remindMeLater: Potser després From 6883f0f280ec802697987a7c19c8e84f83fe2d85 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:31:14 -0700 Subject: [PATCH 088/162] Revert "refactor: :recycle: simplify shift key logic" This reverts commit ea767909978b5dd7158c0d38a1a1f6053772e814. --- .../src/components/MkEmojiPickerDialog.vue | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index c168bafd2..28cc1d215 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -31,7 +31,7 @@ </template> <script lang="ts" setup> -import { ref } from "vue"; +import { ref, onMounted, onBeforeUnmount } from "vue"; import MkModal from "@/components/MkModal.vue"; import MkEmojiPicker from "@/components/MkEmojiPicker.vue"; import { defaultStore } from "@/store"; @@ -58,9 +58,22 @@ const emit = defineEmits<{ const modal = ref<InstanceType<typeof MkModal>>(); const picker = ref<InstanceType<typeof MkEmojiPicker>>(); +const isShiftKeyPressed = ref(false); + +const keydownHandler = (e) => { + if (e.key === "Shift") { + isShiftKeyPressed.value = true; + } +}; + +const keyupHandler = (e) => { + if (e.key === "Shift") { + isShiftKeyPressed.value = false; + } +}; function checkForShift(ev?: MouseEvent) { - if (ev?.shiftKey) { + if (!isShiftKeyPressed.value) { modal.value?.close(ev); } } @@ -78,6 +91,16 @@ function opening() { } picker.value?.focus(); } + +onMounted(() => { + window.addEventListener("keydown", keydownHandler); + window.addEventListener("keyup", keyupHandler); +}); + +onBeforeUnmount(() => { + window.removeEventListener("keydown", keydownHandler); + window.removeEventListener("keyup", keyupHandler); +}); </script> <style lang="scss" scoped> From 3cfd634940b3cb43a7609f071de16fa5c1d238b8 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:32:28 -0700 Subject: [PATCH 089/162] dev73 --- package.json | 2 +- pnpm-lock.yaml | 1981 +++++++++++++++++++----------------------------- 2 files changed, 773 insertions(+), 1210 deletions(-) diff --git a/package.json b/package.json index b4b7ba646..6ca8bf72c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev72", + "version": "14.0.0-dev73", "codename": "aqua", "repository": { "type": "git", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1189c2343..ff6f98d88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,7 +173,7 @@ importers: version: 0.4.0 chokidar: specifier: ^3.3.1 - version: 3.5.3 + version: 3.3.1 cli-highlight: specifier: 2.1.11 version: 2.1.11 @@ -424,7 +424,7 @@ importers: devDependencies: '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.68)(chokidar@3.5.3) + version: 0.1.62(@swc/core@1.3.68)(chokidar@3.3.1) '@swc/core': specifier: ^1.3.68 version: 1.3.68 @@ -598,7 +598,7 @@ importers: version: 5.1.6 webpack: specifier: ^5.88.1 - version: 5.88.1(@swc/core@1.3.68) + version: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) ws: specifier: 8.13.0 version: 8.13.0 @@ -622,7 +622,7 @@ importers: version: 4.4.0 semver: specifier: ^7.3.8 - version: 7.5.1 + version: 7.5.4 optionalDependencies: '@swc/core-android-arm64': specifier: 1.3.11 @@ -636,10 +636,10 @@ importers: version: 7.36.0(@types/node@20.3.1) '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62) + version: 0.1.62(@swc/core@1.3.68)(chokidar@3.3.1) '@swc/core': specifier: ^1.3.62 - version: 1.3.62 + version: 1.3.68 '@types/jest': specifier: ^27.4.0 version: 27.4.0 @@ -660,10 +660,10 @@ importers: version: 9.0.8 ts-jest: specifier: ^27.1.2 - version: 27.1.2(@babel/core@7.22.8)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3) + version: 27.1.2(@babel/core@7.22.9)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3) ts-node: specifier: 10.4.0 - version: 10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3) + version: 10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3) tsd: specifier: ^0.28.1 version: 0.28.1 @@ -930,7 +930,7 @@ importers: version: 0.9.1 '@types/ws': specifier: ^8.5.4 - version: 8.5.4 + version: 8.5.5 async-lock: specifier: 1.4.0 version: 1.4.0 @@ -939,7 +939,7 @@ importers: version: 1.2.2 dayjs: specifier: ^1.11.7 - version: 1.11.8 + version: 1.11.7 form-data: specifier: ^4.0.0 version: 4.0.0 @@ -991,37 +991,37 @@ importers: version: 2.0.0 '@types/uuid': specifier: ^9.0.0 - version: 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.42.0)(typescript@4.9.4) + 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.42.0)(typescript@4.9.4) + version: 5.49.0(eslint@8.44.0)(typescript@4.9.4) eslint: specifier: ^8.32.0 - version: 8.42.0 + version: 8.44.0 eslint-config-prettier: specifier: ^8.6.0 - version: 8.6.0(eslint@8.42.0) + version: 8.6.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.42.0) + 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.42.0) + 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.42.0) + version: 11.0.0(eslint@8.44.0) eslint-plugin-prettier: specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.42.0)(prettier@2.8.8) + version: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@2.8.3) eslint-plugin-promise: specifier: ^6.1.1 - version: 6.1.1(eslint@8.42.0) + version: 6.1.1(eslint@8.44.0) eslint-plugin-standard: specifier: ^5.0.0 - version: 5.0.0(eslint@8.42.0) + version: 5.0.0(eslint@8.44.0) jest: specifier: ^29.4.0 version: 29.4.0(@types/node@18.11.18) @@ -1030,13 +1030,13 @@ importers: version: 29.4.0 lodash: specifier: ^4.17.14 - version: 4.17.21 + version: 4.17.14 prettier: specifier: ^2.8.3 - version: 2.8.8 + version: 2.8.3 ts-jest: specifier: ^29.0.5 - version: 29.0.5(@babel/core@7.22.8)(jest@29.4.0)(typescript@4.9.4) + version: 29.0.5(@babel/core@7.22.9)(jest@29.4.0)(typescript@4.9.4) typedoc: specifier: ^0.23.24 version: 0.23.24(typescript@4.9.4) @@ -1045,10 +1045,10 @@ importers: devDependencies: '@swc/cli': specifier: ^0.1.62 - version: 0.1.62(@swc/core@1.3.62) + version: 0.1.62(@swc/core@1.3.68)(chokidar@3.3.1) '@swc/core': specifier: ^1.3.62 - version: 1.3.62 + version: 1.3.68 '@swc/core-android-arm64': specifier: 1.3.11 version: 1.3.11 @@ -1060,13 +1060,13 @@ importers: version: 6.2.1 swc-loader: specifier: ^0.2.3 - version: 0.2.3(@swc/core@1.3.62)(webpack@5.85.1) + version: 0.2.3(@swc/core@1.3.68)(webpack@5.88.1) webpack: specifier: ^5.85.1 - version: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) + version: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) webpack-cli: specifier: ^5.1.3 - version: 5.1.3(webpack@5.85.1) + version: 5.1.3(webpack@5.88.1) packages: @@ -1087,62 +1087,34 @@ packages: dependencies: '@babel/highlight': 7.22.5 - /@babel/compat-data@7.22.5: - resolution: {integrity: sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==} + /@babel/compat-data@7.22.9: + resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} engines: {node: '>=6.9.0'} - /@babel/compat-data@7.22.6: - resolution: {integrity: sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.22.5: - resolution: {integrity: sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==} + /@babel/core@7.22.9: + resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.5 - '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.5) - '@babel/helper-module-transforms': 7.22.5 - '@babel/helpers': 7.22.5 - '@babel/parser': 7.22.5 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.5 - '@babel/types': 7.22.5 - convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - /@babel/core@7.22.8: - resolution: {integrity: sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.7 - '@babel/helper-compilation-targets': 7.22.6(@babel/core@7.22.8) - '@babel/helper-module-transforms': 7.22.5 + '@babel/generator': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) '@babel/helpers': 7.22.6 '@babel/parser': 7.22.7 '@babel/template': 7.22.5 '@babel/traverse': 7.22.8 '@babel/types': 7.22.5 - '@nicolo-ribaudo/semver-v6': 6.3.3 convert-source-map: 1.9.0 debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 + semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true - /@babel/generator@7.22.5: - resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==} + /@babel/generator@7.22.9: + resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.5 @@ -1150,43 +1122,19 @@ packages: '@jridgewell/trace-mapping': 0.3.18 jsesc: 2.5.2 - /@babel/generator@7.22.7: - resolution: {integrity: sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.5): - resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==} + /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.22.5 - '@babel/core': 7.22.5 + '@babel/compat-data': 7.22.9 + '@babel/core': 7.22.9 '@babel/helper-validator-option': 7.22.5 browserslist: 4.21.9 lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-compilation-targets@7.22.6(@babel/core@7.22.8): - resolution: {integrity: sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.22.6 - '@babel/core': 7.22.8 - '@babel/helper-validator-option': 7.22.5 - '@nicolo-ribaudo/semver-v6': 6.3.3 - browserslist: 4.21.9 - lru-cache: 5.1.1 - dev: true - /@babel/helper-environment-visitor@7.22.5: resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} engines: {node: '>=6.9.0'} @@ -1210,20 +1158,18 @@ packages: dependencies: '@babel/types': 7.22.5 - /@babel/helper-module-transforms@7.22.5: - resolution: {integrity: sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==} + /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 dependencies: + '@babel/core': 7.22.9 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-module-imports': 7.22.5 '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.5 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.5 - '@babel/types': 7.22.5 - transitivePeerDependencies: - - supports-color /@babel/helper-plugin-utils@7.22.5: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} @@ -1235,18 +1181,11 @@ packages: dependencies: '@babel/types': 7.22.5 - /@babel/helper-split-export-declaration@7.22.5: - resolution: {integrity: sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 - /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.5 - dev: true /@babel/helper-string-parser@7.22.5: resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} @@ -1260,16 +1199,6 @@ packages: resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} engines: {node: '>=6.9.0'} - /@babel/helpers@7.22.5: - resolution: {integrity: sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.5 - '@babel/types': 7.22.5 - transitivePeerDependencies: - - supports-color - /@babel/helpers@7.22.6: resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} engines: {node: '>=6.9.0'} @@ -1279,7 +1208,6 @@ packages: '@babel/types': 7.22.5 transitivePeerDependencies: - supports-color - dev: true /@babel/highlight@7.22.5: resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} @@ -1289,182 +1217,172 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.22.5: - resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.5 - /@babel/parser@7.22.7: resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} engines: {node: '>=6.0.0'} hasBin: true dependencies: '@babel/types': 7.22.5 - dev: true - /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.5): + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.9): resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.5) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) dev: false - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.5): + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.9): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.5): + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.9): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: false - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.5): + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.9): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.5): + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.5): + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.9): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.5): + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.9): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.5): + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.9): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.5): + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.9): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.5): + /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.5): + /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.5 - '@babel/helper-module-transforms': 7.22.5 + '@babel/core': 7.22.9 + '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 - transitivePeerDependencies: - - supports-color dev: false /@babel/runtime@7.21.0: @@ -1474,8 +1392,8 @@ packages: regenerator-runtime: 0.13.11 dev: true - /@babel/runtime@7.22.5: - resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==} + /@babel/runtime@7.22.6: + resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 @@ -1485,32 +1403,15 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.5 - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@babel/types': 7.22.5 - /@babel/traverse@7.22.5: - resolution: {integrity: sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.5 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.5 - '@babel/parser': 7.22.5 - '@babel/types': 7.22.5 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - /@babel/traverse@7.22.8: resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.7 + '@babel/generator': 7.22.9 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-function-name': 7.22.5 '@babel/helper-hoist-variables': 7.22.5 @@ -1521,7 +1422,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/types@7.22.5: resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} @@ -1800,8 +1700,8 @@ packages: - supports-color dev: false - /@esbuild/android-arm64@0.18.11: - resolution: {integrity: sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==} + /@esbuild/android-arm64@0.18.12: + resolution: {integrity: sha512-BMAlczRqC/LUt2P97E4apTBbkvS9JTJnp2DKFbCwpZ8vBvXVbNdqmvzW/OsdtI/+mGr+apkkpqGM8WecLkPgrA==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -1809,8 +1709,8 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.18.11: - resolution: {integrity: sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==} + /@esbuild/android-arm@0.18.12: + resolution: {integrity: sha512-LIxaNIQfkFZbTLb4+cX7dozHlAbAshhFE5PKdro0l+FnCpx1GDJaQ2WMcqm+ToXKMt8p8Uojk/MFRuGyz3V5Sw==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1818,8 +1718,8 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.18.11: - resolution: {integrity: sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==} + /@esbuild/android-x64@0.18.12: + resolution: {integrity: sha512-zU5MyluNsykf5cOJ0LZZZjgAHbhPJ1cWfdH1ZXVMXxVMhEV0VZiZXQdwBBVvmvbF28EizeK7obG9fs+fpmS0eQ==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1827,8 +1727,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.18.11: - resolution: {integrity: sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==} + /@esbuild/darwin-arm64@0.18.12: + resolution: {integrity: sha512-zUZMep7YONnp6954QOOwEBwFX9svlKd3ov6PkxKd53LGTHsp/gy7vHaPGhhjBmEpqXEXShi6dddjIkmd+NgMsA==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1836,8 +1736,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.18.11: - resolution: {integrity: sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==} + /@esbuild/darwin-x64@0.18.12: + resolution: {integrity: sha512-ohqLPc7i67yunArPj1+/FeeJ7AgwAjHqKZ512ADk3WsE3FHU9l+m5aa7NdxXr0HmN1bjDlUslBjWNbFlD9y12Q==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1845,8 +1745,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.18.11: - resolution: {integrity: sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==} + /@esbuild/freebsd-arm64@0.18.12: + resolution: {integrity: sha512-GIIHtQXqgeOOqdG16a/A9N28GpkvjJnjYMhOnXVbn3EDJcoItdR58v/pGN31CHjyXDc8uCcRnFWmqaJt24AYJg==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1854,8 +1754,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.18.11: - resolution: {integrity: sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==} + /@esbuild/freebsd-x64@0.18.12: + resolution: {integrity: sha512-zK0b9a1/0wZY+6FdOS3BpZcPc1kcx2G5yxxfEJtEUzVxI6n/FrC2Phsxj/YblPuBchhBZ/1wwn7AyEBUyNSa6g==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1863,8 +1763,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.18.11: - resolution: {integrity: sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==} + /@esbuild/linux-arm64@0.18.12: + resolution: {integrity: sha512-JKgG8Q/LL/9sw/iHHxQyVMoQYu3rU3+a5Z87DxC+wAu3engz+EmctIrV+FGOgI6gWG1z1+5nDDbXiRMGQZXqiw==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1872,8 +1772,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.18.11: - resolution: {integrity: sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==} + /@esbuild/linux-arm@0.18.12: + resolution: {integrity: sha512-y75OijvrBE/1XRrXq1jtrJfG26eHeMoqLJ2dwQNwviwTuTtHGCojsDO6BJNF8gU+3jTn1KzJEMETytwsFSvc+Q==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1881,8 +1781,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.18.11: - resolution: {integrity: sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==} + /@esbuild/linux-ia32@0.18.12: + resolution: {integrity: sha512-yoRIAqc0B4lDIAAEFEIu9ttTRFV84iuAl0KNCN6MhKLxNPfzwCBvEMgwco2f71GxmpBcTtn7KdErueZaM2rEvw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1890,8 +1790,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.18.11: - resolution: {integrity: sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==} + /@esbuild/linux-loong64@0.18.12: + resolution: {integrity: sha512-qYgt3dHPVvf/MgbIBpJ4Sup/yb9DAopZ3a2JgMpNKIHUpOdnJ2eHBo/aQdnd8dJ21X/+sS58wxHtA9lEazYtXQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1899,8 +1799,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.18.11: - resolution: {integrity: sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==} + /@esbuild/linux-mips64el@0.18.12: + resolution: {integrity: sha512-wHphlMLK4ufNOONqukELfVIbnGQJrHJ/mxZMMrP2jYrPgCRZhOtf0kC4yAXBwnfmULimV1qt5UJJOw4Kh13Yfg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1908,8 +1808,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.18.11: - resolution: {integrity: sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==} + /@esbuild/linux-ppc64@0.18.12: + resolution: {integrity: sha512-TeN//1Ft20ZZW41+zDSdOI/Os1bEq5dbvBvYkberB7PHABbRcsteeoNVZFlI0YLpGdlBqohEpjrn06kv8heCJg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1917,8 +1817,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.18.11: - resolution: {integrity: sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==} + /@esbuild/linux-riscv64@0.18.12: + resolution: {integrity: sha512-AgUebVS4DoAblBgiB2ACQ/8l4eGE5aWBb8ZXtkXHiET9mbj7GuWt3OnsIW/zX+XHJt2RYJZctbQ2S/mDjbp0UA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1926,8 +1826,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.18.11: - resolution: {integrity: sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==} + /@esbuild/linux-s390x@0.18.12: + resolution: {integrity: sha512-dJ3Rb3Ei2u/ysSXd6pzleGtfDdc2MuzKt8qc6ls8vreP1G3B7HInX3i7gXS4BGeVd24pp0yqyS7bJ5NHaI9ing==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1935,8 +1835,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.18.11: - resolution: {integrity: sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==} + /@esbuild/linux-x64@0.18.12: + resolution: {integrity: sha512-OrNJMGQbPaVyHHcDF8ybNSwu7TDOfX8NGpXCbetwOSP6txOJiWlgQnRymfC9ocR1S0Y5PW0Wb1mV6pUddqmvmQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1944,8 +1844,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.18.11: - resolution: {integrity: sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==} + /@esbuild/netbsd-x64@0.18.12: + resolution: {integrity: sha512-55FzVCAiwE9FK8wWeCRuvjazNRJ1QqLCYGZVB6E8RuQuTeStSwotpSW4xoRGwp3a1wUsaVCdYcj5LGCASVJmMg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -1953,8 +1853,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.18.11: - resolution: {integrity: sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==} + /@esbuild/openbsd-x64@0.18.12: + resolution: {integrity: sha512-qnluf8rfb6Y5Lw2tirfK2quZOBbVqmwxut7GPCIJsM8lc4AEUj9L8y0YPdLaPK0TECt4IdyBdBD/KRFKorlK3g==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -1962,8 +1862,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.18.11: - resolution: {integrity: sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==} + /@esbuild/sunos-x64@0.18.12: + resolution: {integrity: sha512-+RkKpVQR7bICjTOPUpkTBTaJ4TFqQBX5Ywyd/HSdDkQGn65VPkTsR/pL4AMvuMWy+wnXgIl4EY6q4mVpJal8Kg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -1971,8 +1871,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.18.11: - resolution: {integrity: sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==} + /@esbuild/win32-arm64@0.18.12: + resolution: {integrity: sha512-GNHuciv0mFM7ouzsU0+AwY+7eV4Mgo5WnbhfDCQGtpvOtD1vbOiRjPYG6dhmMoFyBjj+pNqQu2X+7DKn0KQ/Gw==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -1980,8 +1880,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.18.11: - resolution: {integrity: sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==} + /@esbuild/win32-ia32@0.18.12: + resolution: {integrity: sha512-kR8cezhYipbbypGkaqCTWIeu4zID17gamC8YTPXYtcN3E5BhhtTnwKBn9I0PJur/T6UVwIEGYzkffNL0lFvxEw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -1989,8 +1889,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.18.11: - resolution: {integrity: sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==} + /@esbuild/win32-x64@0.18.12: + resolution: {integrity: sha512-O0UYQVkvfM/jO8a4OwoV0mAKSJw+mjWTAd1MJd/1FCX6uiMdLmMRPK/w6e9OQ0ob2WGxzIm9va/KG0Ja4zIOgg==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -1998,16 +1898,6 @@ packages: dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.42.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.42.0 - eslint-visitor-keys: 3.4.1 - dev: 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} @@ -2021,23 +1911,6 @@ packages: resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - /@eslint/eslintrc@2.0.3: - resolution: {integrity: sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.5.2 - globals: 13.20.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - /@eslint/eslintrc@2.1.0: resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2054,11 +1927,6 @@ packages: transitivePeerDependencies: - supports-color - /@eslint/js@8.42.0: - resolution: {integrity: sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - /@eslint/js@8.44.0: resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2127,22 +1995,22 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 slash: 3.0.0 dev: true - /@jest/console@29.6.0: - resolution: {integrity: sha512-anb6L1yg7uPQpytNVA5skRaXy3BmrsU8icRhTVNbWdjYWDDfy8M1Kq5HIVRpYoABdbpqsc5Dr+jtu4+qWRQBiQ==} + /@jest/console@29.6.1: + resolution: {integrity: sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 chalk: 4.1.2 - jest-message-util: 29.6.0 - jest-util: 29.6.0 + jest-message-util: 29.6.1 + jest-util: 29.6.1 slash: 3.0.0 dev: true @@ -2160,7 +2028,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 @@ -2191,8 +2059,8 @@ packages: - utf-8-validate dev: true - /@jest/core@29.6.0: - resolution: {integrity: sha512-5dbMHfY/5R9m8NbgmB3JlxQqooZ/ooPSOiwEQZZ+HODwJTbIu37seVcZNBK29aMdXtjvTRB3f6LCvkKq+r8uQA==} + /@jest/core@29.6.1: + resolution: {integrity: sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -2200,32 +2068,32 @@ packages: node-notifier: optional: true dependencies: - '@jest/console': 29.6.0 - '@jest/reporters': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/transform': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/console': 29.6.1 + '@jest/reporters': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.5.0 - jest-config: 29.6.0(@types/node@18.11.18) - jest-haste-map: 29.6.0 - jest-message-util: 29.6.0 + jest-config: 29.6.1(@types/node@20.4.1) + jest-haste-map: 29.6.1 + jest-message-util: 29.6.1 jest-regex-util: 29.4.3 - jest-resolve: 29.6.0 - jest-resolve-dependencies: 29.6.0 - jest-runner: 29.6.0 - jest-runtime: 29.6.0 - jest-snapshot: 29.6.0 - jest-util: 29.6.0 - jest-validate: 29.6.0 - jest-watcher: 29.6.0 + jest-resolve: 29.6.1 + jest-resolve-dependencies: 29.6.1 + jest-runner: 29.6.1 + jest-runtime: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 + jest-validate: 29.6.1 + jest-watcher: 29.6.1 micromatch: 4.0.5 - pretty-format: 29.6.0 + pretty-format: 29.6.1 slash: 3.0.0 strip-ansi: 6.0.1 transitivePeerDependencies: @@ -2239,33 +2107,33 @@ packages: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 jest-mock: 27.5.1 dev: true - /@jest/environment@29.6.0: - resolution: {integrity: sha512-bUZLYUxYlUIsslBbxII0fq0kr1+friI3Gty+cRLmocGB1jdcAHs7FS8QdCDqedE8q4DZE1g/AJHH6OJZBLGGsg==} + /@jest/environment@29.6.1: + resolution: {integrity: sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/fake-timers': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 - jest-mock: 29.6.0 + '@jest/fake-timers': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 + jest-mock: 29.6.1 dev: true - /@jest/expect-utils@29.6.0: - resolution: {integrity: sha512-LLSQQN7oypMSETKoPWpsWYVKJd9LQWmSDDAc4hUQ4JocVC7LAMy9R3ZMhlnLwbcFvQORZnZR7HM893Px6cJhvA==} + /@jest/expect-utils@29.6.1: + resolution: {integrity: sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: jest-get-type: 29.4.3 dev: true - /@jest/expect@29.6.0: - resolution: {integrity: sha512-a7pISPW28Q3c0/pLwz4mQ6tbAI+hc8/0CJp9ix6e9U4dQ6TiHQX82CT5DV5BMWaw8bFH4E6zsfZxXdn6Ka23Bw==} + /@jest/expect@29.6.1: + resolution: {integrity: sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - expect: 29.6.0 - jest-snapshot: 29.6.0 + expect: 29.6.1 + jest-snapshot: 29.6.1 transitivePeerDependencies: - supports-color dev: true @@ -2276,22 +2144,22 @@ packages: dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 20.3.1 + '@types/node': 20.4.1 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 dev: true - /@jest/fake-timers@29.6.0: - resolution: {integrity: sha512-nuCU46AsZoskthWSDS2Aj6LARgyNcp5Fjx2qxsO/fPl1Wp1CJ+dBDqs0OkEcJK8FBeV/MbjH5efe79M2sHcV+A==} + /@jest/fake-timers@29.6.1: + resolution: {integrity: sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 + '@jest/types': 29.6.1 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.11.18 - jest-message-util: 29.6.0 - jest-mock: 29.6.0 - jest-util: 29.6.0 + '@types/node': 20.4.1 + jest-message-util: 29.6.1 + jest-mock: 29.6.1 + jest-util: 29.6.1 dev: true /@jest/globals@27.5.1: @@ -2303,14 +2171,14 @@ packages: expect: 27.5.1 dev: true - /@jest/globals@29.6.0: - resolution: {integrity: sha512-IQQ3hZ2D/hwEwXSMv5GbfhzdH0nTQR3KPYxnuW6gYWbd6+7/zgMz7Okn6EgBbNtJNONq03k5EKA6HqGyzRbpeg==} + /@jest/globals@29.6.1: + resolution: {integrity: sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.6.0 - '@jest/expect': 29.6.0 - '@jest/types': 29.6.0 - jest-mock: 29.6.0 + '@jest/environment': 29.6.1 + '@jest/expect': 29.6.1 + '@jest/types': 29.6.1 + jest-mock: 29.6.1 transitivePeerDependencies: - supports-color dev: true @@ -2329,9 +2197,9 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 exit: 0.1.2 glob: 7.2.3 graceful-fs: 4.2.11 @@ -2353,8 +2221,8 @@ packages: - supports-color dev: true - /@jest/reporters@29.6.0: - resolution: {integrity: sha512-dWEq4HI0VvHcAD6XTtyBKKARLytyyWPIy1SvGOcU91106MfvHPdxZgupFwVHd8TFpZPpA3SebYjtwS5BUS76Rw==} + /@jest/reporters@29.6.1: + resolution: {integrity: sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -2363,14 +2231,14 @@ packages: optional: true dependencies: '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/transform': 29.6.0 - '@jest/types': 29.6.0 + '@jest/console': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 '@jridgewell/trace-mapping': 0.3.18 - '@types/node': 18.11.18 + '@types/node': 20.4.1 chalk: 4.1.2 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 exit: 0.1.2 glob: 7.2.3 graceful-fs: 4.2.11 @@ -2379,9 +2247,9 @@ packages: istanbul-lib-report: 3.0.0 istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.1.5 - jest-message-util: 29.6.0 - jest-util: 29.6.0 - jest-worker: 29.6.0 + jest-message-util: 29.6.1 + jest-util: 29.6.1 + jest-worker: 29.6.1 slash: 3.0.0 string-length: 4.0.2 strip-ansi: 6.0.1 @@ -2390,13 +2258,6 @@ packages: - supports-color dev: true - /@jest/schemas@29.4.3: - resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.25.24 - dev: true - /@jest/schemas@29.6.0: resolution: {integrity: sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2429,17 +2290,17 @@ packages: '@jest/console': 27.5.1 '@jest/types': 27.5.1 '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 dev: true - /@jest/test-result@29.6.0: - resolution: {integrity: sha512-9qLb7xITeyWhM4yatn2muqfomuoCTOhv0QV9i7XiIyYi3QLfnvPv5NeJp5u0PZeutAOROMLKakOkmoAisOr3YQ==} + /@jest/test-result@29.6.1: + resolution: {integrity: sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/console': 29.6.0 - '@jest/types': 29.6.0 + '@jest/console': 29.6.1 + '@jest/types': 29.6.1 '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 dev: true /@jest/test-sequencer@27.5.1: @@ -2454,13 +2315,13 @@ packages: - supports-color dev: true - /@jest/test-sequencer@29.6.0: - resolution: {integrity: sha512-HYCS3LKRQotKWj2mnA3AN13PPevYZu8MJKm12lzYojpJNnn6kI/3PWmr1At/e3tUu+FHQDiOyaDVuR4EV3ezBw==} + /@jest/test-sequencer@29.6.1: + resolution: {integrity: sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/test-result': 29.6.0 + '@jest/test-result': 29.6.1 graceful-fs: 4.2.11 - jest-haste-map: 29.6.0 + jest-haste-map: 29.6.1 slash: 3.0.0 dev: true @@ -2468,7 +2329,7 @@ packages: resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@jest/types': 27.5.1 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 @@ -2487,21 +2348,21 @@ packages: - supports-color dev: true - /@jest/transform@29.6.0: - resolution: {integrity: sha512-bhP/KxPo3e322FJ0nKAcb6WVK76ZYyQd1lWygJzoSqP8SYMSLdxHqP4wnPTI4WvbB8PKPDV30y5y7Tya4RHOBA==} + /@jest/transform@29.6.1: + resolution: {integrity: sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/core': 7.22.5 - '@jest/types': 29.6.0 + '@babel/core': 7.22.9 + '@jest/types': 29.6.1 '@jridgewell/trace-mapping': 0.3.18 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 convert-source-map: 2.0.0 fast-json-stable-stringify: 2.1.0 graceful-fs: 4.2.11 - jest-haste-map: 29.6.0 + jest-haste-map: 29.6.1 jest-regex-util: 29.4.3 - jest-util: 29.6.0 + jest-util: 29.6.1 micromatch: 4.0.5 pirates: 4.0.6 slash: 3.0.0 @@ -2516,19 +2377,19 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 '@types/yargs': 16.0.5 chalk: 4.1.2 dev: true - /@jest/types@29.6.0: - resolution: {integrity: sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg==} + /@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': 18.11.18 + '@types/node': 20.4.1 '@types/yargs': 17.0.24 chalk: 4.1.2 dev: true @@ -2553,8 +2414,8 @@ packages: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - /@jridgewell/source-map@0.3.3: - resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 @@ -2621,7 +2482,7 @@ packages: detect-libc: 2.0.1 https-proxy-agent: 5.0.1 make-dir: 3.1.0 - node-fetch: 2.6.11 + node-fetch: 2.6.12 nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 @@ -2639,7 +2500,7 @@ packages: detect-libc: 2.0.1 https-proxy-agent: 5.0.1 make-dir: 3.1.0 - node-fetch: 2.6.11 + node-fetch: 2.6.12 nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 @@ -2719,7 +2580,7 @@ packages: ext-name: 5.0.0 file-type: 17.1.6 filenamify: 5.1.1 - got: 11.8.5 + got: 11.8.6 os-filter-obj: 2.0.0 dev: true @@ -2776,11 +2637,6 @@ packages: engines: {node: '>= 10'} hasBin: true - /@nicolo-ribaudo/semver-v6@6.3.3: - resolution: {integrity: sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==} - hasBin: true - dev: true - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -3060,10 +2916,6 @@ packages: resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} dev: true - /@sinclair/typebox@0.25.24: - resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==} - dev: true - /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -3110,27 +2962,7 @@ packages: resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} dev: false - /@swc/cli@0.1.62(@swc/core@1.3.62): - resolution: {integrity: sha512-kOFLjKY3XH1DWLfXL1/B5MizeNorHR8wHKEi92S/Zi9Md/AK17KSqR8MgyRJ6C1fhKHvbBCl8wboyKAFXStkYw==} - engines: {node: '>= 12.13'} - hasBin: true - peerDependencies: - '@swc/core': ^1.2.66 - chokidar: ^3.5.1 - peerDependenciesMeta: - chokidar: - optional: true - dependencies: - '@mole-inc/bin-wrapper': 8.0.1 - '@swc/core': 1.3.62 - commander: 7.2.0 - fast-glob: 3.2.12 - semver: 7.5.4 - slash: 3.0.0 - source-map: 0.7.4 - dev: true - - /@swc/cli@0.1.62(@swc/core@1.3.68)(chokidar@3.5.3): + /@swc/cli@0.1.62(@swc/core@1.3.68)(chokidar@3.3.1): resolution: {integrity: sha512-kOFLjKY3XH1DWLfXL1/B5MizeNorHR8wHKEi92S/Zi9Md/AK17KSqR8MgyRJ6C1fhKHvbBCl8wboyKAFXStkYw==} engines: {node: '>= 12.13'} hasBin: true @@ -3143,9 +2975,9 @@ packages: dependencies: '@mole-inc/bin-wrapper': 8.0.1 '@swc/core': 1.3.68 - chokidar: 3.5.3 + chokidar: 3.3.1 commander: 7.2.0 - fast-glob: 3.2.12 + fast-glob: 3.3.0 semver: 7.5.4 slash: 3.0.0 source-map: 0.7.4 @@ -3156,19 +2988,9 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [android] - requiresBuild: true dependencies: '@swc/wasm': 1.2.130 - /@swc/core-darwin-arm64@1.3.62: - resolution: {integrity: sha512-MmGilibITz68LEje6vJlKzc2gUUSgzvB3wGLSjEORikTNeM7P8jXVxE4A8fgZqDeudJUm9HVWrxCV+pHDSwXhA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@swc/core-darwin-arm64@1.3.68: resolution: {integrity: sha512-Z5pNxeuP2NxpOHTzDQkJs0wAPLnTlglZnR3WjObijwvdwT/kw1Y5EPDKM/BVSIeG40SPMkDLBbI0aj0qyXzrBA==} engines: {node: '>=10'} @@ -3177,15 +2999,6 @@ packages: requiresBuild: true optional: true - /@swc/core-darwin-x64@1.3.62: - resolution: {integrity: sha512-Xl93MMB3sCWVlYWuQIB+v6EQgzoiuQYK5tNt9lsHoIEVu2zLdkQjae+5FUHZb1VYqCXIiWcULFfVz0R4Sjb7JQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@swc/core-darwin-x64@1.3.68: resolution: {integrity: sha512-ZHl42g6yXhfX4PzAQ0BNvBXpt/OcbAHfubWRN6eXELK3fiNnxL7QBW1if7iizlq6iA+Mj1pwHyyUit1pz0+fgA==} engines: {node: '>=10'} @@ -3194,15 +3007,6 @@ packages: requiresBuild: true optional: true - /@swc/core-linux-arm-gnueabihf@1.3.62: - resolution: {integrity: sha512-nJsp6O7kCtAjTTMcIjVB0g5y1JNiYAa5q630eiwrnaHUusEFoANDdORI3Z9vXeikMkng+6yIv9/V8Rb093xLjQ==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@swc/core-linux-arm-gnueabihf@1.3.68: resolution: {integrity: sha512-Mk8f6KCOQ2CNAR4PtWajIjS6XKSSR7ZYDOCf1GXRxhS3qEyQH7V8elWvqWYqHcT4foO60NUmxA/NOM/dQrdO1A==} engines: {node: '>=10'} @@ -3211,15 +3015,6 @@ packages: requiresBuild: true optional: true - /@swc/core-linux-arm64-gnu@1.3.62: - resolution: {integrity: sha512-XGsV93vpUAopDt5y6vPwbK1Nc/MlL55L77bAZUPIiosWD1cWWPHNtNSpriE6+I+JiMHe0pqtfS/SSTk6ZkFQVw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@swc/core-linux-arm64-gnu@1.3.68: resolution: {integrity: sha512-RhBllggh9t9sIxaRgRcGrVaS7fDk6KsIqR6b9+dwU5OyDr4ZyHWw1ZaH/1/HAebuXYhNBjoNUiRtca6lKRIPgQ==} engines: {node: '>=10'} @@ -3228,15 +3023,6 @@ packages: requiresBuild: true optional: true - /@swc/core-linux-arm64-musl@1.3.62: - resolution: {integrity: sha512-ESUmJjSlTTkoBy9dMG49opcNn8BmviqStMhwyeD1G8XRnmRVCZZgoBOKdvCXmJhw8bQXDhZumeaTUB+OFUKVXg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@swc/core-linux-arm64-musl@1.3.68: resolution: {integrity: sha512-8K3zjU+tFgn6yGDEeD343gkKaHU9dhz77NiVkI1VzwRaT/Ag5pwl5eMQ1yStm8koNFzn3zq6rGjHfI5g2yI5Wg==} engines: {node: '>=10'} @@ -3245,15 +3031,6 @@ packages: requiresBuild: true optional: true - /@swc/core-linux-x64-gnu@1.3.62: - resolution: {integrity: sha512-wnHJkt3ZBrax3SFnUHDcncG6mrSg9ZZjMhQV9Mc3JL1x1s1Gy9rGZCoBNnV/BUZWTemxIBcQbANRSDut/WO+9A==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@swc/core-linux-x64-gnu@1.3.68: resolution: {integrity: sha512-4xAnvsBOyeTL0AB8GWlRKDM/hsysJ5jr5qvdKKI3rZfJgnnxl/xSX6TJKPsJ8gygfUJ3BmfCbmUmEyeDZ3YPvA==} engines: {node: '>=10'} @@ -3262,15 +3039,6 @@ packages: requiresBuild: true optional: true - /@swc/core-linux-x64-musl@1.3.62: - resolution: {integrity: sha512-9oRbuTC/VshB66Rgwi3pTq3sPxSTIb8k9L1vJjES+dDMKa29DAjPtWCXG/pyZ00ufpFZgkGEuAHH5uqUcr1JQg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@swc/core-linux-x64-musl@1.3.68: resolution: {integrity: sha512-RCpaBo1fcpy1EFdjF+I7N4lfzOaHXVV0iMw/ABM+0PD6tp3V/9pxsguaZyeAHyEiUlDA6PZ4TfXv5zfnXEgW4Q==} engines: {node: '>=10'} @@ -3279,15 +3047,6 @@ packages: requiresBuild: true optional: true - /@swc/core-win32-arm64-msvc@1.3.62: - resolution: {integrity: sha512-zv14vlF2VRrxS061XkfzGjCYnOrEo5glKJjLK5PwUKysIoVrx/L8nAbFxjkX5cObdlyoqo+ekelyBPAO+4bS0w==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@swc/core-win32-arm64-msvc@1.3.68: resolution: {integrity: sha512-v2WZvXrSslYEpY1nqpItyamL4DyaJinmOkXvM8Bc1LLKU5rGuvmBdjUYg/5Y+o0AUynuiWubpgHNOkBWiCvfqw==} engines: {node: '>=10'} @@ -3296,15 +3055,6 @@ packages: requiresBuild: true optional: true - /@swc/core-win32-ia32-msvc@1.3.62: - resolution: {integrity: sha512-8MC/PZQSsOP2iA/81tAfNRqMWyEqTS/8zKUI67vPuLvpx6NAjRn3E9qBv7iFqH79iqZNzqSMo3awnLrKZyFbcw==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@swc/core-win32-ia32-msvc@1.3.68: resolution: {integrity: sha512-HH5NJrIdzkJs+1xxprie0qSCMBeL9yeEhcC1yZTzYv8bwmabOUSdtKIqS55iYP/2hLWn9CTbvKPmLOIhCopW3Q==} engines: {node: '>=10'} @@ -3313,15 +3063,6 @@ packages: requiresBuild: true optional: true - /@swc/core-win32-x64-msvc@1.3.62: - resolution: {integrity: sha512-GJSmUJ95HKHZXAxiuPUmrcm/S3ivQvEzXhOZaIqYBIwUsm02vFZkClsV7eIKzWjso1t0+I/8MjrnUNaSWqh1rQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@swc/core-win32-x64-msvc@1.3.68: resolution: {integrity: sha512-9HZVtLQUgK8r/yXQdwe0VBexbIcrY6+fBROhs7AAPWdewpaUeLkwQEJk6TbYr9CQuHw26FFGg6SjwAiqXF+kgQ==} engines: {node: '>=10'} @@ -3330,28 +3071,6 @@ packages: requiresBuild: true optional: true - /@swc/core@1.3.62: - resolution: {integrity: sha512-J58hWY+/G8vOr4J6ZH9hLg0lMSijZtqIIf4HofZezGog/pVX6sJyBJ40dZ1ploFkDIlWTWvJyqtpesBKS73gkQ==} - engines: {node: '>=10'} - requiresBuild: true - peerDependencies: - '@swc/helpers': ^0.5.0 - peerDependenciesMeta: - '@swc/helpers': - optional: true - optionalDependencies: - '@swc/core-darwin-arm64': 1.3.62 - '@swc/core-darwin-x64': 1.3.62 - '@swc/core-linux-arm-gnueabihf': 1.3.62 - '@swc/core-linux-arm64-gnu': 1.3.62 - '@swc/core-linux-arm64-musl': 1.3.62 - '@swc/core-linux-x64-gnu': 1.3.62 - '@swc/core-linux-x64-musl': 1.3.62 - '@swc/core-win32-arm64-msvc': 1.3.62 - '@swc/core-win32-ia32-msvc': 1.3.62 - '@swc/core-win32-x64-msvc': 1.3.62 - dev: true - /@swc/core@1.3.68: resolution: {integrity: sha512-njGQuJO+Wy06dEayt70cf0c/KI3HGjm4iW9LLViVLBuYNzJ4SSdNfzejludzufu6im+dsDJ0i3QjgWhAIcVHMQ==} engines: {node: '>=10'} @@ -3375,7 +3094,6 @@ packages: /@swc/wasm@1.2.130: resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==} - requiresBuild: true /@syuilo/aiscript@0.11.1: resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==} @@ -3576,7 +3294,7 @@ packages: '@tensorflow/tfjs-layers': 3.21.0(@tensorflow/tfjs-core@3.21.0) argparse: 1.0.10 chalk: 4.1.2 - core-js: 3.31.0 + core-js: 3.31.1 regenerator-runtime: 0.13.11 yargs: 16.2.0 transitivePeerDependencies: @@ -3596,7 +3314,7 @@ packages: '@tensorflow/tfjs-layers': 4.2.0(@tensorflow/tfjs-core@4.2.0) argparse: 1.0.10 chalk: 4.1.2 - core-js: 3.31.0 + core-js: 3.31.1 regenerator-runtime: 0.13.11 yargs: 16.2.0 transitivePeerDependencies: @@ -3636,12 +3354,12 @@ packages: /@types/accepts@1.3.5: resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/adm-zip@0.5.0: resolution: {integrity: sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/argparse@1.0.38: @@ -3655,7 +3373,7 @@ packages: /@types/babel__core@7.20.1: resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@babel/types': 7.22.5 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 @@ -3671,7 +3389,7 @@ packages: /@types/babel__template@7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@babel/types': 7.22.5 dev: true @@ -3689,14 +3407,14 @@ packages: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/cacheable-request@6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 18.11.18 + '@types/node': 20.4.1 '@types/responselike': 1.0.0 /@types/cbor@6.0.0: @@ -3709,14 +3427,14 @@ packages: /@types/co-body@6.1.0: resolution: {integrity: sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 '@types/qs': 6.9.7 dev: false /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/content-disposition@0.5.5: resolution: {integrity: sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==} @@ -3727,7 +3445,7 @@ packages: '@types/connect': 3.4.35 '@types/express': 4.17.17 '@types/keygrip': 1.0.2 - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/core-js@2.5.0: resolution: {integrity: sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==} @@ -3777,7 +3495,7 @@ packages: /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -3793,7 +3511,7 @@ packages: /@types/fluent-ffmpeg@2.1.21: resolution: {integrity: sha512-+n3dy/Tegt6n+YwGZUiGq6i8Jrnt8+MoyPiW1L6J5EWUl7GSt18a/VyReecfCsvTTNBXNMIKOMHDstiQM8nJLA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/form-data@2.5.0: @@ -3806,7 +3524,7 @@ packages: /@types/formidable@2.0.6: resolution: {integrity: sha512-L4HcrA05IgQyNYJj6kItuIkXrInJvsXTPC5B1i64FggWKKqSL+4hgt7asiSNva75AoLQjq29oPxFfU4GAQ6Z2w==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: false /@types/glob-stream@8.0.0: @@ -3827,7 +3545,7 @@ packages: /@types/graceful-fs@4.1.6: resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true /@types/gulp-rename@2.0.2: @@ -3880,8 +3598,8 @@ packages: /@types/jest@29.4.0: resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==} dependencies: - expect: 29.6.0 - pretty-format: 29.5.0 + expect: 29.6.1 + pretty-format: 29.6.1 dev: true /@types/js-yaml@4.0.5: @@ -3891,7 +3609,7 @@ packages: /@types/jsdom@21.1.1: resolution: {integrity: sha512-cZFuoVLtzKP3gmq9eNosUL1R50U+USkbLtUQ1bYVgl/lKp0FZM7Cq4aIHAL8oIvQ17uSHi7jXPtfDOdjPwBE7A==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 '@types/tough-cookie': 4.0.2 parse5: 7.1.2 dev: true @@ -3922,7 +3640,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/koa-bodyparser@4.3.10: resolution: {integrity: sha512-6ae05pjhmrmGhUR8GYD5qr5p9LTEMEGfGXCsK8VaSL+totwigm8+H/7MHW7K4854CMeuwRAubT8qcc/EagaeIA==} @@ -4038,7 +3756,7 @@ packages: '@types/http-errors': 2.0.1 '@types/keygrip': 1.0.2 '@types/koa-compose': 3.2.5 - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/koa__cors@3.3.0: resolution: {integrity: sha512-FUN8YxcBakIs+walVe3+HcNP+Bxd0SB8BJHBWkglZ5C1XQWljlKcEFDG/dPiCIqwVCUbc5X0nYDlH62uEhdHMA==} @@ -4087,13 +3805,13 @@ packages: /@types/needle@3.2.0: resolution: {integrity: sha512-6XzvzEyJ2ozFNfPajFmqH9JOt0Hp+9TawaYpJT59iIP/zR0U37cfWCRwosyIeEBBZBi021Osq4jGAD3AOju5fg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 form-data: 3.0.1 dev: false @@ -4116,12 +3834,11 @@ packages: /@types/node@20.4.1: resolution: {integrity: sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==} - dev: true /@types/nodemailer@6.4.8: resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/normalize-package-data@2.4.1: @@ -4131,7 +3848,7 @@ packages: /@types/oauth@0.9.1: resolution: {integrity: sha512-a1iY62/a3yhZ7qH7cNUsxoI3U/0Fe9+RnuFrpTKr+0WVOzbKlSLojShCKe20aOD1Sppv+i8Zlq0pLDuTJnwS4A==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/object-assign-deep@0.4.0: resolution: {integrity: sha512-3D0F3rHRNDc8cQSXNzwF1jBrJi28Mdrhc10ZLlqbJWDPYRWTTWB9Tc8JoKrgBvLKioXoPoHT6Uzf3s2F7akCUg==} @@ -4161,7 +3878,7 @@ packages: resolution: {integrity: sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew==} dependencies: '@types/needle': 3.2.0 - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/pug@2.0.6: @@ -4175,7 +3892,7 @@ packages: /@types/qrcode@1.5.1: resolution: {integrity: sha512-HpSN675K0PmxIDRpjMI3Mc2GiKo3dNu+X/F5SoItiaDS1lVfgC6Wac1c5lQDfKWbTJUSHWiHKzpJpBZG7k9gaA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/qs@6.9.7: @@ -4206,7 +3923,7 @@ packages: /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/sanitize-html@2.9.0: resolution: {integrity: sha512-4fP/kEcKNj2u39IzrxWYuf/FnCCwwQCpif6wwY6ROUS1EPRIfWJjGkY3HIowY1EX/VbX5e86yq8AAE7UPMgATg==} @@ -4230,14 +3947,14 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/serve-static@1.15.2: resolution: {integrity: sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==} dependencies: '@types/http-errors': 2.0.1 '@types/mime': 3.0.1 - '@types/node': 18.11.18 + '@types/node': 20.4.1 /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} @@ -4293,10 +4010,6 @@ packages: resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} dev: true - /@types/uuid@9.0.0: - resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} - dev: true - /@types/uuid@9.0.2: resolution: {integrity: sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==} dev: true @@ -4319,7 +4032,7 @@ packages: /@types/web-push@3.3.2: resolution: {integrity: sha512-JxWGVL/m7mWTIg4mRYO+A6s0jPmBkr4iJr39DqJpRJAc+jrPiEe1/asmkwerzRon8ZZDxaZJpsxpv0Z18Wo9gw==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true /@types/webgl-ext@0.0.30: @@ -4333,20 +4046,13 @@ packages: /@types/websocket@1.0.5: resolution: {integrity: sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 20.4.1 dev: true - /@types/ws@8.5.4: - resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} - dependencies: - '@types/node': 18.11.18 - dev: false - /@types/ws@8.5.5: resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} dependencies: - '@types/node': 18.11.18 - dev: true + '@types/node': 20.4.1 /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} @@ -4372,7 +4078,7 @@ packages: dev: true optional: true - /@typescript-eslint/eslint-plugin@5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.42.0)(typescript@4.9.4): + /@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: @@ -4383,12 +4089,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@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.42.0)(typescript@4.9.4) - '@typescript-eslint/utils': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@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.42.0 + eslint: 8.44.0 ignore: 5.2.4 natural-compare-lite: 1.4.0 regexpp: 3.2.0 @@ -4399,7 +4105,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@5.49.0(eslint@8.42.0)(typescript@4.9.4): + /@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: @@ -4413,7 +4119,7 @@ packages: '@typescript-eslint/types': 5.49.0 '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) debug: 4.3.4(supports-color@8.1.1) - eslint: 8.42.0 + eslint: 8.44.0 typescript: 4.9.4 transitivePeerDependencies: - supports-color @@ -4427,7 +4133,7 @@ packages: '@typescript-eslint/visitor-keys': 5.49.0 dev: true - /@typescript-eslint/type-utils@5.49.0(eslint@8.42.0)(typescript@4.9.4): + /@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: @@ -4438,9 +4144,9 @@ packages: optional: true dependencies: '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) - '@typescript-eslint/utils': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@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.42.0 + eslint: 8.44.0 tsutils: 3.21.0(typescript@4.9.4) typescript: 4.9.4 transitivePeerDependencies: @@ -4473,7 +4179,7 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@5.49.0(eslint@8.42.0)(typescript@4.9.4): + /@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: @@ -4484,9 +4190,9 @@ packages: '@typescript-eslint/scope-manager': 5.49.0 '@typescript-eslint/types': 5.49.0 '@typescript-eslint/typescript-estree': 5.49.0(typescript@4.9.4) - eslint: 8.42.0 + eslint: 8.44.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0(eslint@8.42.0) + eslint-utils: 3.0.0(eslint@8.44.0) semver: 7.5.4 transitivePeerDependencies: - supports-color @@ -4515,7 +4221,7 @@ packages: /@vue/compiler-core@3.3.4: resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@vue/shared': 3.3.4 estree-walker: 2.0.2 source-map-js: 1.0.2 @@ -4531,7 +4237,7 @@ packages: /@vue/compiler-sfc@2.7.14: resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 postcss: 8.4.25 source-map: 0.6.1 dev: true @@ -4539,15 +4245,15 @@ packages: /@vue/compiler-sfc@3.3.4: resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@vue/compiler-core': 3.3.4 '@vue/compiler-dom': 3.3.4 '@vue/compiler-ssr': 3.3.4 '@vue/reactivity-transform': 3.3.4 '@vue/shared': 3.3.4 estree-walker: 2.0.2 - magic-string: 0.30.0 - postcss: 8.4.24 + magic-string: 0.30.1 + postcss: 8.4.25 source-map-js: 1.0.2 dev: true @@ -4561,11 +4267,11 @@ packages: /@vue/reactivity-transform@3.3.4: resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 estree-walker: 2.0.2 - magic-string: 0.30.0 + magic-string: 0.30.1 dev: true /@vue/reactivity@3.3.4: @@ -4717,29 +4423,29 @@ packages: resolution: {integrity: sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow==} dev: false - /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.3)(webpack@5.85.1): + /@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.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.85.1) + webpack: 5.88.1(@swc/core@1.3.68)(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.85.1): + /@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.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.85.1) + webpack: 5.88.1(@swc/core@1.3.68)(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.85.1): + /@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: @@ -4750,8 +4456,8 @@ packages: webpack-dev-server: optional: true dependencies: - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) - webpack-cli: 5.1.3(webpack@5.85.1) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + webpack-cli: 5.1.3(webpack@5.88.1) dev: true /@xtuc/ieee754@1.2.0: @@ -4793,7 +4499,7 @@ packages: /acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: - acorn: 8.9.0 + acorn: 8.10.0 acorn-walk: 8.2.0 dev: false @@ -4805,14 +4511,6 @@ packages: acorn: 8.10.0 dev: true - /acorn-import-assertions@1.9.0(acorn@8.9.0): - resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.9.0 - dev: true - /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -4839,11 +4537,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - /acorn@8.9.0: - resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} - engines: {node: '>=0.4.0'} - hasBin: true - /adm-zip@0.5.10: resolution: {integrity: sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==} engines: {node: '>=6.0'} @@ -5176,7 +4869,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 get-intrinsic: 1.2.1 is-string: 1.0.7 dev: true @@ -5226,7 +4919,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 es-shim-unscopables: 1.0.0 dev: true @@ -5236,7 +4929,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 es-shim-unscopables: 1.0.0 dev: true @@ -5341,7 +5034,7 @@ packages: resolution: {integrity: sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==} dependencies: browserslist: 1.7.7 - caniuse-db: 1.0.30001509 + caniuse-db: 1.0.30001515 normalize-range: 0.1.2 num2fraction: 1.2.2 postcss: 5.2.18 @@ -5368,7 +5061,7 @@ packages: '@ava/typescript': optional: true dependencies: - acorn: 8.9.0 + acorn: 8.10.0 acorn-walk: 8.2.0 ansi-styles: 6.2.1 arrgv: 1.0.2 @@ -5390,7 +5083,7 @@ packages: del: 7.0.0 emittery: 1.0.1 figures: 5.0.0 - globby: 13.2.0 + globby: 13.2.2 ignore-by-default: 2.1.0 indent-string: 5.0.0 is-error: 2.2.2 @@ -5487,8 +5180,8 @@ packages: eslint: '>= 4.12.1' dependencies: '@babel/code-frame': 7.22.5 - '@babel/parser': 7.22.5 - '@babel/traverse': 7.22.5 + '@babel/parser': 7.22.7 + '@babel/traverse': 7.22.8 '@babel/types': 7.22.5 eslint: 8.44.0 eslint-visitor-keys: 1.3.0 @@ -5497,18 +5190,18 @@ packages: - supports-color dev: false - /babel-jest@27.5.1(@babel/core@7.22.5): + /babel-jest@27.5.1(@babel/core@7.22.9): resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.8.0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 '@types/babel__core': 7.20.1 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 27.5.1(@babel/core@7.22.5) + babel-preset-jest: 27.5.1(@babel/core@7.22.9) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -5516,17 +5209,17 @@ packages: - supports-color dev: true - /babel-jest@29.6.0(@babel/core@7.22.5): - resolution: {integrity: sha512-Jj8Bq2yKsk11XLk06Nm8SdvYkAcecH+GuhxB8DnK5SncjHnJ88TQjSnGgE7jpajpnSvz9DZ6X8hXrDkD/6/TPQ==} + /babel-jest@29.6.1(@babel/core@7.22.9): + resolution: {integrity: sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.8.0 dependencies: - '@babel/core': 7.22.5 - '@jest/transform': 29.6.0 + '@babel/core': 7.22.9 + '@jest/transform': 29.6.1 '@types/babel__core': 7.20.1 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.5.0(@babel/core@7.22.5) + babel-preset-jest: 29.5.0(@babel/core@7.22.9) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -5567,46 +5260,46 @@ packages: '@types/babel__traverse': 7.20.1 dev: true - /babel-preset-current-node-syntax@1.0.1(@babel/core@7.22.5): + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.22.9): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.5) + '@babel/core': 7.22.9 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) dev: true - /babel-preset-jest@27.5.1(@babel/core@7.22.5): + /babel-preset-jest@27.5.1(@babel/core@7.22.9): resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 babel-plugin-jest-hoist: 27.5.1 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.9) dev: true - /babel-preset-jest@29.5.0(@babel/core@7.22.5): + /babel-preset-jest@29.5.0(@babel/core@7.22.9): resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 babel-plugin-jest-hoist: 29.5.0 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.9) dev: true /babel-walk@3.0.0-canary-5: @@ -5792,8 +5485,8 @@ packages: deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. hasBin: true dependencies: - caniuse-db: 1.0.30001509 - electron-to-chromium: 1.4.442 + caniuse-db: 1.0.30001515 + electron-to-chromium: 1.4.459 dev: true /browserslist@4.21.9: @@ -5801,8 +5494,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001514 - electron-to-chromium: 1.4.455 + caniuse-lite: 1.0.30001515 + electron-to-chromium: 1.4.459 node-releases: 2.0.13 update-browserslist-db: 1.0.11(browserslist@4.21.9) @@ -6018,17 +5711,17 @@ packages: resolution: {integrity: sha512-SBTl70K0PkDUIebbkXrxWqZlHNs0wRgRD6QZ8guctShjbh63gEPfF+Wj0Yw+75f5Y8tSzqAI/NcisYv/cCah2Q==} dependencies: browserslist: 1.7.7 - caniuse-db: 1.0.30001509 + caniuse-db: 1.0.30001515 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: true - /caniuse-db@1.0.30001509: - resolution: {integrity: sha512-Gf3pFp97loixG5w83NVb09DMI+WzkVXLn4H2abxv7DXxHUyKYbZc5qpEqAQy/mDFO6bAnNQh4hZ8lLeGlPTZQg==} + /caniuse-db@1.0.30001515: + resolution: {integrity: sha512-xm/Fbjo09QRliBdFiaEBaD29QgEHxU6bbTGLSNTGvJ1t1XHcHp/GOVyjJj/uYsmy2R0VjKNXrwEO46WYFMfacA==} dev: true - /caniuse-lite@1.0.30001514: - resolution: {integrity: sha512-ENcIpYBmwAAOm/V2cXgM7rZUrKKaqisZl4ZAI520FIkqGXUxJjmaIssbRW5HVVR5tyV6ygTLIm15aU8LUmQSaQ==} + /caniuse-lite@1.0.30001515: + resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} /canonicalize@1.0.8: resolution: {integrity: sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==} @@ -6169,6 +5862,20 @@ packages: lodash.some: 4.6.0 dev: false + /chokidar@3.3.1: + resolution: {integrity: sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.3.0 + optionalDependencies: + fsevents: 2.1.3 + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -6182,6 +5889,7 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 + dev: true /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -6415,8 +6123,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /collect-v8-coverage@1.0.1: - resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: true /collection-map@1.0.0: @@ -6790,7 +6498,7 @@ packages: /constantinople@4.0.1: resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@babel/types': 7.22.5 /content-disposition@0.5.4: @@ -6840,15 +6548,9 @@ packages: resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} dev: false - /core-js@3.31.0: - resolution: {integrity: sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==} - requiresBuild: true - dev: false - /core-js@3.31.1: resolution: {integrity: sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ==} requiresBuild: true - dev: true /core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -6895,10 +6597,10 @@ packages: cross-spawn: 7.0.3 dev: true - /cross-fetch@3.1.6: - resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==} + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} dependencies: - node-fetch: 2.6.11 + node-fetch: 2.6.12 transitivePeerDependencies: - encoding @@ -7045,7 +6747,7 @@ packages: cli-table3: 0.6.3 commander: 5.1.0 common-tags: 1.8.2 - dayjs: 1.11.8 + dayjs: 1.11.9 debug: 4.3.4(supports-color@8.1.1) enquirer: 2.3.6 eventemitter2: 6.4.7 @@ -7115,7 +6817,7 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} dependencies: - '@babel/runtime': 7.22.5 + '@babel/runtime': 7.22.6 /date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} @@ -7124,8 +6826,13 @@ packages: time-zone: 1.0.0 dev: true - /dayjs@1.11.8: - resolution: {integrity: sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ==} + /dayjs@1.11.7: + resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} + dev: false + + /dayjs@1.11.9: + resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} + dev: true /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -7174,6 +6881,7 @@ packages: /debuglog@1.0.1: resolution: {integrity: sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. dev: false /decamelize-keys@1.1.1: @@ -7292,7 +7000,7 @@ packages: resolution: {integrity: sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q==} engines: {node: '>=14.16'} dependencies: - globby: 13.2.0 + globby: 13.2.2 graceful-fs: 4.2.11 is-glob: 4.0.3 is-path-cwd: 3.0.0 @@ -7529,12 +7237,8 @@ packages: dependencies: jake: 10.8.7 - /electron-to-chromium@1.4.442: - resolution: {integrity: sha512-RkrZF//Ya+0aJq2NM3OdisNh5ZodZq1rdXOS96G8DdDgpDKqKE81yTbbQ3F/4CKm1JBPsGu1Lp/akkna2xO06Q==} - dev: true - - /electron-to-chromium@1.4.455: - resolution: {integrity: sha512-8tgdX0Odl24LtmLwxotpJCVjIndN559AvaOtd67u+2mo+IDsgsTF580NB+uuDCqsHw8yFg53l5+imFV9Fw3cbA==} + /electron-to-chromium@1.4.459: + resolution: {integrity: sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg==} /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -7632,8 +7336,8 @@ packages: is-arrayish: 0.2.1 dev: true - /es-abstract@1.21.2: - resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==} + /es-abstract@1.21.3: + resolution: {integrity: sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 @@ -7667,9 +7371,10 @@ packages: string.prototype.trim: 1.2.7 string.prototype.trimend: 1.0.6 string.prototype.trimstart: 1.0.6 + typed-array-byte-offset: 1.0.0 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 + which-typed-array: 1.1.10 dev: true /es-module-lexer@1.3.0: @@ -7743,34 +7448,34 @@ packages: es6-symbol: 3.1.3 dev: true - /esbuild@0.18.11: - resolution: {integrity: sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==} + /esbuild@0.18.12: + resolution: {integrity: sha512-XuOVLDdtsDslXStStduT41op21Ytmf4/BDS46aa3xPJ7X5h2eMWBF1oAe3QjUH3bDksocNXgzGUZ7XHIBya6Tg==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.18.11 - '@esbuild/android-arm64': 0.18.11 - '@esbuild/android-x64': 0.18.11 - '@esbuild/darwin-arm64': 0.18.11 - '@esbuild/darwin-x64': 0.18.11 - '@esbuild/freebsd-arm64': 0.18.11 - '@esbuild/freebsd-x64': 0.18.11 - '@esbuild/linux-arm': 0.18.11 - '@esbuild/linux-arm64': 0.18.11 - '@esbuild/linux-ia32': 0.18.11 - '@esbuild/linux-loong64': 0.18.11 - '@esbuild/linux-mips64el': 0.18.11 - '@esbuild/linux-ppc64': 0.18.11 - '@esbuild/linux-riscv64': 0.18.11 - '@esbuild/linux-s390x': 0.18.11 - '@esbuild/linux-x64': 0.18.11 - '@esbuild/netbsd-x64': 0.18.11 - '@esbuild/openbsd-x64': 0.18.11 - '@esbuild/sunos-x64': 0.18.11 - '@esbuild/win32-arm64': 0.18.11 - '@esbuild/win32-ia32': 0.18.11 - '@esbuild/win32-x64': 0.18.11 + '@esbuild/android-arm': 0.18.12 + '@esbuild/android-arm64': 0.18.12 + '@esbuild/android-x64': 0.18.12 + '@esbuild/darwin-arm64': 0.18.12 + '@esbuild/darwin-x64': 0.18.12 + '@esbuild/freebsd-arm64': 0.18.12 + '@esbuild/freebsd-x64': 0.18.12 + '@esbuild/linux-arm': 0.18.12 + '@esbuild/linux-arm64': 0.18.12 + '@esbuild/linux-ia32': 0.18.12 + '@esbuild/linux-loong64': 0.18.12 + '@esbuild/linux-mips64el': 0.18.12 + '@esbuild/linux-ppc64': 0.18.12 + '@esbuild/linux-riscv64': 0.18.12 + '@esbuild/linux-s390x': 0.18.12 + '@esbuild/linux-x64': 0.18.12 + '@esbuild/netbsd-x64': 0.18.12 + '@esbuild/openbsd-x64': 0.18.12 + '@esbuild/sunos-x64': 0.18.12 + '@esbuild/win32-arm64': 0.18.12 + '@esbuild/win32-ia32': 0.18.12 + '@esbuild/win32-x64': 0.18.12 dev: true /escalade@3.1.1: @@ -7802,28 +7507,27 @@ packages: engines: {node: '>=12'} dev: true - /escodegen@2.0.0: - resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} hasBin: true dependencies: esprima: 4.0.1 estraverse: 5.3.0 esutils: 2.0.3 - optionator: 0.8.3 optionalDependencies: source-map: 0.6.1 - /eslint-config-prettier@8.6.0(eslint@8.42.0): + /eslint-config-prettier@8.6.0(eslint@8.44.0): resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.42.0 + eslint: 8.44.0 dev: true - /eslint-config-standard@16.0.3(eslint-plugin-import@2.27.5)(eslint-plugin-node@11.0.0)(eslint-plugin-promise@6.1.1)(eslint@8.42.0): + /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 @@ -7831,10 +7535,10 @@ packages: eslint-plugin-node: ^11.1.0 eslint-plugin-promise: ^4.2.1 || ^5.0.0 dependencies: - eslint: 8.42.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.42.0) - eslint-plugin-node: 11.0.0(eslint@8.42.0) - eslint-plugin-promise: 6.1.1(eslint@8.42.0) + 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: @@ -7861,7 +7565,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.44.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -7882,26 +7586,26 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@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.42.0 + eslint: 8.44.0 eslint-import-resolver-node: 0.3.7 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-es@3.0.1(eslint@8.42.0): + /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.42.0 + eslint: 8.44.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.42.0): + /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: @@ -7911,15 +7615,15 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.49.0(eslint@8.42.0)(typescript@4.9.4) + '@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.42.0 + eslint: 8.44.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.42.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.49.0)(eslint-import-resolver-node@0.3.7)(eslint@8.44.0) has: 1.0.3 is-core-module: 2.12.1 is-glob: 4.0.3 @@ -7934,14 +7638,14 @@ packages: - supports-color dev: true - /eslint-plugin-node@11.0.0(eslint@8.42.0): + /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.42.0 - eslint-plugin-es: 3.0.1(eslint@8.42.0) + 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 @@ -7949,7 +7653,7 @@ packages: semver: 6.3.1 dev: true - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.42.0)(prettier@2.8.8): + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@2.8.3): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -7960,28 +7664,28 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.42.0 - eslint-config-prettier: 8.6.0(eslint@8.42.0) - prettier: 2.8.8 + eslint: 8.44.0 + eslint-config-prettier: 8.6.0(eslint@8.44.0) + prettier: 2.8.3 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-promise@6.1.1(eslint@8.42.0): + /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.42.0 + eslint: 8.44.0 dev: true - /eslint-plugin-standard@5.0.0(eslint@8.42.0): + /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.42.0 + eslint: 8.44.0 dev: true /eslint-rule-docs@1.1.235: @@ -8010,13 +7714,13 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils@3.0.0(eslint@8.42.0): + /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.42.0 + eslint: 8.44.0 eslint-visitor-keys: 2.1.0 dev: true @@ -8033,54 +7737,6 @@ packages: resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint@8.42.0: - resolution: {integrity: sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.42.0) - '@eslint-community/regexpp': 4.5.1 - '@eslint/eslintrc': 2.0.3 - '@eslint/js': 8.42.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.0 - eslint-visitor-keys: 3.4.1 - espree: 9.5.2 - 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.44.0: resolution: {integrity: sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8128,15 +7784,6 @@ packages: transitivePeerDependencies: - supports-color - /espree@9.5.2: - resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) - eslint-visitor-keys: 3.4.1 - dev: true - /espree@9.6.0: resolution: {integrity: sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8340,16 +7987,16 @@ packages: jest-message-util: 27.5.1 dev: true - /expect@29.6.0: - resolution: {integrity: sha512-AV+HaBtnDJ2YEUhPPo25HyUHBLaetM+y/Dq6pEC8VPQyt1dK+k8MfGkMy46djy2bddcqESc1kl4/K1uLWSfk9g==} + /expect@29.6.1: + resolution: {integrity: sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/expect-utils': 29.6.0 - '@types/node': 18.11.18 + '@jest/expect-utils': 29.6.1 + '@types/node': 20.4.1 jest-get-type: 29.4.3 - jest-matcher-utils: 29.6.0 - jest-message-util: 29.6.0 - jest-util: 29.6.0 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-util: 29.6.1 dev: true /exponential-backoff@3.1.1: @@ -8448,17 +8095,6 @@ packages: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} dev: true - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - /fast-glob@3.3.0: resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} engines: {node: '>=8.6.0'} @@ -8667,9 +8303,9 @@ packages: /fix-esm@1.0.1: resolution: {integrity: sha512-EZtb7wPXZS54GaGxaWxMlhd1DUDCnAg5srlYdu/1ZVeW+7wwR3Tp59nu52dXByFs3MBRq+SByx1wDOJpRvLEXw==} dependencies: - '@babel/core': 7.22.5 - '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.5) - '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.5) + '@babel/core': 7.22.9 + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.9) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) transitivePeerDependencies: - supports-color dev: false @@ -8901,11 +8537,20 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + /fsevents@2.1.3: + resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + deprecated: '"Please update to latest v2.3 or v2.2"' + requiresBuild: true + optional: true + /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true + dev: true optional: true /fulcon@1.0.2: @@ -8922,7 +8567,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 functions-have-names: 1.2.3 dev: true @@ -9219,12 +8864,12 @@ packages: slash: 3.0.0 dev: true - /globby@13.2.0: - resolution: {integrity: sha512-jWsQfayf13NvqKUIL3Ta+CIqMnvlaIDFveWE/dpOZ9+3AMEJozsxDvKA02zync9UuvOM8rOXzsD5GqKP4OnWPQ==} + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.0 ignore: 5.2.4 merge2: 1.4.1 slash: 4.0.0 @@ -9262,6 +8907,24 @@ packages: lowercase-keys: 2.0.0 p-cancelable: 2.1.1 responselike: 2.0.1 + dev: false + + /got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.0 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + dev: true /got@12.5.3: resolution: {integrity: sha512-8wKnb9MGU8IPGRIo+/ukTy9XLJBwDiCpIf5TVzQ9Cpol50eMTpBq2GAuDsuDIz7hTYmZgMgC1e9ydr6kSDWs3w==} @@ -9348,7 +9011,7 @@ packages: engines: {node: '>=10'} dependencies: plugin-error: 1.0.1 - terser: 5.18.2 + terser: 5.19.0 through2: 4.0.2 vinyl-sourcemaps-apply: 0.2.1 dev: true @@ -9758,8 +9421,8 @@ packages: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} - /immutable@4.3.0: - resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==} + /immutable@4.3.1: + resolution: {integrity: sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==} dev: true /import-fresh@3.3.0: @@ -10372,8 +10035,8 @@ packages: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.22.5 - '@babel/parser': 7.22.5 + '@babel/core': 7.22.9 + '@babel/parser': 7.22.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -10460,7 +10123,7 @@ packages: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -10480,27 +10143,27 @@ packages: - supports-color dev: true - /jest-circus@29.6.0: - resolution: {integrity: sha512-LtG45qEKhse2Ws5zNR4DnZATReLGQXzBZGZnJ0DU37p6d4wDhu41vvczCQ3Ou+llR6CRYDBshsubV7H4jZvIkw==} + /jest-circus@29.6.1: + resolution: {integrity: sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.6.0 - '@jest/expect': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/environment': 29.6.1 + '@jest/expect': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 is-generator-fn: 2.1.0 - jest-each: 29.6.0 - jest-matcher-utils: 29.6.0 - jest-message-util: 29.6.0 - jest-runtime: 29.6.0 - jest-snapshot: 29.6.0 - jest-util: 29.6.0 + jest-each: 29.6.1 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-runtime: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 p-limit: 3.1.0 - pretty-format: 29.6.0 + pretty-format: 29.6.1 pure-rand: 6.0.2 slash: 3.0.0 stack-utils: 2.0.6 @@ -10538,8 +10201,8 @@ packages: - utf-8-validate dev: true - /jest-cli@29.6.0(@types/node@18.11.18): - resolution: {integrity: sha512-WvZIaanK/abkw6s01924DQ2QLwM5Q4Y4iPbSDb9Zg6smyXGqqcPQ7ft9X8D7B0jICz312eSzM6UlQNxuZJBrMw==} + /jest-cli@29.6.1(@types/node@18.11.18): + resolution: {integrity: sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true peerDependencies: @@ -10548,16 +10211,16 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/types': 29.6.0 + '@jest/core': 29.6.1 + '@jest/test-result': 29.6.1 + '@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.0(@types/node@18.11.18) - jest-util: 29.6.0 - jest-validate: 29.6.0 + jest-config: 29.6.1(@types/node@18.11.18) + jest-util: 29.6.1 + jest-validate: 29.6.1 prompts: 2.4.2 yargs: 17.7.2 transitivePeerDependencies: @@ -10575,10 +10238,10 @@ packages: ts-node: optional: true dependencies: - '@babel/core': 7.22.5 + '@babel/core': 7.22.9 '@jest/test-sequencer': 27.5.1 '@jest/types': 27.5.1 - babel-jest: 27.5.1(@babel/core@7.22.5) + babel-jest: 27.5.1(@babel/core@7.22.9) chalk: 4.1.2 ci-info: 3.8.0 deepmerge: 4.3.1 @@ -10599,7 +10262,7 @@ packages: pretty-format: 27.5.1 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3) + ts-node: 10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3) transitivePeerDependencies: - bufferutil - canvas @@ -10607,8 +10270,8 @@ packages: - utf-8-validate dev: true - /jest-config@29.6.0(@types/node@18.11.18): - resolution: {integrity: sha512-fKA4jM91PDqWVkMpb1FVKxIuhg3hC6hgaen57cr1rRZkR96dCatvJZsk3ik7/GNu9ERj9wgAspOmyvkFoGsZhA==} + /jest-config@29.6.1(@types/node@18.11.18): + resolution: {integrity: sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@types/node': '*' @@ -10619,27 +10282,66 @@ packages: ts-node: optional: true dependencies: - '@babel/core': 7.22.5 - '@jest/test-sequencer': 29.6.0 - '@jest/types': 29.6.0 + '@babel/core': 7.22.9 + '@jest/test-sequencer': 29.6.1 + '@jest/types': 29.6.1 '@types/node': 18.11.18 - babel-jest: 29.6.0(@babel/core@7.22.5) + babel-jest: 29.6.1(@babel/core@7.22.9) chalk: 4.1.2 ci-info: 3.8.0 deepmerge: 4.3.1 glob: 7.2.3 graceful-fs: 4.2.11 - jest-circus: 29.6.0 - jest-environment-node: 29.6.0 + jest-circus: 29.6.1 + jest-environment-node: 29.6.1 jest-get-type: 29.4.3 jest-regex-util: 29.4.3 - jest-resolve: 29.6.0 - jest-runner: 29.6.0 - jest-util: 29.6.0 - jest-validate: 29.6.0 + jest-resolve: 29.6.1 + jest-runner: 29.6.1 + jest-util: 29.6.1 + jest-validate: 29.6.1 micromatch: 4.0.5 parse-json: 5.2.0 - pretty-format: 29.6.0 + pretty-format: 29.6.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config@29.6.1(@types/node@20.4.1): + resolution: {integrity: sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==} + 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.9 + '@jest/test-sequencer': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 + babel-jest: 29.6.1(@babel/core@7.22.9) + 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.1 + jest-environment-node: 29.6.1 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.6.1 + jest-runner: 29.6.1 + jest-util: 29.6.1 + jest-validate: 29.6.1 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.6.1 slash: 3.0.0 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -10656,24 +10358,14 @@ packages: pretty-format: 27.5.1 dev: true - /jest-diff@29.5.0: - resolution: {integrity: sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==} + /jest-diff@29.6.1: + resolution: {integrity: sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 diff-sequences: 29.4.3 jest-get-type: 29.4.3 - pretty-format: 29.5.0 - dev: true - - /jest-diff@29.6.0: - resolution: {integrity: sha512-ZRm7cd2m9YyZ0N3iMyuo1iUiprxQ/MFpYWXzEEj7hjzL3WnDffKW8192XBDcrAI8j7hnrM1wed3bL/oEnYF/8w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.4.3 - jest-get-type: 29.4.3 - pretty-format: 29.6.0 + pretty-format: 29.6.1 dev: true /jest-docblock@27.5.1: @@ -10701,15 +10393,15 @@ packages: pretty-format: 27.5.1 dev: true - /jest-each@29.6.0: - resolution: {integrity: sha512-d0Jem4RBAlFUyV6JSXPSHVUpNo5RleSj+iJEy1G3+ZCrzHDjWs/1jUfrbnJKHdJdAx5BCEce/Ju379WqHhQk4w==} + /jest-each@29.6.1: + resolution: {integrity: sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 + '@jest/types': 29.6.1 chalk: 4.1.2 jest-get-type: 29.4.3 - jest-util: 29.6.0 - pretty-format: 29.6.0 + jest-util: 29.6.1 + pretty-format: 29.6.1 dev: true /jest-environment-jsdom@27.5.1: @@ -10719,7 +10411,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -10737,27 +10429,27 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 jest-mock: 27.5.1 jest-util: 27.5.1 dev: true - /jest-environment-node@29.6.0: - resolution: {integrity: sha512-BOf5Q2/nFCdBOnyBM5c5/6DbdQYgc+0gyUQ8l8qhUAB8O7pM+4QJXIXJsRZJaxd5SHV6y5VArTVhOfogoqcP8Q==} + /jest-environment-node@29.6.1: + resolution: {integrity: sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.6.0 - '@jest/fake-timers': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 - jest-mock: 29.6.0 - jest-util: 29.6.0 + '@jest/environment': 29.6.1 + '@jest/fake-timers': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 + jest-mock: 29.6.1 + jest-util: 29.6.1 dev: true /jest-fetch-mock@3.0.3: resolution: {integrity: sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==} dependencies: - cross-fetch: 3.1.6 + cross-fetch: 3.1.8 promise-polyfill: 8.3.0 transitivePeerDependencies: - encoding @@ -10779,7 +10471,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.6 - '@types/node': 20.3.1 + '@types/node': 20.4.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -10793,19 +10485,19 @@ packages: fsevents: 2.3.2 dev: true - /jest-haste-map@29.6.0: - resolution: {integrity: sha512-dY1DKufptj7hcJSuhpqlYPGcnN3XjlOy/g0jinpRTMsbb40ivZHiuIPzeminOZkrek8C+oDxC54ILGO3vMLojg==} + /jest-haste-map@29.6.1: + resolution: {integrity: sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 + '@jest/types': 29.6.1 '@types/graceful-fs': 4.1.6 - '@types/node': 18.11.18 + '@types/node': 20.4.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 jest-regex-util: 29.4.3 - jest-util: 29.6.0 - jest-worker: 29.6.0 + jest-util: 29.6.1 + jest-worker: 29.6.1 micromatch: 4.0.5 walker: 1.0.8 optionalDependencies: @@ -10820,7 +10512,7 @@ packages: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -10845,12 +10537,12 @@ packages: pretty-format: 27.5.1 dev: true - /jest-leak-detector@29.6.0: - resolution: {integrity: sha512-JdV6EZOPxHR1gd6ccxjNowuROkT2jtGU5G/g58RcJX1xe5mrtLj0g6/ZkyMoXF4cs+tTkHMFX6pcIrB1QPQwCw==} + /jest-leak-detector@29.6.1: + resolution: {integrity: sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: jest-get-type: 29.4.3 - pretty-format: 29.6.0 + pretty-format: 29.6.1 dev: true /jest-matcher-utils@27.5.1: @@ -10863,14 +10555,14 @@ packages: pretty-format: 27.5.1 dev: true - /jest-matcher-utils@29.6.0: - resolution: {integrity: sha512-oSlqfGN+sbkB2Q5um/zL7z80w84FEAcLKzXBZIPyRk2F2Srg1ubhrHVKW68JCvb2+xKzAeGw35b+6gciS24PHw==} + /jest-matcher-utils@29.6.1: + resolution: {integrity: sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 - jest-diff: 29.6.0 + jest-diff: 29.6.1 jest-get-type: 29.4.3 - pretty-format: 29.6.0 + pretty-format: 29.6.1 dev: true /jest-message-util@27.5.1: @@ -10888,17 +10580,17 @@ packages: stack-utils: 2.0.6 dev: true - /jest-message-util@29.6.0: - resolution: {integrity: sha512-mkCp56cETbpoNtsaeWVy6SKzk228mMi9FPHSObaRIhbR2Ujw9PqjW/yqVHD2tN1bHbC8ol6h3UEo7dOPmIYwIA==} + /jest-message-util@29.6.1: + resolution: {integrity: sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/code-frame': 7.22.5 - '@jest/types': 29.6.0 + '@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.0 + pretty-format: 29.6.1 slash: 3.0.0 stack-utils: 2.0.6 dev: true @@ -10908,16 +10600,16 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 dev: true - /jest-mock@29.6.0: - resolution: {integrity: sha512-2Pb7R2w24Q0aUVn+2/vdRDL6CqGqpheDZy7zrXav8FotOpSGw/4bS2hyVoKHMEx4xzOn6EyCAGwc5czWxXeN7w==} + /jest-mock@29.6.1: + resolution: {integrity: sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 - '@types/node': 18.11.18 - jest-util: 29.6.0 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 + jest-util: 29.6.1 dev: true /jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): @@ -10932,7 +10624,7 @@ packages: jest-resolve: 27.5.1 dev: true - /jest-pnp-resolver@1.2.3(jest-resolve@29.6.0): + /jest-pnp-resolver@1.2.3(jest-resolve@29.6.1): resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} peerDependencies: @@ -10941,7 +10633,7 @@ packages: jest-resolve: optional: true dependencies: - jest-resolve: 29.6.0 + jest-resolve: 29.6.1 dev: true /jest-regex-util@27.5.1: @@ -10965,12 +10657,12 @@ packages: - supports-color dev: true - /jest-resolve-dependencies@29.6.0: - resolution: {integrity: sha512-eOfPog9K3hJdJk/3i6O6bQhXS+3uXhMDkLJGX+xmMPp7T1d/zdcFofbDnHgNoEkhD/mSimC5IagLEP7lpLLu/A==} + /jest-resolve-dependencies@29.6.1: + resolution: {integrity: sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: jest-regex-util: 29.4.3 - jest-snapshot: 29.6.0 + jest-snapshot: 29.6.1 transitivePeerDependencies: - supports-color dev: true @@ -10991,16 +10683,16 @@ packages: slash: 3.0.0 dev: true - /jest-resolve@29.6.0: - resolution: {integrity: sha512-+hrpY4LzAONoZA/rvB6rnZLkOSA6UgJLpdCWrOZNSgGxWMumzRLu7dLUSCabAHzoHIDQ9qXfr3th1zYNJ0E8sQ==} + /jest-resolve@29.6.1: + resolution: {integrity: sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 graceful-fs: 4.2.11 - jest-haste-map: 29.6.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.6.0) - jest-util: 29.6.0 - jest-validate: 29.6.0 + jest-haste-map: 29.6.1 + jest-pnp-resolver: 1.2.3(jest-resolve@29.6.1) + jest-util: 29.6.1 + jest-validate: 29.6.1 resolve: 1.22.2 resolve.exports: 2.0.2 slash: 3.0.0 @@ -11015,7 +10707,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.11 @@ -11038,29 +10730,29 @@ packages: - utf-8-validate dev: true - /jest-runner@29.6.0: - resolution: {integrity: sha512-4fZuGV2lOxS2BiqEG9/AI8E6O+jo+QZjMVcgi1x5E6aDql0Gd/EFIbUQ0pSS09y8cya1vJB/qC2xsE468jqtSg==} + /jest-runner@29.6.1: + resolution: {integrity: sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/console': 29.6.0 - '@jest/environment': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/transform': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/console': 29.6.1 + '@jest/environment': 29.6.1 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 jest-docblock: 29.4.3 - jest-environment-node: 29.6.0 - jest-haste-map: 29.6.0 - jest-leak-detector: 29.6.0 - jest-message-util: 29.6.0 - jest-resolve: 29.6.0 - jest-runtime: 29.6.0 - jest-util: 29.6.0 - jest-watcher: 29.6.0 - jest-worker: 29.6.0 + jest-environment-node: 29.6.1 + jest-haste-map: 29.6.1 + jest-leak-detector: 29.6.1 + jest-message-util: 29.6.1 + jest-resolve: 29.6.1 + jest-runtime: 29.6.1 + jest-util: 29.6.1 + jest-watcher: 29.6.1 + jest-worker: 29.6.1 p-limit: 3.1.0 source-map-support: 0.5.13 transitivePeerDependencies: @@ -11080,7 +10772,7 @@ packages: '@jest/types': 27.5.1 chalk: 4.1.2 cjs-module-lexer: 1.2.3 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 execa: 5.1.1 glob: 7.2.3 graceful-fs: 4.2.11 @@ -11097,30 +10789,30 @@ packages: - supports-color dev: true - /jest-runtime@29.6.0: - resolution: {integrity: sha512-5FavYo3EeXLHIvnJf+r7Cj0buePAbe4mzRB9oeVxDS0uVmouSBjWeGgyRjZkw7ArxOoZI8gO6f8SGMJ2HFlwwg==} + /jest-runtime@29.6.1: + resolution: {integrity: sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.6.0 - '@jest/fake-timers': 29.6.0 - '@jest/globals': 29.6.0 + '@jest/environment': 29.6.1 + '@jest/fake-timers': 29.6.1 + '@jest/globals': 29.6.1 '@jest/source-map': 29.6.0 - '@jest/test-result': 29.6.0 - '@jest/transform': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/test-result': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 chalk: 4.1.2 cjs-module-lexer: 1.2.3 - collect-v8-coverage: 1.0.1 + collect-v8-coverage: 1.0.2 glob: 7.2.3 graceful-fs: 4.2.11 - jest-haste-map: 29.6.0 - jest-message-util: 29.6.0 - jest-mock: 29.6.0 + jest-haste-map: 29.6.1 + jest-message-util: 29.6.1 + jest-mock: 29.6.1 jest-regex-util: 29.4.3 - jest-resolve: 29.6.0 - jest-snapshot: 29.6.0 - jest-util: 29.6.0 + jest-resolve: 29.6.1 + jest-snapshot: 29.6.1 + jest-util: 29.6.1 slash: 3.0.0 strip-bom: 4.0.0 transitivePeerDependencies: @@ -11131,7 +10823,7 @@ packages: resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 graceful-fs: 4.2.11 dev: true @@ -11139,16 +10831,16 @@ packages: resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@babel/core': 7.22.5 - '@babel/generator': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.5) - '@babel/traverse': 7.22.5 + '@babel/core': 7.22.9 + '@babel/generator': 7.22.9 + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) + '@babel/traverse': 7.22.8 '@babel/types': 7.22.5 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 '@types/babel__traverse': 7.20.1 '@types/prettier': 2.7.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.9) chalk: 4.1.2 expect: 27.5.1 graceful-fs: 4.2.11 @@ -11160,35 +10852,35 @@ packages: jest-util: 27.5.1 natural-compare: 1.4.0 pretty-format: 27.5.1 - semver: 7.5.1 + semver: 7.5.4 transitivePeerDependencies: - supports-color dev: true - /jest-snapshot@29.6.0: - resolution: {integrity: sha512-H3kUE9NwWDEDoutcOSS921IqdlkdjgnMdj1oMyxAHNflscdLc9dB8OudZHV6kj4OHJxbMxL8CdI5DlwYrs4wQg==} + /jest-snapshot@29.6.1: + resolution: {integrity: sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/core': 7.22.5 - '@babel/generator': 7.22.5 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5) - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.5) + '@babel/core': 7.22.9 + '@babel/generator': 7.22.9 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) '@babel/types': 7.22.5 - '@jest/expect-utils': 29.6.0 - '@jest/transform': 29.6.0 - '@jest/types': 29.6.0 + '@jest/expect-utils': 29.6.1 + '@jest/transform': 29.6.1 + '@jest/types': 29.6.1 '@types/prettier': 2.7.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.9) chalk: 4.1.2 - expect: 29.6.0 + expect: 29.6.1 graceful-fs: 4.2.11 - jest-diff: 29.6.0 + jest-diff: 29.6.1 jest-get-type: 29.4.3 - jest-matcher-utils: 29.6.0 - jest-message-util: 29.6.0 - jest-util: 29.6.0 + jest-matcher-utils: 29.6.1 + jest-message-util: 29.6.1 + jest-util: 29.6.1 natural-compare: 1.4.0 - pretty-format: 29.6.0 + pretty-format: 29.6.1 semver: 7.5.4 transitivePeerDependencies: - supports-color @@ -11199,19 +10891,19 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 picomatch: 2.3.1 dev: true - /jest-util@29.6.0: - resolution: {integrity: sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA==} + /jest-util@29.6.1: + resolution: {integrity: sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -11230,16 +10922,16 @@ packages: pretty-format: 27.5.1 dev: true - /jest-validate@29.6.0: - resolution: {integrity: sha512-MLTrAJsb1+W7svbeZ+A7pAnyXMaQrjvPDKCy7OlfsfB6TMVc69v7WjUWfiR6r3snULFWZASiKgvNVDuATta1dg==} + /jest-validate@29.6.1: + resolution: {integrity: sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.6.0 + '@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.0 + pretty-format: 29.6.1 dev: true /jest-watcher@27.5.1: @@ -11248,24 +10940,24 @@ packages: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.3.1 + '@types/node': 20.4.1 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 string-length: 4.0.2 dev: true - /jest-watcher@29.6.0: - resolution: {integrity: sha512-LdsQqFNX60mRdRRe+zsELnYRH1yX6KL+ukbh+u6WSQeTheZZe1TlLJNKRQiZ7e0VbvMkywmMWL/KV35noOJCcw==} + /jest-watcher@29.6.1: + resolution: {integrity: sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/test-result': 29.6.0 - '@jest/types': 29.6.0 - '@types/node': 18.11.18 + '@jest/test-result': 29.6.1 + '@jest/types': 29.6.1 + '@types/node': 20.4.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 - jest-util: 29.6.0 + jest-util: 29.6.1 string-length: 4.0.2 dev: true @@ -11282,7 +10974,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.3.1 + '@types/node': 20.4.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -11291,18 +10983,18 @@ packages: 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.0 + '@types/node': 20.4.1 + jest-util: 29.6.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true - /jest-worker@29.6.0: - resolution: {integrity: sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA==} + /jest-worker@29.6.1: + resolution: {integrity: sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 18.11.18 - jest-util: 29.6.0 + '@types/node': 20.4.1 + jest-util: 29.6.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -11338,10 +11030,10 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.6.0 - '@jest/types': 29.6.0 + '@jest/core': 29.6.1 + '@jest/types': 29.6.1 import-local: 3.1.0 - jest-cli: 29.6.0(@types/node@18.11.18) + jest-cli: 29.6.1(@types/node@18.11.18) transitivePeerDependencies: - '@types/node' - supports-color @@ -11464,13 +11156,13 @@ packages: data-urls: 2.0.0 decimal.js: 10.4.3 domexception: 2.0.1 - escodegen: 2.0.0 + escodegen: 2.1.0 form-data: 3.0.1 html-encoding-sniffer: 2.0.1 http-proxy-agent: 4.0.1 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.5 + nwsapi: 2.2.7 parse5: 6.0.1 saxes: 5.0.1 symbol-tree: 3.2.4 @@ -11499,20 +11191,20 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.9.0 + acorn: 8.10.0 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 data-urls: 3.0.2 decimal.js: 10.4.3 domexception: 4.0.0 - escodegen: 2.0.0 + escodegen: 2.1.0 form-data: 4.0.0 html-encoding-sniffer: 3.0.0 http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.5 + nwsapi: 2.2.7 parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -11567,7 +11259,7 @@ packages: json5: 2.2.3 loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /json5@1.0.2: @@ -12021,13 +11713,6 @@ packages: engines: {node: '>=6'} dev: true - /levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -12214,6 +11899,10 @@ 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==} @@ -12284,8 +11973,8 @@ packages: engines: {node: '>=12'} dev: false - /magic-string@0.30.0: - resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} + /magic-string@0.30.1: + resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==} engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 @@ -12421,7 +12110,7 @@ packages: /meilisearch@0.33.0: resolution: {integrity: sha512-bYPb9WyITnJfzf92e7QFK8Rc50DmshFWxypXCs3ILlpNh8pT15A7KSu9Xgnnk/K3G/4vb3wkxxtFS4sxNkWB8w==} dependencies: - cross-fetch: 3.1.6 + cross-fetch: 3.1.8 transitivePeerDependencies: - encoding dev: false @@ -12697,7 +12386,7 @@ packages: dependencies: ansi-colors: 4.1.1 browser-stdout: 1.3.1 - chokidar: 3.5.3 + chokidar: 3.3.1 debug: 4.3.4(supports-color@8.1.1) diff: 5.0.0 escape-string-regexp: 4.0.0 @@ -12921,17 +12610,6 @@ packages: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} - /node-fetch@2.6.11: - resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - /node-fetch@2.6.12: resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} engines: {node: 4.x || >=6.0.0} @@ -12942,7 +12620,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: false /node-fetch@3.3.1: resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} @@ -13029,7 +12706,7 @@ packages: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.12.1 - semver: 7.5.1 + semver: 7.5.4 validate-npm-package-license: 3.0.4 dev: true @@ -13139,8 +12816,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /nwsapi@2.2.5: - resolution: {integrity: sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==} + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} /oauth-sign@0.9.0: resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} @@ -13236,7 +12913,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /oblivious-set@1.1.1: @@ -13287,17 +12964,6 @@ packages: hasBin: true dev: false - /optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -14022,14 +13688,6 @@ packages: supports-color: 3.2.3 dev: true - /postcss@8.4.24: - resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.6 - picocolors: 1.0.0 - source-map-js: 1.0.2 - /postcss@8.4.25: resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} engines: {node: ^10 || ^12 || >=14} @@ -14037,7 +13695,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} @@ -14080,10 +13737,6 @@ packages: tunnel-agent: 0.6.0 dev: false - /prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -14106,6 +13759,12 @@ 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'} @@ -14132,17 +13791,8 @@ packages: react-is: 17.0.2 dev: true - /pretty-format@29.5.0: - resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.4.3 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - - /pretty-format@29.6.0: - resolution: {integrity: sha512-XH+D4n7Ey0iSR6PdAnBs99cWMZdGsdKrR33iUHQNr79w1szKTCIZDVdXuccAsHVwDBp0XeWPfNEoaxP9EZgRmQ==} + /pretty-format@29.6.1: + resolution: {integrity: sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/schemas': 29.6.0 @@ -14612,11 +14262,18 @@ packages: minimatch: 5.1.6 dev: false + /readdirp@3.3.0: + resolution: {integrity: sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 + dev: true /rechoir@0.6.2: resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} @@ -15055,7 +14712,7 @@ packages: htmlparser2: 8.0.2 is-plain-object: 5.0.0 parse-srcset: 1.0.2 - postcss: 8.4.24 + postcss: 8.4.25 dev: false /sass@1.63.6: @@ -15064,7 +14721,7 @@ packages: hasBin: true dependencies: chokidar: 3.5.3 - immutable: 4.3.0 + immutable: 4.3.1 source-map-js: 1.0.2 dev: true @@ -15143,13 +14800,6 @@ packages: lru-cache: 6.0.0 dev: true - /semver@7.5.1: - resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -15667,7 +15317,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /string.prototype.trimend@1.0.6: @@ -15675,7 +15325,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /string.prototype.trimstart@1.0.6: @@ -15683,7 +15333,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - es-abstract: 1.21.2 + es-abstract: 1.21.3 dev: true /string_decoder@0.10.31: @@ -15880,16 +15530,6 @@ packages: whet.extend: 0.9.9 dev: true - /swc-loader@0.2.3(@swc/core@1.3.62)(webpack@5.85.1): - resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} - peerDependencies: - '@swc/core': ^1.2.147 - webpack: '>=2' - dependencies: - '@swc/core': 1.3.62 - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) - dev: true - /swc-loader@0.2.3(@swc/core@1.3.68)(webpack@5.88.1): resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} peerDependencies: @@ -15897,7 +15537,7 @@ packages: webpack: '>=2' dependencies: '@swc/core': 1.3.68 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /swiper@10.0.4: @@ -15994,31 +15634,6 @@ packages: supports-hyperlinks: 2.3.0 dev: true - /terser-webpack-plugin@5.3.9(@swc/core@1.3.62)(webpack@5.85.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.18 - '@swc/core': 1.3.62 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.1 - terser: 5.18.2 - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) - dev: true - /terser-webpack-plugin@5.3.9(@swc/core@1.3.68)(webpack@5.88.1): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} @@ -16040,17 +15655,17 @@ packages: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.1 - terser: 5.18.2 - webpack: 5.88.1(@swc/core@1.3.68) + terser: 5.19.0 + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true - /terser@5.18.2: - resolution: {integrity: sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==} + /terser@5.19.0: + resolution: {integrity: sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q==} engines: {node: '>=10'} hasBin: true dependencies: - '@jridgewell/source-map': 0.3.3 - acorn: 8.9.0 + '@jridgewell/source-map': 0.3.5 + acorn: 8.10.0 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -16069,7 +15684,7 @@ packages: idb-keyval: 3.2.0 is-electron: 2.2.2 is-url: 1.2.4 - node-fetch: 2.6.11 + node-fetch: 2.6.12 opencollective-postinstall: 2.0.3 regenerator-runtime: 0.13.11 resolve-url: 0.2.1 @@ -16299,7 +15914,7 @@ packages: escape-string-regexp: 5.0.0 dev: true - /ts-jest@27.1.2(@babel/core@7.22.8)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3): + /ts-jest@27.1.2(@babel/core@7.22.9)(@types/jest@27.4.0)(jest@27.4.5)(typescript@5.1.3): resolution: {integrity: sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} hasBin: true @@ -16320,7 +15935,7 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.22.8 + '@babel/core': 7.22.9 '@types/jest': 27.4.0 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -16329,12 +15944,12 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.5.1 + semver: 7.5.4 typescript: 5.1.3 yargs-parser: 20.2.9 dev: true - /ts-jest@29.0.5(@babel/core@7.22.8)(jest@29.4.0)(typescript@4.9.4): + /ts-jest@29.0.5(@babel/core@7.22.9)(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 @@ -16355,11 +15970,11 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.22.8 + '@babel/core': 7.22.9 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 jest: 29.4.0(@types/node@18.11.18) - jest-util: 29.6.0 + jest-util: 29.6.1 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -16380,10 +15995,10 @@ packages: micromatch: 4.0.5 semver: 7.5.4 typescript: 5.1.6 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true - /ts-node@10.4.0(@swc/core@1.3.62)(@types/node@20.3.1)(typescript@5.1.3): + /ts-node@10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3): resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} hasBin: true peerDependencies: @@ -16398,13 +16013,13 @@ packages: optional: true dependencies: '@cspotcode/source-map-support': 0.7.0 - '@swc/core': 1.3.62 + '@swc/core': 1.3.68 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 20.3.1 - acorn: 8.9.0 + acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 @@ -16435,7 +16050,7 @@ packages: '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 '@types/node': 18.11.18 - acorn: 8.9.0 + acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 @@ -16483,7 +16098,7 @@ packages: '@tsd/typescript': 5.0.4 eslint-formatter-pretty: 4.1.0 globby: 11.1.0 - jest-diff: 29.5.0 + jest-diff: 29.6.1 meow: 9.0.0 path-exists: 4.0.0 read-pkg-up: 7.0.1 @@ -16522,12 +16137,6 @@ packages: /twemoji-parser@14.0.0: resolution: {integrity: sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==} - /type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -16581,6 +16190,17 @@ packages: /type@2.7.2: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.10 + dev: true + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: @@ -17089,7 +16709,7 @@ packages: optional: true dependencies: '@types/node': 20.4.1 - esbuild: 0.18.11 + esbuild: 0.18.12 postcss: 8.4.25 rollup: 3.26.2 sass: 1.63.6 @@ -17246,7 +16866,7 @@ packages: engines: {node: '>=12'} dev: false - /webpack-cli@5.1.3(webpack@5.85.1): + /webpack-cli@5.1.3(webpack@5.88.1): resolution: {integrity: sha512-MTuk7NUMvEHQUSXCpvUrF1q2p0FJS40dPFfqQvG3jTWcgv/8plBNz2Kv2HXZiLGPnfmSAA5uCtCILO1JBmmkfw==} engines: {node: '>=14.15.0'} hasBin: true @@ -17264,9 +16884,9 @@ packages: optional: true dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.3)(webpack@5.85.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.3)(webpack@5.85.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.3)(webpack@5.85.1) + '@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 @@ -17275,7 +16895,7 @@ packages: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) webpack-merge: 5.9.0 dev: true @@ -17292,48 +16912,7 @@ packages: engines: {node: '>=10.13.0'} dev: true - /webpack@5.85.1(@swc/core@1.3.62)(webpack-cli@5.1.3): - resolution: {integrity: sha512-xTb7MRf4LY8Z5rzn7aIx4TDrwYJrjcHnIfU1TqtyZOoObyuGSpAUwIvVuqq5wPnv7WEgQr8UvO1q/dgoGG4HjA==} - 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.9.0 - acorn-import-assertions: 1.9.0(acorn@8.9.0) - browserslist: 4.21.9 - 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.62)(webpack@5.85.1) - watchpack: 2.4.0 - webpack-cli: 5.1.3(webpack@5.85.1) - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - - /webpack@5.88.1(@swc/core@1.3.68): + /webpack@5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3): resolution: {integrity: sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==} engines: {node: '>=10.13.0'} hasBin: true @@ -17366,6 +16945,7 @@ packages: tapable: 2.2.1 terser-webpack-plugin: 5.3.9(@swc/core@1.3.68)(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' @@ -17470,19 +17050,6 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 is-typed-array: 1.1.10 - dev: false - - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: true /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} @@ -17511,15 +17078,11 @@ packages: resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} engines: {node: '>= 10.0.0'} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.7 '@babel/types': 7.22.5 assert-never: 1.2.1 babel-walk: 3.0.0-canary-5 - /word-wrap@1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - /workerpool@6.2.1: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} dev: true @@ -17647,7 +17210,7 @@ packages: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} dependencies: - sax: 1.2.4 + sax: 1.2.1 xmlbuilder: 11.0.1 dev: false From bfa2f045d2c0f937cbc9756844ba834b1478f0d2 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Wed, 12 Jul 2023 23:56:22 -0700 Subject: [PATCH 090/162] refactor: :recycle: substr -> slice --- packages/backend/src/misc/acct.ts | 2 +- packages/backend/src/server/api/service/discord.ts | 2 +- packages/backend/src/server/api/service/github.ts | 2 +- packages/calckey-js/src/acct.ts | 2 +- packages/client/src/components/MkUserPreview.vue | 2 +- packages/client/src/scripts/gen-search-query.ts | 2 +- packages/client/src/scripts/search.ts | 2 +- packages/client/src/scripts/theme-editor.ts | 2 +- packages/client/src/scripts/theme.ts | 4 ++-- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/misc/acct.ts b/packages/backend/src/misc/acct.ts index 5b7767a10..cb6808b4b 100644 --- a/packages/backend/src/misc/acct.ts +++ b/packages/backend/src/misc/acct.ts @@ -4,7 +4,7 @@ export type Acct = { }; export function parse(acct: string): Acct { - if (acct.startsWith("@")) acct = acct.substr(1); + if (acct.startsWith("@")) acct = acct.slice(1); const split = acct.split("@", 2); return { username: split[0], host: split[1] || null }; } diff --git a/packages/backend/src/server/api/service/discord.ts b/packages/backend/src/server/api/service/discord.ts index 9906d2f7c..296e9cb48 100644 --- a/packages/backend/src/server/api/service/discord.ts +++ b/packages/backend/src/server/api/service/discord.ts @@ -18,7 +18,7 @@ function getUserToken(ctx: Koa.BaseContext): string | null { function compareOrigin(ctx: Koa.BaseContext): boolean { function normalizeUrl(url?: string): string { - return url ? (url.endsWith("/") ? url.substr(0, url.length - 1) : url) : ""; + return slice( url.length - 1) : url) : ""; } const referer = ctx.headers["referer"]; diff --git a/packages/backend/src/server/api/service/github.ts b/packages/backend/src/server/api/service/github.ts index f77c5f795..da9d0931a 100644 --- a/packages/backend/src/server/api/service/github.ts +++ b/packages/backend/src/server/api/service/github.ts @@ -18,7 +18,7 @@ function getUserToken(ctx: Koa.BaseContext): string | null { function compareOrigin(ctx: Koa.BaseContext): boolean { function normalizeUrl(url?: string): string { - return url ? (url.endsWith("/") ? url.substr(0, url.length - 1) : url) : ""; + return slice( url.length - 1) : url) : ""; } const referer = ctx.headers["referer"]; diff --git a/packages/calckey-js/src/acct.ts b/packages/calckey-js/src/acct.ts index 5b7767a10..cb6808b4b 100644 --- a/packages/calckey-js/src/acct.ts +++ b/packages/calckey-js/src/acct.ts @@ -4,7 +4,7 @@ export type Acct = { }; export function parse(acct: string): Acct { - if (acct.startsWith("@")) acct = acct.substr(1); + if (acct.startsWith("@")) acct = acct.slice(1); const split = acct.split("@", 2); return { username: split[0], host: split[1] || null }; } diff --git a/packages/client/src/components/MkUserPreview.vue b/packages/client/src/components/MkUserPreview.vue index 6c3838fd2..7aec66136 100644 --- a/packages/client/src/components/MkUserPreview.vue +++ b/packages/client/src/components/MkUserPreview.vue @@ -155,7 +155,7 @@ onMounted(() => { user.description.length > 400; } else { const query = props.q.startsWith("@") - ? Acct.parse(props.q.substr(1)) + ? Acct.parse(props.q.slice(1)) : { userId: props.q }; os.api("users/show", query).then((res) => { diff --git a/packages/client/src/scripts/gen-search-query.ts b/packages/client/src/scripts/gen-search-query.ts index 822572d3e..fcf1f727e 100644 --- a/packages/client/src/scripts/gen-search-query.ts +++ b/packages/client/src/scripts/gen-search-query.ts @@ -8,7 +8,7 @@ export async function genSearchQuery(v: any, q: string) { for (const at of q .split(" ") .filter((x) => x.startsWith("@")) - .map((x) => x.substr(1))) { + .map((x) => x.slice(1))) { if (at.includes(".")) { if (at === localHost || at === ".") { host = null; diff --git a/packages/client/src/scripts/search.ts b/packages/client/src/scripts/search.ts index 34318ab0e..ecea1ff2d 100644 --- a/packages/client/src/scripts/search.ts +++ b/packages/client/src/scripts/search.ts @@ -19,7 +19,7 @@ export async function search() { } if (q.startsWith("#")) { - mainRouter.push(`/tags/${encodeURIComponent(q.substr(1))}`); + mainRouter.push(`/tags/${encodeURIComponent(q.slice(1))}`); return; } diff --git a/packages/client/src/scripts/theme-editor.ts b/packages/client/src/scripts/theme-editor.ts index 482841017..fc015b6ac 100644 --- a/packages/client/src/scripts/theme-editor.ts +++ b/packages/client/src/scripts/theme-editor.ts @@ -35,7 +35,7 @@ export const fromThemeString = (str?: string): ThemeValue => { } else if (str.startsWith('"')) { return { type: "css", - value: str.substr(1).trim(), + value: str.slice(1).trim(), }; } else { return str; diff --git a/packages/client/src/scripts/theme.ts b/packages/client/src/scripts/theme.ts index 383deb34c..c52c2c217 100644 --- a/packages/client/src/scripts/theme.ts +++ b/packages/client/src/scripts/theme.ts @@ -112,7 +112,7 @@ function compile(theme: Theme): Record<string, string> { function getColor(val: string): tinycolor.Instance { // ref (prop) if (val[0] === "@") { - return getColor(theme.props[val.substr(1)]); + return getColor(theme.props[val.slice(1)]); } // ref (const) @@ -123,7 +123,7 @@ function compile(theme: Theme): Record<string, string> { // func else if (val[0] === ":") { const parts = val.split("<"); - const func = parts.shift().substr(1); + const func = parts.shift().slice(1); const arg = parseFloat(parts.shift()); const color = getColor(parts.join("<")); From 7b4de4125f2d7fd2a01425bc77f9bea626fbdbf3 Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Thu, 13 Jul 2023 13:22:50 +0000 Subject: [PATCH 091/162] fix #10483 --- packages/backend/src/server/api/service/discord.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/service/discord.ts b/packages/backend/src/server/api/service/discord.ts index 296e9cb48..848a70d4a 100644 --- a/packages/backend/src/server/api/service/discord.ts +++ b/packages/backend/src/server/api/service/discord.ts @@ -18,7 +18,7 @@ function getUserToken(ctx: Koa.BaseContext): string | null { function compareOrigin(ctx: Koa.BaseContext): boolean { function normalizeUrl(url?: string): string { - return slice( url.length - 1) : url) : ""; + return url ? (url.endsWith("/") ? url.slice(0, url.length - 1) : url) : ""; } const referer = ctx.headers["referer"]; From 26a49cfa0727458deb9d57526e9505d31e83e685 Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Thu, 13 Jul 2023 13:25:45 +0000 Subject: [PATCH 092/162] fix #10483 (2) --- packages/backend/src/server/api/service/github.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/service/github.ts b/packages/backend/src/server/api/service/github.ts index da9d0931a..fd015fb8a 100644 --- a/packages/backend/src/server/api/service/github.ts +++ b/packages/backend/src/server/api/service/github.ts @@ -18,7 +18,7 @@ function getUserToken(ctx: Koa.BaseContext): string | null { function compareOrigin(ctx: Koa.BaseContext): boolean { function normalizeUrl(url?: string): string { - return slice( url.length - 1) : url) : ""; + return url ? (url.endsWith("/") ? url.slice(0, url.length - 1) : url) : ""; } const referer = ctx.headers["referer"]; From 098ca8e6228319efab27982dbb42f0284fa099f1 Mon Sep 17 00:00:00 2001 From: okayurisotto <okayurisotto@proton.me> Date: Tue, 11 Jul 2023 14:58:58 +0900 Subject: [PATCH 093/162] refactor(backend): Use `exist` to check existence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(backend): 存在確認の`findOneBy`を`exist`に置き換え * cleanup --- .../api/endpoints/admin/promo/create.ts | 4 ++-- .../src/server/api/endpoints/auth/accept.ts | 10 ++++++---- .../server/api/endpoints/blocking/create.ts | 10 ++++++---- .../server/api/endpoints/blocking/delete.ts | 10 ++++++---- .../server/api/endpoints/clips/add-note.ts | 10 ++++++---- .../endpoints/drive/files/check-existence.ts | 10 ++++++---- .../server/api/endpoints/following/create.ts | 10 ++++++---- .../server/api/endpoints/following/delete.ts | 10 ++++++---- .../api/endpoints/gallery/posts/like.ts | 10 ++++++---- .../api/endpoints/i/read-announcement.ts | 6 ++++-- .../server/api/endpoints/i/revoke-token.ts | 4 ++-- .../src/server/api/endpoints/mute/create.ts | 10 ++++++---- .../src/server/api/endpoints/notes/create.ts | 20 +++++++++++-------- .../api/endpoints/notes/favorites/create.ts | 10 ++++++---- .../src/server/api/endpoints/pages/like.ts | 10 ++++++---- .../src/server/api/endpoints/promo/read.ts | 10 ++++++---- .../server/api/endpoints/users/followers.ts | 10 ++++++---- .../server/api/endpoints/users/following.ts | 10 ++++++---- .../server/api/endpoints/users/lists/push.ts | 10 ++++++---- .../server/api/endpoints/users/lists/show.ts | 10 ++++++---- .../server/api/stream/channels/user-list.ts | 10 ++++++---- 21 files changed, 122 insertions(+), 82 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts index a6d1f3519..00244a777 100644 --- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/promo/create.ts @@ -40,9 +40,9 @@ export default define(meta, paramDef, async (ps, user) => { throw err; }); - const exist = await PromoNotes.findOneBy({ noteId: note.id }); + const exist = await PromoNotes.exist({ where: { noteId: note.id } }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyPromoted); } diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts index 35565e256..8e6ad6527 100644 --- a/packages/backend/src/server/api/endpoints/auth/accept.ts +++ b/packages/backend/src/server/api/endpoints/auth/accept.ts @@ -41,12 +41,14 @@ export default define(meta, paramDef, async (ps, user) => { const accessToken = secureRndstr(32, true); // Fetch exist access token - const exist = await AccessTokens.findOneBy({ - appId: session.appId, - userId: user.id, + const exist = await AccessTokens.exist({ + where: { + appId: session.appId, + userId: user.id, + }, }); - if (exist == null) { + if (!exist) { // Lookup app const app = await Apps.findOneByOrFail({ id: session.appId }); diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 4bd58d5ef..f00a2923d 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -69,12 +69,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check if already blocking - const exist = await Blockings.findOneBy({ - blockerId: blocker.id, - blockeeId: blockee.id, + const exist = await Blockings.exist({ + where: { + blockerId: blocker.id, + blockeeId: blockee.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyBlocking); } diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index 6c4ca2775..037d5af22 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -69,12 +69,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check not blocking - const exist = await Blockings.findOneBy({ - blockerId: blocker.id, - blockeeId: blockee.id, + const exist = await Blockings.exist({ + where: { + blockerId: blocker.id, + blockeeId: blockee.id, + }, }); - if (exist == null) { + if (!exist) { throw new ApiError(meta.errors.notBlocking); } diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts index b9d6b54c9..416af6faa 100644 --- a/packages/backend/src/server/api/endpoints/clips/add-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts @@ -57,12 +57,14 @@ export default define(meta, paramDef, async (ps, user) => { throw err; }); - const exist = await ClipNotes.findOneBy({ - noteId: note.id, - clipId: clip.id, + const exist = await ClipNotes.exist({ + where: { + noteId: note.id, + clipId: clip.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyClipped); } diff --git a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts index df8968520..e26da30eb 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts @@ -26,10 +26,12 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, user) => { - const file = await DriveFiles.findOneBy({ - md5: ps.md5, - userId: user.id, + const exist = await DriveFiles.exist({ + where: { + md5: ps.md5, + userId: user.id, + }, }); - return file != null; + return exist; }); diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index e617c1ffb..48ae6ae7a 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -82,12 +82,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check if already following - const exist = await Followings.findOneBy({ - followerId: follower.id, - followeeId: followee.id, + const exist = await Followings.exist({ + where: { + followerId: follower.id, + followeeId: followee.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyFollowing); } diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 2eebe8a90..cbc6097f4 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -69,12 +69,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check not following - const exist = await Followings.findOneBy({ - followerId: follower.id, - followeeId: followee.id, + const exist = await Followings.exist({ + where: { + followerId: follower.id, + followeeId: followee.id, + }, }); - if (exist == null) { + if (!exist) { throw new ApiError(meta.errors.notFollowing); } diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts index fd46406bd..2506e40aa 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts @@ -40,12 +40,14 @@ export default define(meta, paramDef, async (ps, user) => { } // if already liked - const exist = await GalleryLikes.findOneBy({ - postId: post.id, - userId: user.id, + const exist = await GalleryLikes.exist({ + where: { + postId: post.id, + userId: user.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyLiked); } diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts index 5218dba87..e44445b1b 100644 --- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts +++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts @@ -30,9 +30,11 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Check if announcement exists - const announcement = await Announcements.findOneBy({ id: ps.announcementId }); + const exist = await Announcements.findOneBy({ + where: { id: ps.announcementId }, + }); - if (announcement == null) { + if (!exist) { throw new ApiError(meta.errors.noSuchAnnouncement); } diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts index 308442bf7..3a410fa0e 100644 --- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts +++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts @@ -17,9 +17,9 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, user) => { - const token = await AccessTokens.findOneBy({ id: ps.tokenId }); + const exist = await AccessTokens.exist({ where: { id: ps.tokenId } }); - if (token) { + if (exist) { await AccessTokens.delete({ id: ps.tokenId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index bacab9b45..7b2f10905 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -64,12 +64,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check if already muting - const exist = await Mutings.findOneBy({ - muterId: muter.id, - muteeId: mutee.id, + const exist = await Mutings.exist({ + where: { + muterId: muter.id, + muteeId: mutee.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyMuting); } diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 41b8ab979..e15221046 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -224,11 +224,13 @@ export default define(meta, paramDef, async (ps, user) => { // Check blocking if (renote.userId !== user.id) { - const block = await Blockings.findOneBy({ - blockerId: renote.userId, - blockeeId: user.id, + const isBlocked = await Blockings.exist({ + where: { + blockerId: renote.userId, + blockeeId: user.id, + }, }); - if (block) { + if (isBlocked) { throw new ApiError(meta.errors.youHaveBeenBlocked); } } @@ -249,11 +251,13 @@ export default define(meta, paramDef, async (ps, user) => { // Check blocking if (reply.userId !== user.id) { - const block = await Blockings.findOneBy({ - blockerId: reply.userId, - blockeeId: user.id, + const isBlocked = await Blockings.exist({ + where: { + blockerId: reply.userId, + blockeeId: user.id, + }, }); - if (block) { + if (isBlocked) { throw new ApiError(meta.errors.youHaveBeenBlocked); } } diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts index 835594f03..64862a373 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts @@ -43,12 +43,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // if already favorited - const exist = await NoteFavorites.findOneBy({ - noteId: note.id, - userId: user.id, + const exist = await NoteFavorites.exist({ + where: { + noteId: note.id, + userId: user.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyFavorited); } diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts index f14ed39eb..03482c961 100644 --- a/packages/backend/src/server/api/endpoints/pages/like.ts +++ b/packages/backend/src/server/api/endpoints/pages/like.ts @@ -40,12 +40,14 @@ export default define(meta, paramDef, async (ps, user) => { } // if already liked - const exist = await PageLikes.findOneBy({ - pageId: page.id, - userId: user.id, + const exist = await PageLikes.exist({ + where: { + pageId: page.id, + userId: user.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyLiked); } diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts index 09c8cb6fa..5310382a4 100644 --- a/packages/backend/src/server/api/endpoints/promo/read.ts +++ b/packages/backend/src/server/api/endpoints/promo/read.ts @@ -33,12 +33,14 @@ export default define(meta, paramDef, async (ps, user) => { throw err; }); - const exist = await PromoReads.findOneBy({ - noteId: note.id, - userId: user.id, + const exist = await PromoReads.exist({ + where: { + noteId: note.id, + userId: user.id, + }, }); - if (exist != null) { + if (exist) { return; } diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 855ab3573..31719bad3 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -98,11 +98,13 @@ export default define(meta, paramDef, async (ps, me) => { if (me == null) { throw new ApiError(meta.errors.forbidden); } else if (me.id !== user.id) { - const following = await Followings.findOneBy({ - followeeId: user.id, - followerId: me.id, + const isFollowed = await Followings.exist({ + where: { + followeeId: user.id, + followerId: me.id, + }, }); - if (following == null) { + if (!isFollowed) { throw new ApiError(meta.errors.nullFollowers); } } diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 37d69b048..1c1da0e11 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -97,11 +97,13 @@ export default define(meta, paramDef, async (ps, me) => { if (me == null) { throw new ApiError(meta.errors.forbidden); } else if (me.id !== user.id) { - const following = await Followings.findOneBy({ - followeeId: user.id, - followerId: me.id, + const isFollowing = await Followings.exist({ + where: { + followeeId: user.id, + followerId: me.id, + }, }); - if (following == null) { + if (!isFollowing) { throw new ApiError(meta.errors.cannot_find); } } diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts index a14195bbc..10b9acc42 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/push.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts @@ -52,12 +52,14 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { // Fetch the list - const userList = await UserLists.findOneBy({ - id: ps.listId, - userId: me.id, + const userList = await UserLists.exist({ + where: { + id: ps.listId, + userId: me.id, + }, }); - if (userList == null) { + if (!exist) { throw new ApiError(meta.errors.noSuchList); } diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts index 716fd405d..8479a4e03 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/show.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts @@ -37,12 +37,14 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { // Fetch the list - const userList = await UserLists.findOneBy({ - id: ps.listId, - userId: me.id, + const exist = await UserLists.exist({ + where: { + id: ps.listId, + userId: me.id, + }, }); - if (userList == null) { + if (!exist) { throw new ApiError(meta.errors.noSuchList); } diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index 0b52f6912..d14031950 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -22,11 +22,13 @@ export default class extends Channel { this.listId = params.listId as string; // Check existence and owner - const list = await UserLists.findOneBy({ - id: this.listId, - userId: this.user!.id, + const exist = await UserLists.exist({ + where: { + id: this.listId, + userId: this.user!.id, + }, }); - if (!list) return; + if (!exist) return; // Subscribe stream this.subscriber.on(`userListStream:${this.listId}`, this.send); From 23ccb38e73267ec41f47d720a6e933da809267b8 Mon Sep 17 00:00:00 2001 From: naskya <m@naskya.net> Date: Thu, 13 Jul 2023 15:28:44 +0000 Subject: [PATCH 094/162] Stop using the name 'exist' if it's not for existence check --- .../src/remote/activitypub/models/person.ts | 44 +++++++++---------- .../api/endpoints/gallery/posts/unlike.ts | 6 +-- .../src/server/api/endpoints/mute/delete.ts | 6 +-- .../api/endpoints/notes/favorites/delete.ts | 6 +-- .../src/server/api/endpoints/pages/unlike.ts | 6 +-- .../api/endpoints/renote-mute/delete.ts | 6 +-- .../src/server/api/endpoints/sw/register.ts | 10 ++--- .../api/endpoints/sw/show-registration.ts | 10 ++--- .../src/services/note/reaction/delete.ts | 14 +++--- 9 files changed, 53 insertions(+), 55 deletions(-) diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index c5519ba03..14abf3b1d 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -147,11 +147,11 @@ export async function fetchPerson( } //#region Returns if already registered with this server - const exist = await Users.findOneBy({ uri }); + const user = await Users.findOneBy({ uri }); - if (exist) { - await uriPersonCache.set(uri, exist); - return exist; + if (user != null) { + await uriPersonCache.set(uri, user); + return user; } //#endregion @@ -396,9 +396,9 @@ export async function updatePerson( } //#region Already registered on this server? - const exist = (await Users.findOneBy({ uri })) as IRemoteUser; + const user = (await Users.findOneBy({ uri })) as IRemoteUser; - if (exist == null) { + if (user == null) { return; } //#endregion @@ -416,17 +416,15 @@ export async function updatePerson( [person.icon, person.image].map((img) => img == null ? Promise.resolve(null) - : resolveImage(exist, img).catch(() => null), + : resolveImage(user, img).catch(() => null), ), ); // Custom pictogram acquisition - const emojis = await extractEmojis(person.tag || [], exist.host).catch( - (e) => { - logger.info(`extractEmojis: ${e}`); - return [] as Emoji[]; - }, - ); + const emojis = await extractEmojis(person.tag || [], user.host).catch((e) => { + logger.info(`extractEmojis: ${e}`); + return [] as Emoji[]; + }); const emojiNames = emojis.map((emoji) => emoji.name); @@ -518,11 +516,11 @@ export async function updatePerson( } // Update user - await Users.update(exist.id, updates); + await Users.update(user.id, updates); if (person.publicKey) { await UserPublickeys.update( - { userId: exist.id }, + { userId: user.id }, { keyId: person.publicKey.id, keyPem: person.publicKey.publicKeyPem, @@ -531,7 +529,7 @@ export async function updatePerson( } await UserProfiles.update( - { userId: exist.id }, + { userId: user.id }, { url: url, fields, @@ -543,15 +541,15 @@ export async function updatePerson( }, ); - publishInternalEvent("remoteUserUpdated", { id: exist.id }); + publishInternalEvent("remoteUserUpdated", { id: user.id }); // Hashtag Update - updateUsertags(exist, tags); + updateUsertags(user, tags); // If the user in question is a follower, followers will also be updated. await Followings.update( { - followerId: exist.id, + followerId: user.id, }, { followerSharedInbox: @@ -560,7 +558,7 @@ export async function updatePerson( }, ); - await updateFeatured(exist.id, resolver).catch((err) => logger.error(err)); + await updateFeatured(user.id, resolver).catch((err) => logger.error(err)); } /** @@ -576,10 +574,10 @@ export async function resolvePerson( if (typeof uri !== "string") throw new Error("uri is not string"); //#region If already registered on this server, return it. - const exist = await fetchPerson(uri); + const user = await fetchPerson(uri); - if (exist) { - return exist; + if (user != null) { + return user; } //#endregion diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts index 772dc9202..03bc299b9 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts @@ -38,17 +38,17 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.noSuchPost); } - const exist = await GalleryLikes.findOneBy({ + const like = await GalleryLikes.findOneBy({ postId: post.id, userId: user.id, }); - if (exist == null) { + if (like == null) { throw new ApiError(meta.errors.notLiked); } // Delete like - await GalleryLikes.delete(exist.id); + await GalleryLikes.delete(like.id); GalleryPosts.decrement({ id: post.id }, "likedCount", 1); }); diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts index cc67a44c2..cd00c1a8a 100644 --- a/packages/backend/src/server/api/endpoints/mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/mute/delete.ts @@ -56,18 +56,18 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check not muting - const exist = await Mutings.findOneBy({ + const muting = await Mutings.findOneBy({ muterId: muter.id, muteeId: mutee.id, }); - if (exist == null) { + if (muting == null) { throw new ApiError(meta.errors.notMuting); } // Delete mute await Mutings.delete({ - id: exist.id, + id: muting.id, }); publishUserEvent(user.id, "unmute", mutee); diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts index 9a0976748..e05d04a96 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts @@ -42,15 +42,15 @@ export default define(meta, paramDef, async (ps, user) => { }); // if already favorited - const exist = await NoteFavorites.findOneBy({ + const favorite = await NoteFavorites.findOneBy({ noteId: note.id, userId: user.id, }); - if (exist == null) { + if (favorite == null) { throw new ApiError(meta.errors.notFavorited); } // Delete favorite - await NoteFavorites.delete(exist.id); + await NoteFavorites.delete(favorite.id); }); diff --git a/packages/backend/src/server/api/endpoints/pages/unlike.ts b/packages/backend/src/server/api/endpoints/pages/unlike.ts index 07bf3fbf4..e607d7a54 100644 --- a/packages/backend/src/server/api/endpoints/pages/unlike.ts +++ b/packages/backend/src/server/api/endpoints/pages/unlike.ts @@ -38,17 +38,17 @@ export default define(meta, paramDef, async (ps, user) => { throw new ApiError(meta.errors.noSuchPage); } - const exist = await PageLikes.findOneBy({ + const like = await PageLikes.findOneBy({ pageId: page.id, userId: user.id, }); - if (exist == null) { + if (like == null) { throw new ApiError(meta.errors.notLiked); } // Delete like - await PageLikes.delete(exist.id); + await PageLikes.delete(like.id); Pages.decrement({ id: page.id }, "likedCount", 1); }); diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts index fb4c972af..7a898141c 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts @@ -45,18 +45,18 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check not muting - const exist = await RenoteMutings.findOneBy({ + const muting = await RenoteMutings.findOneBy({ muterId: muter.id, muteeId: mutee.id, }); - if (exist == null) { + if (muting == null) { throw new ApiError(meta.errors.notMuting); } // Delete mute await RenoteMutings.delete({ - id: exist.id, + id: muting.id, }); // publishUserEvent(user.id, "unmute", mutee); diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts index 41be4bf74..6268ae26d 100644 --- a/packages/backend/src/server/api/endpoints/sw/register.ts +++ b/packages/backend/src/server/api/endpoints/sw/register.ts @@ -57,8 +57,7 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, me) => { - // if already subscribed - const exist = await SwSubscriptions.findOneBy({ + const subscription = await SwSubscriptions.findOneBy({ userId: me.id, endpoint: ps.endpoint, auth: ps.auth, @@ -67,13 +66,14 @@ export default define(meta, paramDef, async (ps, me) => { const instance = await fetchMeta(true); - if (exist != null) { + // if already subscribed + if (subscription != null) { return { state: "already-subscribed" as const, key: instance.swPublicKey, userId: me.id, - endpoint: exist.endpoint, - sendReadMessage: exist.sendReadMessage, + endpoint: subscription.endpoint, + sendReadMessage: subscription.sendReadMessage, }; } diff --git a/packages/backend/src/server/api/endpoints/sw/show-registration.ts b/packages/backend/src/server/api/endpoints/sw/show-registration.ts index c7a9609cf..3ccb7de94 100644 --- a/packages/backend/src/server/api/endpoints/sw/show-registration.ts +++ b/packages/backend/src/server/api/endpoints/sw/show-registration.ts @@ -42,16 +42,16 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, me) => { - const exist = await SwSubscriptions.findOneBy({ + const subscription = await SwSubscriptions.findOneBy({ userId: me.id, endpoint: ps.endpoint, }); - if (exist != null) { + if (subscription != null) { return { - userId: exist.userId, - endpoint: exist.endpoint, - sendReadMessage: exist.sendReadMessage, + userId: subscription.userId, + endpoint: subscription.endpoint, + sendReadMessage: subscription.sendReadMessage, }; } diff --git a/packages/backend/src/services/note/reaction/delete.ts b/packages/backend/src/services/note/reaction/delete.ts index 82648249e..15c6d1cf6 100644 --- a/packages/backend/src/services/note/reaction/delete.ts +++ b/packages/backend/src/services/note/reaction/delete.ts @@ -13,13 +13,13 @@ export default async ( user: { id: User["id"]; host: User["host"] }, note: Note, ) => { - // if already unreacted - const exist = await NoteReactions.findOneBy({ + const reaction = await NoteReactions.findOneBy({ noteId: note.id, userId: user.id, }); - if (exist == null) { + // if already unreacted + if (reaction == null) { throw new IdentifiableError( "60527ec9-b4cb-4a88-a6bd-32d3ad26817d", "not reacted", @@ -27,7 +27,7 @@ export default async ( } // Delete reaction - const result = await NoteReactions.delete(exist.id); + const result = await NoteReactions.delete(reaction.id); if (result.affected !== 1) { throw new IdentifiableError( @@ -37,7 +37,7 @@ export default async ( } // Decrement reactions count - const sql = `jsonb_set("reactions", '{${exist.reaction}}', (COALESCE("reactions"->>'${exist.reaction}', '0')::int - 1)::text::jsonb)`; + const sql = `jsonb_set("reactions", '{${reaction.reaction}}', (COALESCE("reactions"->>'${reaction.reaction}', '0')::int - 1)::text::jsonb)`; await Notes.createQueryBuilder() .update() .set({ @@ -49,14 +49,14 @@ export default async ( Notes.decrement({ id: note.id }, "score", 1); publishNoteStream(note.id, "unreacted", { - reaction: decodeReaction(exist.reaction).reaction, + reaction: decodeReaction(reaction.reaction).reaction, userId: user.id, }); //#region 配信 if (Users.isLocalUser(user) && !note.localOnly) { const content = renderActivity( - renderUndo(await renderLike(exist, note), user), + renderUndo(await renderLike(reaction, note), user), ); const dm = new DeliverManager(user, content); if (note.userHost !== null) { From 652209e5205887d4bf8cb4fa1bd00998fc12e7a4 Mon Sep 17 00:00:00 2001 From: naskya <m@naskya.net> Date: Thu, 13 Jul 2023 15:31:40 +0000 Subject: [PATCH 095/162] More replacements which aren't covered by f4870d6e --- .../src/server/api/endpoints/following/invalidate.ts | 10 ++++++---- .../src/server/api/endpoints/renote-mute/create.ts | 10 ++++++---- packages/backend/src/services/note/unread.ts | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts index 979d298f7..01ccc2761 100644 --- a/packages/backend/src/server/api/endpoints/following/invalidate.ts +++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts @@ -69,12 +69,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check not following - const exist = await Followings.findOneBy({ - followerId: follower.id, - followeeId: followee.id, + const exist = await Followings.exist({ + where: { + followerId: follower.id, + followeeId: followee.id, + }, }); - if (exist == null) { + if (!exist) { throw new ApiError(meta.errors.notFollowing); } diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts index 857cbd975..f09f197c0 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts @@ -47,12 +47,14 @@ export default define(meta, paramDef, async (ps, user) => { }); // Check if already muting - const exist = await RenoteMutings.findOneBy({ - muterId: muter.id, - muteeId: mutee.id, + const exist = await RenoteMutings.exist({ + where: { + muterId: muter.id, + muteeId: mutee.id, + }, }); - if (exist != null) { + if (exist) { throw new ApiError(meta.errors.alreadyMuting); } diff --git a/packages/backend/src/services/note/unread.ts b/packages/backend/src/services/note/unread.ts index 275b230d4..cb87abe0e 100644 --- a/packages/backend/src/services/note/unread.ts +++ b/packages/backend/src/services/note/unread.ts @@ -42,9 +42,9 @@ export async function insertNoteUnread( // 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する setTimeout(async () => { - const exist = await NoteUnreads.findOneBy({ id: unread.id }); + const exist = await NoteUnreads.exist({ where: { id: unread.id } }); - if (exist == null) return; + if (!exist) return; if (params.isMentioned) { publishMainStream(userId, "unreadMention", note.id); From 9e2443634ceba06a7dcedb71207cadf0f274ebe3 Mon Sep 17 00:00:00 2001 From: naskya <m@naskya.net> Date: Thu, 13 Jul 2023 16:10:13 +0000 Subject: [PATCH 096/162] fix --- .../api/endpoints/i/read-announcement.ts | 12 +++++----- .../server/api/endpoints/users/lists/push.ts | 22 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts index e44445b1b..d0dfa6657 100644 --- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts +++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts @@ -30,7 +30,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Check if announcement exists - const exist = await Announcements.findOneBy({ + const exist = await Announcements.exist({ where: { id: ps.announcementId }, }); @@ -39,12 +39,14 @@ export default define(meta, paramDef, async (ps, user) => { } // Check if already read - const read = await AnnouncementReads.findOneBy({ - announcementId: ps.announcementId, - userId: user.id, + const read = await AnnouncementReads.exist({ + where: { + announcementId: ps.announcementId, + userId: user.id, + }, }); - if (read != null) { + if (read) { return; } diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts index 10b9acc42..6f3e09fcb 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/push.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts @@ -52,14 +52,14 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { // Fetch the list - const userList = await UserLists.exist({ + const listExists = await UserLists.exist({ where: { id: ps.listId, userId: me.id, }, }); - if (!exist) { + if (!listExists) { throw new ApiError(meta.errors.noSuchList); } @@ -72,18 +72,22 @@ export default define(meta, paramDef, async (ps, me) => { // Check blocking if (user.id !== me.id) { - const block = await Blockings.findOneBy({ - blockerId: user.id, - blockeeId: me.id, + const isBlocked = await Blockings.exist({ + where: { + blockerId: user.id, + blockeeId: me.id, + }, }); - if (block) { + if (isBlocked) { throw new ApiError(meta.errors.youHaveBeenBlocked); } } - const exist = await UserListJoinings.findOneBy({ - userListId: userList.id, - userId: user.id, + const exist = await UserListJoinings.exist({ + where: { + userListId: userList.id, + userId: user.id, + }, }); if (exist) { From b9435c9ae1d79d37c8990d205b8e5f25822b6b52 Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Thu, 13 Jul 2023 21:45:54 +0000 Subject: [PATCH 097/162] Fallback language for code MFM should be plaintext --- packages/client/src/components/MkCode.core.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkCode.core.vue b/packages/client/src/components/MkCode.core.vue index 579c6cf1e..00cded283 100644 --- a/packages/client/src/components/MkCode.core.vue +++ b/packages/client/src/components/MkCode.core.vue @@ -18,7 +18,7 @@ const props = defineProps<{ }>(); const prismLang = computed(() => - Prism.languages[props.lang] ? props.lang : "js", + Prism.languages[props.lang] ? props.lang : "plaintext", ); const html = computed(() => Prism.highlight( From 1ed9438972ad67ca57e52b0bf8a07f2f044066f9 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Thu, 13 Jul 2023 19:26:44 -0400 Subject: [PATCH 098/162] style: user card design --- packages/client/src/components/MkUserInfo.vue | 320 +++++++++++++----- 1 file changed, 244 insertions(+), 76 deletions(-) diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index 9c2763e53..9ff5f8b6c 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -1,151 +1,319 @@ <template> - <div class="_panel vjnjpkug"> + <article class="_panel user-card"> <div class="banner" :style=" user.bannerUrl ? `background-image: url(${user.bannerUrl})` : '' " + :class="{ detailed }" ></div> - <MkAvatar - class="avatar" - :user="user" - :disable-preview="true" - :show-indicator="true" - /> - <div class="title"> + <h3 class="title"> + <MkAvatar + class="avatar" + :user="user" + :disable-preview="true" + :show-indicator="true" + /> <MkA class="name" :to="userPage(user)" - ><MkUserName :user="user" :nowrap="false" + ><MkUserName :user="user" :nowrap="true" /></MkA> <p class="username"><MkAcct :user="user" /></p> - </div> - <div class="description"> - <div v-if="user.description" class="mfm"> - <Mfm - :text="user.description" - :author="user" - :i="$i" - :custom-emojis="user.emojis" - /> - </div> + </h3> + <div + class="description" + :class="{ collapsed: isLong && collapsed, truncate: !detailed }" + > + <Mfm + v-if="user.description" + class="mfm" + :text="user.description" + :author="user" + :i="$i" + :custom-emojis="user.emojis" + /> <span v-else style="opacity: 0.7">{{ i18n.ts.noAccountDescription }}</span> </div> + <XShowMoreButton + v-if="isLong" + v-model="collapsed" + ></XShowMoreButton> + <div v-if="user.fields.length > 0 && detailed" class="fields"> + <dl + v-for="(field, i) in user.fields" + :key="i" + class="field" + > + <dt class="name"> + <Mfm + :text="field.name" + :plain="true" + :custom-emojis="user.emojis" + :colored="false" + /> + </dt> + <dd class="value"> + <Mfm + :text="field.value" + :author="user" + :i="$i" + :custom-emojis="user.emojis" + :colored="false" + /> + </dd> + </dl> + </div> <div class="status"> - <div> - <p>{{ i18n.ts.notes }}</p> + <p> <MkNumber :value="user.notesCount" /> - </div> - <div> - <p>{{ i18n.ts.following }}</p> + {{ i18n.ts.notes }} + </p> + <p> <MkNumber :value="user.followingCount" /> - </div> - <div> - <p>{{ i18n.ts.followers }}</p> + {{ i18n.ts.following }} + </p> + <p> <MkNumber :value="user.followersCount" /> - </div> + {{ i18n.ts.followers }} + </p> </div> - <div class="koudoku-button"> - <MkFollowButton v-if="$i && user.id != $i.id" :user="user" /> + <div class="buttons"> + <slot> + <MkFollowButton v-if="$i && user.id != $i.id" :user="user" /> + </slot> </div> - </div> + </article> </template> <script lang="ts" setup> import * as misskey from "calckey-js"; import MkFollowButton from "@/components/MkFollowButton.vue"; +import XShowMoreButton from "@/components/MkShowMoreButton.vue"; import MkNumber from "@/components/MkNumber.vue"; import { userPage } from "@/filters/user"; import { i18n } from "@/i18n"; -defineProps<{ +const props = defineProps<{ user: misskey.entities.UserDetailed; + detailed?: boolean; }>(); + +let isLong = $ref( + props.detailed && + ( + props.user.description.split("\n").length > 9 || + props.user.description.length > 400 + ) +); +let collapsed = $ref(isLong); </script> <style lang="scss" scoped> -.vjnjpkug { +.user-card { position: relative; + display: flex; + flex-direction: column; - > .banner { - height: 84px; + .banner { + height: 94px; background-color: rgba(0, 0, 0, 0.1); background-size: cover; background-position: center; + margin-bottom: calc(0px - var(--radius)); + &::before { + content: ""; + position: absolute; + inset: 0; + z-index: 2; + height: inherit; + background: linear-gradient( + -125deg, + rgba(0, 0, 0, 0.7), + transparent, + transparent + ); + } + &.detailed::after { + content: ""; + background-image: var(--blur, inherit); + position: fixed; + inset: 0; + background-size: cover; + background-position: center; + pointer-events: none; + opacity: 0.1; + filter: var(--blur, blur(10px)); + z-index: 5; + } } - > .avatar { + + .title { + position: relative; display: block; - position: absolute; - top: 62px; - left: 13px; - z-index: 2; - width: 58px; - height: 58px; - border: solid 4px var(--panel); - } - - > .title { - display: block; - padding: 10px 0 10px 88px; - - > .name { + padding: 10px 10px 10px 84px; + margin: 0; + font-size: 1em; + border-radius: var(--radius); + background: var(--panel); + line-height: 1; + z-index: 4; + + .avatar { + display: block; + position: absolute; + bottom: 6px; + left: 10px; + z-index: 2; + width: 58px; + height: 58px; + background: var(--panel); + border: solid 4px var(--panel); + } + .name { display: inline-block; margin: 0; font-weight: bold; line-height: 16px; - word-break: break-all; + overflow: hidden; + text-overflow: ellipsis; + height: 1.5em; + margin-block: -0.5em; + padding-block: 0.5em 0.25em; + max-width: 100%; } - > .username { + .username { display: block; margin: 0; line-height: 16px; font-size: 0.8em; color: var(--fg); + font-weight: 500; opacity: 0.7; + line-height: 1; } } - > .description { - padding: 16px; + .description { + overflow: hidden; + padding-inline: 16px; + margin-bottom: 10px; font-size: 0.8em; - border-top: solid 0.5px var(--divider); - - > .mfm { + &.truncate { display: -webkit-box; - -webkit-line-clamp: 3; + -webkit-line-clamp: 6; -webkit-box-orient: vertical; - overflow: hidden; + } + &.collapsed { + position: relative; + max-height: calc(9em + 50px); + mask: linear-gradient(black calc(100% - 64px), transparent); + -webkit-mask: linear-gradient( + black calc(100% - 64px), + transparent + ); + } + &.collapsed, &.truncate { + :deep(br) { + display: none; // collapse white spaces + } } } - - > .status { - padding: 10px 16px; - border-top: solid 0.5px var(--divider); - - > div { + :deep(.fade) { + position: relative; + display: block; + width: 100%; + margin-top: -4.5em; + z-index: 2; + > span { display: inline-block; - width: 33%; - - > p { - margin: 0; - font-size: 0.7em; - color: var(--fg); - } - + background: var(--panel); + padding: 0.4em 1em; + font-size: 0.8em; + border-radius: 999px; + box-shadow: 0 2px 6px rgb(0 0 0 / 20%); + } + &:hover { > span { - font-size: 1em; - color: var(--accent); + background: var(--panelHighlight); } } } + :deep(.showLess) { + width: 100%; + position: sticky; + bottom: var(--stickyBottom); - > .koudoku-button { + > span { + display: inline-block; + background: var(--panel); + padding: 6px 10px; + font-size: 0.8em; + border-radius: 999px; + box-shadow: 0 0 7px 7px var(--bg); + } + } + > .fields { + padding-inline: 16px; + font-size: 0.8em; + padding-block: 1em; + border-top: 1px solid var(--divider); + + > .field { + display: flex; + padding: 0; + margin: 0; + align-items: center; + + &:not(:last-child) { + margin-bottom: 8px; + } + + :deep(span) { + white-space: nowrap !important; + } + + > .name { + width: 30%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-weight: bold; + text-align: center; + padding-right: 10px; + } + + > .value { + width: 70%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0; + } + } + } + .status { + display: flex; + gap: 1em; + padding-inline: 16px; + font-size: 0.8em; + margin-top: auto; + border-top: 1px solid var(--divider); + > p > :deep(span) { + font-weight: 700; + color: var(--accent); + } + } + + .buttons { position: absolute; top: 8px; right: 8px; margin-bottom: 1rem; + z-index: 3; + color: white; } } </style> From f26f70413965fb06feaade7112f66758955c78b8 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Thu, 13 Jul 2023 19:27:00 -0400 Subject: [PATCH 099/162] refactor: use new card design in user popup --- .../client/src/components/MkUserPreview.vue | 303 +----------------- 1 file changed, 2 insertions(+), 301 deletions(-) diff --git a/packages/client/src/components/MkUserPreview.vue b/packages/client/src/components/MkUserPreview.vue index 6c3838fd2..60a91c11b 100644 --- a/packages/client/src/components/MkUserPreview.vue +++ b/packages/client/src/components/MkUserPreview.vue @@ -19,96 +19,7 @@ } " > - <div v-if="user != null" class="info"> - <div - class="banner" - :style=" - user.bannerUrl - ? `background-image: url(${user.bannerUrl})` - : '' - " - > - <span - v-if="$i && $i.id != user.id && user.isFollowed" - class="followed" - >{{ i18n.ts.followsYou }}</span - > - </div> - <MkAvatar - class="avatar" - :user="user" - :disable-preview="true" - :show-indicator="true" - /> - <div class="title"> - <MkA class="name" :to="userPage(user)" - ><MkUserName :user="user" :nowrap="true" - /></MkA> - <p class="username"><MkAcct :user="user" /></p> - </div> - <div - class="description" - :class="{ collapsed: isLong && collapsed }" - > - <Mfm - v-if="user.description" - :text="user.description" - :author="user" - :i="$i" - :custom-emojis="user.emojis" - /> - </div> - <XShowMoreButton - v-if="isLong" - v-model="collapsed" - ></XShowMoreButton> - <div v-if="user.fields.length > 0" class="fields"> - <dl - v-for="(field, i) in user.fields" - :key="i" - class="field" - > - <dt class="name"> - <Mfm - :text="field.name" - :plain="true" - :custom-emojis="user.emojis" - :colored="false" - /> - </dt> - <dd class="value"> - <Mfm - :text="field.value" - :author="user" - :i="$i" - :custom-emojis="user.emojis" - :colored="false" - /> - </dd> - </dl> - </div> - <div class="status"> - <div> - <p>{{ i18n.ts.notes }}</p> - <span>{{ user.notesCount }}</span> - </div> - <div> - <p>{{ i18n.ts.following }}</p> - <span>{{ user.followingCount }}</span> - </div> - <div> - <p>{{ i18n.ts.followers }}</p> - <span>{{ user.followersCount }}</span> - </div> - </div> - <div class="follow-button-container"> - <MkFollowButton - v-if="$i && user.id != $i.id" - :user="user" - mini - /> - </div> - </div> + <MkUserInfo v-if="user != null" :user="user" :detailed="true" /> <div v-else> <MkLoading /> </div> @@ -118,14 +29,10 @@ <script lang="ts" setup> import { onMounted } from "vue"; +import MkUserInfo from "@/components/MkUserInfo.vue"; import * as Acct from "calckey-js/built/acct"; import type * as misskey from "calckey-js"; -import MkFollowButton from "@/components/MkFollowButton.vue"; -import { userPage } from "@/filters/user"; -import XShowMoreButton from "@/components/MkShowMoreButton.vue"; import * as os from "@/os"; -import { $i } from "@/account"; -import { i18n } from "@/i18n"; const props = defineProps<{ showing: boolean; @@ -144,15 +51,9 @@ let user = $ref<misskey.entities.UserDetailed | null>(null); let top = $ref(0); let left = $ref(0); -let isLong = $ref(false); -let collapsed = $ref(!isLong); - onMounted(() => { if (typeof props.q === "object") { user = props.q; - isLong = - user.description.split("\n").length > 9 || - user.description.length > 400; } else { const query = props.q.startsWith("@") ? Acct.parse(props.q.substr(1)) @@ -161,9 +62,6 @@ onMounted(() => { os.api("users/show", query).then((res) => { if (!props.showing) return; user = res; - isLong = - user.description.split("\n").length > 9 || - user.description.length > 400; }); } @@ -196,202 +94,5 @@ onMounted(() => { overflow: hidden; transform-origin: center top; - > .info { - > .banner { - height: 84px; - background-color: rgba(0, 0, 0, 0.1); - background-size: cover; - background-position: center; - > .followed { - position: absolute; - top: 12px; - left: 12px; - padding: 4px 8px; - color: #fff; - background: rgba(0, 0, 0, 0.7); - font-size: 0.7em; - border-radius: 6px; - } - - &::before { - content: ""; - position: absolute; - inset: 0; - z-index: 2; - height: 84px; - background: linear-gradient( - -125deg, - rgba(0, 0, 0, 0.7), - transparent, - transparent - ); - } - - &::after { - content: ""; - background-image: var(--blur, inherit); - position: fixed; - inset: 0; - background-size: cover; - background-position: center; - pointer-events: none; - opacity: 0.1; - filter: var(--blur, blur(10px)); - } - } - - > .avatar { - display: block; - position: absolute; - top: 70px; - left: 13px; - z-index: 2; - width: 58px; - height: 58px; - border: solid 3px var(--face); - border-radius: 8px; - } - - > .title { - display: block; - padding: 8px 0 8px 82px; - - > .name { - display: inline-block; - margin: 0; - font-weight: bold; - line-height: 16px; - word-break: break-all; - } - - > .username { - display: block; - margin: 0; - line-height: 16px; - font-size: 0.8em; - color: var(--fg); - opacity: 0.7; - } - } - - > .description { - padding: 0 16px; - font-size: 0.8em; - color: var(--fg); - &.collapsed { - position: relative; - max-height: calc(9em + 50px); - mask: linear-gradient(black calc(100% - 64px), transparent); - -webkit-mask: linear-gradient( - black calc(100% - 64px), - transparent - ); - } - } - :deep(.fade) { - position: relative; - display: block; - width: 100%; - margin-top: -2.5em; - z-index: 2; - > span { - display: inline-block; - background: var(--panel); - padding: 0.4em 1em; - font-size: 0.8em; - border-radius: 999px; - box-shadow: 0 2px 6px rgb(0 0 0 / 20%); - } - &:hover { - > span { - background: var(--panelHighlight); - } - } - } - :deep(.showLess) { - width: 100%; - margin-top: 1em; - position: sticky; - bottom: var(--stickyBottom); - - > span { - display: inline-block; - background: var(--panel); - padding: 6px 10px; - font-size: 0.8em; - border-radius: 999px; - box-shadow: 0 0 7px 7px var(--bg); - } - } - - > .fields { - padding: 0 16px; - font-size: 0.8em; - margin-top: 1em; - - > .field { - display: flex; - padding: 0; - margin: 0; - align-items: center; - - &:not(:last-child) { - margin-bottom: 8px; - } - - :deep(span) { - white-space: nowrap !important; - } - - > .name { - width: 30%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-weight: bold; - text-align: center; - } - - > .value { - width: 70%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 0; - } - } - } - - > .status { - padding: 8px 16px; - - > div { - display: inline-block; - width: 33%; - - > p { - margin: 0; - font-size: 0.7em; - color: var(--fg); - } - - > span { - font-size: 1em; - color: var(--accent); - :deep(span) { - white-space: nowrap; - } - } - } - } - - > .follow-button-container { - position: absolute; - top: 8px; - right: 8px; - z-index: 3; - color: white; - } - } } </style> From 450eae74c18d12e0a15a65f531b322b6fc0b8fdd Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Thu, 13 Jul 2023 19:30:22 -0400 Subject: [PATCH 100/162] chore: format --- packages/client/src/components/MkUserInfo.vue | 30 ++++++------------- .../client/src/components/MkUserPreview.vue | 1 - 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index 9ff5f8b6c..ad3602330 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -19,7 +19,7 @@ /></MkA> <p class="username"><MkAcct :user="user" /></p> </h3> - <div + <div class="description" :class="{ collapsed: isLong && collapsed, truncate: !detailed }" > @@ -35,16 +35,9 @@ i18n.ts.noAccountDescription }}</span> </div> - <XShowMoreButton - v-if="isLong" - v-model="collapsed" - ></XShowMoreButton> + <XShowMoreButton v-if="isLong" v-model="collapsed"></XShowMoreButton> <div v-if="user.fields.length > 0 && detailed" class="fields"> - <dl - v-for="(field, i) in user.fields" - :key="i" - class="field" - > + <dl v-for="(field, i) in user.fields" :key="i" class="field"> <dt class="name"> <Mfm :text="field.name" @@ -101,10 +94,8 @@ const props = defineProps<{ let isLong = $ref( props.detailed && - ( - props.user.description.split("\n").length > 9 || - props.user.description.length > 400 - ) + (props.user.description.split("\n").length > 9 || + props.user.description.length > 400), ); let collapsed = $ref(isLong); </script> @@ -148,7 +139,6 @@ let collapsed = $ref(isLong); } } - .title { position: relative; display: block; @@ -159,7 +149,7 @@ let collapsed = $ref(isLong); background: var(--panel); line-height: 1; z-index: 4; - + .avatar { display: block; position: absolute; @@ -210,12 +200,10 @@ let collapsed = $ref(isLong); position: relative; max-height: calc(9em + 50px); mask: linear-gradient(black calc(100% - 64px), transparent); - -webkit-mask: linear-gradient( - black calc(100% - 64px), - transparent - ); + -webkit-mask: linear-gradient(black calc(100% - 64px), transparent); } - &.collapsed, &.truncate { + &.collapsed, + &.truncate { :deep(br) { display: none; // collapse white spaces } diff --git a/packages/client/src/components/MkUserPreview.vue b/packages/client/src/components/MkUserPreview.vue index 60a91c11b..894e3dfb8 100644 --- a/packages/client/src/components/MkUserPreview.vue +++ b/packages/client/src/components/MkUserPreview.vue @@ -93,6 +93,5 @@ onMounted(() => { width: 300px; overflow: hidden; transform-origin: center top; - } </style> From d9d8cb31cf648b33102fbf3930d1a7876388668d Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Thu, 13 Jul 2023 19:32:35 -0400 Subject: [PATCH 101/162] fix: collapsing white space --- packages/client/src/components/MkUserInfo.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index ad3602330..55979a229 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -205,7 +205,7 @@ let collapsed = $ref(isLong); &.collapsed, &.truncate { :deep(br) { - display: none; // collapse white spaces + display: block; // collapse white spaces } } } From dbb9c3d248710b74e6ac9b2c17cad858183c3331 Mon Sep 17 00:00:00 2001 From: okayurisotto <aytkzm@gmail.com> Date: Wed, 12 Apr 2023 01:07:24 +0900 Subject: [PATCH 102/162] Refactor sw (#10579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(sw): remove dead code * refactor(sw): remove dead code * refactor(sw): remove dead code * refactor(sw): remove dead code * refactor(sw): remove dead code * refactor(sw): remove dead code * refactor(sw): 冗長な部分を変更 * refactor(sw): 使われていない煩雑な機能を削除 * refactor(sw): remove dead code * refactor(sw): URL文字列の作成に`URL`を使うように * refactor(sw): 型アサーションの削除とそれに伴い露呈したエラーへの対処 * refactor(sw): `append` -> `set` in `URLSearchParams` * refactor(sw): `any`の削除とそれに伴い露呈したエラーへの対処 * refactor(sw): 型アサーションの削除とそれに伴い露呈したエラーへの対処 対処と言っても`throw`するだけ。いままでもこの状況ではエラーが投げられていたはずなので、この対処により新たな問題が起きることはないはず。 * refactor(sw): i18n loading * refactor(sw): 型推論がうまくできる書き方に変更 `codes`が`(string | undefined)[]`から`string[]`になった * refactor(sw): クエリ文字列の作成に`URLSearchParams`を使うように * refactor(sw): `findClient` * refactor(sw): `openClient`における`any`や`as`の書き換え * refactor(sw): `openPost`における`any`の書き換え * refactor(sw): `let` -> `const` * refactor(sw): `any` -> `unknown` * cleanup(sw): import * cleanup(sw) * cleanup(sw): `?.` * cleanup(sw/.eslintrc.js) * refactor(sw): `@typescript-eslint/explicit-function-return-type` * refactor(sw): `@typescript-eslint/no-unused-vars` * refactor(sw): どうしようもないところに`eslint-disable-next-line`を * refactor(sw): `import/no-default-export` * update operations.ts * throw new Error --------- Co-authored-by: tamaina <tamaina@hotmail.co.jp> Co-authored-by: Kainoa kanter <kainoa@t1c.dev> --- packages/sw/src/@types/global.d.ts | 8 + packages/sw/src/filters/user.ts | 14 -- .../sw/src/scripts/create-notification.ts | 85 +++---- .../sw/src/scripts/get-account-from-id.ts | 11 +- packages/sw/src/scripts/get-user-name.ts | 4 +- packages/sw/src/scripts/i18n.ts | 7 +- packages/sw/src/scripts/lang.ts | 20 +- packages/sw/src/scripts/login-id.ts | 10 +- packages/sw/src/scripts/operations.ts | 112 +++++---- packages/sw/src/scripts/twemoji-base.ts | 12 +- packages/sw/src/scripts/url.ts | 15 -- packages/sw/src/sw.ts | 224 +++++++++--------- packages/sw/src/types.ts | 41 +++- 13 files changed, 291 insertions(+), 272 deletions(-) create mode 100644 packages/sw/src/@types/global.d.ts delete mode 100644 packages/sw/src/filters/user.ts delete mode 100644 packages/sw/src/scripts/url.ts diff --git a/packages/sw/src/@types/global.d.ts b/packages/sw/src/@types/global.d.ts new file mode 100644 index 000000000..a7d176b0b --- /dev/null +++ b/packages/sw/src/@types/global.d.ts @@ -0,0 +1,8 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type FIXME = any; + +declare const _LANGS_: string[][]; +declare const _VERSION_: string; +declare const _ENV_: string; +declare const _DEV_: boolean; +declare const _PERF_PREFIX_: string; diff --git a/packages/sw/src/filters/user.ts b/packages/sw/src/filters/user.ts deleted file mode 100644 index 782194d16..000000000 --- a/packages/sw/src/filters/user.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as misskey from "calckey-js"; -import * as Acct from "calckey-js/built/acct"; - -export const acct = (user: misskey.Acct) => { - return Acct.toString(user); -}; - -export const userName = (user: misskey.entities.User) => { - return user.name || user.username; -}; - -export const userPage = (user: misskey.Acct, path?, absolute = false) => { - return `${absolute ? origin : ""}/@${acct(user)}${path ? `/${path}` : ""}`; -}; diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 03ce2a60d..12d76aabf 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -1,23 +1,36 @@ /* * Notification manager for SW */ -declare let self: ServiceWorkerGlobalScope; - -import { swLang } from "@/scripts/lang"; -import { cli } from "@/scripts/operations"; -import { pushNotificationDataMap } from "@/types"; -import getUserName from "@/scripts/get-user-name"; -import { I18n } from "@/scripts/i18n"; -import { getAccountFromId } from "@/scripts/get-account-from-id"; +import type { BadgeNames, PushNotificationDataMap } from "@/types"; import { char2fileName } from "@/scripts/twemoji-base"; -import * as url from "@/scripts/url"; +import { cli } from "@/scripts/operations"; +import { getAccountFromId } from "@/scripts/get-account-from-id"; +import { swLang } from "@/scripts/lang"; +import { getUserName } from "@/scripts/get-user-name"; -const iconUrl = (name: string) => - `/static-assets/notification-badges/${name}.png`; +const closeNotificationsByTags = async (tags: string[]): Promise<void> => { + for (const n of ( + await Promise.all( + tags.map((tag) => globalThis.registration.getNotifications({ tag })), + ) + ).flat()) { + n.close(); + } +}; + +const iconUrl = (name: BadgeNames): string => + `/static-assets/tabler-badges/${name}.png`; +/* How to add a new badge: + * 1. Find the icon and download png from https://tabler-icons.io/ + * 2. vips resize ~/Downloads/icon-name.png vipswork.png 0.4; vips scRGB2BW vipswork.png ~/icon-name.png"[compression=9,strip]"; rm vipswork.png; + * 3. mv ~/icon-name.png ~/misskey/packages/backend/assets/tabler-badges/ + * 4. Add 'icon-name' to BadgeNames + * 5. Add `badge: iconUrl('icon-name'),` + */ export async function createNotification< - K extends keyof pushNotificationDataMap, ->(data: pushNotificationDataMap[K]) { + K extends keyof PushNotificationDataMap, +>(data: PushNotificationDataMap[K]): Promise<void> { const n = await composeNotification(data); if (n) { @@ -28,11 +41,10 @@ export async function createNotification< } } -async function composeNotification<K extends keyof pushNotificationDataMap>( - data: pushNotificationDataMap[K], +async function composeNotification( + data: PushNotificationDataMap[keyof PushNotificationDataMap], ): Promise<[string, NotificationOptions] | null> { - if (!swLang.i18n) swLang.fetchLocale(); - const i18n = (await swLang.i18n) as I18n<any>; + const i18n = await (swLang.i18n ?? swLang.fetchLocale()); const { t } = i18n; switch (data.type) { /* @@ -164,38 +176,20 @@ async function composeNotification<K extends keyof pushNotificationDataMap>( if (reaction.startsWith(":")) { // カスタム絵文字の場合 - const customEmoji = data.body.note.emojis.find( - (x) => x.name === reaction.substr(1, reaction.length - 2), - ); - if (customEmoji) { - if (reaction.includes("@")) { - reaction = `:${reaction.substr(1, reaction.indexOf("@") - 1)}:`; - } - - const u = new URL(customEmoji.url); - if (u.href.startsWith(`${origin}/proxy/`)) { - // もう既にproxyっぽそうだったらsearchParams付けるだけ - u.searchParams.set("badge", "1"); - badge = u.href; - } else { - const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので - badge = `${origin}/proxy/${dummy}?${url.query({ - url: u.href, - badge: "1", - })}`; - } - } + const name = reaction.substring(1, reaction.length - 1); + const badgeUrl = new URL(`/emoji/${name}.webp`, origin); + badgeUrl.searchParams.set("badge", "1"); + badge = badgeUrl.href; + reaction = name.split("@")[0]; } else { // Unicode絵文字の場合 badge = `/twemoji-badge/${char2fileName(reaction)}.png`; } if ( - badge - ? await fetch(badge) - .then((res) => res.status !== 200) - .catch(() => true) - : true + await fetch(badge) + .then((res) => res.status !== 200) + .catch(() => true) ) { badge = iconUrl("plus"); } @@ -339,10 +333,9 @@ async function composeNotification<K extends keyof pushNotificationDataMap>( } } -export async function createEmptyNotification() { +export async function createEmptyNotification(): Promise<void> { return new Promise<void>(async (res) => { - if (!swLang.i18n) swLang.fetchLocale(); - const i18n = (await swLang.i18n) as I18n<any>; + const i18n = await (swLang.i18n ?? swLang.fetchLocale()); const { t } = i18n; await self.registration.showNotification( diff --git a/packages/sw/src/scripts/get-account-from-id.ts b/packages/sw/src/scripts/get-account-from-id.ts index 24f5e590e..dfcb08d0e 100644 --- a/packages/sw/src/scripts/get-account-from-id.ts +++ b/packages/sw/src/scripts/get-account-from-id.ts @@ -1,7 +1,12 @@ import { get } from "idb-keyval"; -export async function getAccountFromId(id: string) { - const accounts = (await get("accounts")) as { token: string; id: string }[]; - if (!accounts) console.log("Accounts are not recorded"); +export async function getAccountFromId( + id: string, +): Promise<{ token: string; id: string } | void> { + const accounts = await get<{ token: string; id: string }[]>("accounts"); + if (!accounts) { + console.log("Accounts are not recorded"); + return; + } return accounts.find((e) => e.id === id); } diff --git a/packages/sw/src/scripts/get-user-name.ts b/packages/sw/src/scripts/get-user-name.ts index 0f8916de8..b0a87d9b8 100644 --- a/packages/sw/src/scripts/get-user-name.ts +++ b/packages/sw/src/scripts/get-user-name.ts @@ -1,6 +1,6 @@ -export default function (user: { +export function getUserName(user: { name?: string | null; username: string; }): string { - return user.name || user.username; + return user.name === "" ? user.username : user.name ?? user.username; } diff --git a/packages/sw/src/scripts/i18n.ts b/packages/sw/src/scripts/i18n.ts index 06fe83f31..71ac9e7b0 100644 --- a/packages/sw/src/scripts/i18n.ts +++ b/packages/sw/src/scripts/i18n.ts @@ -1,4 +1,6 @@ -export class I18n<T extends Record<string, any>> { +export type Locale = { [key: string]: string | Locale }; + +export class I18n<T extends Locale = Locale> { public ts: T; constructor(locale: T) { @@ -15,7 +17,8 @@ export class I18n<T extends Record<string, any>> { try { let str = key .split(".") - .reduce((o, i) => o[i], this.ts) as unknown as string; + .reduce<Locale | Locale[keyof Locale]>((o, i) => o[i], this.ts); + if (typeof str !== "string") throw new Error(); if (args) { for (const [k, v] of Object.entries(args)) { diff --git a/packages/sw/src/scripts/lang.ts b/packages/sw/src/scripts/lang.ts index 31cfb7bd3..bdfc25ef6 100644 --- a/packages/sw/src/scripts/lang.ts +++ b/packages/sw/src/scripts/lang.ts @@ -1,10 +1,8 @@ /* * Language manager for SW */ -declare let self: ServiceWorkerGlobalScope; - import { get, set } from "idb-keyval"; -import { I18n } from "@/scripts/i18n"; +import { I18n, type Locale } from "@/scripts/i18n"; class SwLang { public cacheName = `mk-cache-${_VERSION_}`; @@ -14,19 +12,19 @@ class SwLang { return prelang; }); - public setLang(newLang: string) { + public setLang(newLang: string): Promise<I18n<Locale>> { this.lang = Promise.resolve(newLang); set("lang", newLang); return this.fetchLocale(); } - public i18n: Promise<I18n<any>> | null = null; + public i18n: Promise<I18n> | null = null; - public fetchLocale() { - return this.i18n === this._fetch(); + public fetchLocale(): Promise<I18n<Locale>> { + return (this.i18n = this._fetch()); } - private async _fetch() { + private async _fetch(): Promise<I18n<Locale>> { // Service Workerは何度も起動しそのたびにlocaleを読み込むので、CacheStorageを使う const localeUrl = `/assets/locales/${await this.lang}.${_VERSION_}.json`; let localeRes = await caches.match(localeUrl); @@ -34,13 +32,13 @@ class SwLang { // _DEV_がtrueの場合は常に最新化 if (!localeRes || _DEV_) { localeRes = await fetch(localeUrl); - const clone = localeRes?.clone(); - if (!clone?.clone().ok) Error("locale fetching error"); + const clone = localeRes.clone(); + if (!clone.clone().ok) throw new Error("locale fetching error"); caches.open(this.cacheName).then((cache) => cache.put(localeUrl, clone)); } - return new I18n(await localeRes.json()); + return new I18n<Locale>(await localeRes.json()); } } diff --git a/packages/sw/src/scripts/login-id.ts b/packages/sw/src/scripts/login-id.ts index 0fe345780..773b01536 100644 --- a/packages/sw/src/scripts/login-id.ts +++ b/packages/sw/src/scripts/login-id.ts @@ -1,11 +1,5 @@ -export function getUrlWithLoginId(url: string, loginId: string) { +export function getUrlWithLoginId(url: string, loginId: string): string { const u = new URL(url, origin); - u.searchParams.append("loginId", loginId); - return u.toString(); -} - -export function getUrlWithoutLoginId(url: string) { - const u = new URL(url); - u.searchParams.delete("loginId"); + u.searchParams.set("loginId", loginId); return u.toString(); } diff --git a/packages/sw/src/scripts/operations.ts b/packages/sw/src/scripts/operations.ts index ae76d6ecf..74d1b053e 100644 --- a/packages/sw/src/scripts/operations.ts +++ b/packages/sw/src/scripts/operations.ts @@ -2,69 +2,100 @@ * Operations * 各種操作 */ -declare let self: ServiceWorkerGlobalScope; - import * as Misskey from "calckey-js"; -import { SwMessage, swMessageOrderType } from "@/types"; -import { acct as getAcct } from "@/filters/user"; +import type { SwMessage, SwMessageOrderType } from "@/types"; import { getAccountFromId } from "@/scripts/get-account-from-id"; import { getUrlWithLoginId } from "@/scripts/login-id"; export const cli = new Misskey.api.APIClient({ origin, - fetch: (...args) => fetch(...args), + fetch: (...args): Promise<Response> => fetch(...args), }); -export async function api<E extends keyof Misskey.Endpoints>( +export async function api< + E extends keyof Misskey.Endpoints, + O extends Misskey.Endpoints[E]["req"], +>( endpoint: E, - userId: string, - options?: Misskey.Endpoints[E]["req"], -) { - const account = await getAccountFromId(userId); - if (!account) return; + userId?: string, + options?: O, +): Promise<void | ReturnType<typeof cli.request<E, O>>> { + let account: { token: string; id: string } | void; - return cli.request(endpoint, options, account.token); + if (userId) { + account = await getAccountFromId(userId); + if (!account) return; + } + + return cli.request(endpoint, options, account?.token); +} + +// mark-all-as-read送出を1秒間隔に制限する +const readBlockingStatus = new Map<string, boolean>(); +export function sendMarkAllAsRead( + userId: string, +): Promise<null | undefined | void> { + if (readBlockingStatus.get(userId)) return Promise.resolve(); + readBlockingStatus.set(userId, true); + return new Promise((resolve) => { + setTimeout(() => { + readBlockingStatus.set(userId, false); + api("notifications/mark-all-as-read", userId).then(resolve, resolve); + }, 1000); + }); } // rendered acctからユーザーを開く -export function openUser(acct: string, loginId: string) { +export function openUser( + acct: string, + loginId?: string, +): ReturnType<typeof openClient> { return openClient("push", `/@${acct}`, loginId, { acct }); } // noteIdからノートを開く -export function openNote(noteId: string, loginId: string) { +export function openNote( + noteId: string, + loginId?: string, +): ReturnType<typeof openClient> { return openClient("push", `/notes/${noteId}`, loginId, { noteId }); } -export async function openChat(body: any, loginId: string) { - if (body.groupId === null) { - return openClient("push", `/my/messaging/${getAcct(body.user)}`, loginId, { - body, - }); - } else { - return openClient("push", `/my/messaging/group/${body.groupId}`, loginId, { - body, - }); - } +// noteIdからノートを開く +export function openAntenna( + antennaId: string, + loginId: string, +): ReturnType<typeof openClient> { + return openClient("push", `/timeline/antenna/${antennaId}`, loginId, { + antennaId, + }); } // post-formのオプションから投稿フォームを開く -export async function openPost(options: any, loginId: string) { +export async function openPost( + options: { + initialText?: string; + reply?: Misskey.entities.Note; + renote?: Misskey.entities.Note; + }, + loginId?: string, +): ReturnType<typeof openClient> { // クエリを作成しておく - let url = "/share?"; - if (options.initialText) url += `text=${options.initialText}&`; - if (options.reply) url += `replyId=${options.reply.id}&`; - if (options.renote) url += `renoteId=${options.renote.id}&`; + const url = "/share"; + const query = new URLSearchParams(); + if (options.initialText) query.set("text", options.initialText); + if (options.reply) query.set("replyId", options.reply.id); + if (options.renote) query.set("renoteId", options.renote.id); - return openClient("post", url, loginId, { options }); + return openClient("post", `${url}?${query}`, loginId, { options }); } export async function openClient( - order: swMessageOrderType, + order: SwMessageOrderType, url: string, - loginId: string, - query: any = {}, -) { + loginId?: string, + query: Record<string, SwMessage[string]> = {}, +): Promise<WindowClient | null> { const client = await findClient(); if (client) { @@ -74,19 +105,16 @@ export async function openClient( order, loginId, url, - } as SwMessage); + } satisfies SwMessage); return client; } - return self.clients.openWindow(getUrlWithLoginId(url, loginId)); + return self.clients.openWindow(getUrlWithLoginId(url, loginId!)); } -export async function findClient() { - const clients = await self.clients.matchAll({ +export async function findClient(): Promise<WindowClient | null> { + const clients = await globalThis.clients.matchAll({ type: "window", }); - for (const c of clients) { - if (c.url.indexOf("?zen") < 0) return c; - } - return null; + return clients.find((c) => !new URL(c.url).searchParams.has("zen")) ?? null; } diff --git a/packages/sw/src/scripts/twemoji-base.ts b/packages/sw/src/scripts/twemoji-base.ts index 0e45a527e..ca35befdc 100644 --- a/packages/sw/src/scripts/twemoji-base.ts +++ b/packages/sw/src/scripts/twemoji-base.ts @@ -1,12 +1,8 @@ -export const twemojiSvgBase = "/twemoji"; - export function char2fileName(char: string): string { - let codes = Array.from(char).map((x) => x.codePointAt(0)?.toString(16)); + let codes = Array.from(char) + .map((x) => x.codePointAt(0)?.toString(16)) + .filter(<T>(x: T | undefined): x is T => x !== undefined); if (!codes.includes("200d")) codes = codes.filter((x) => x !== "fe0f"); - codes = codes.filter((x) => x?.length); + codes = codes.filter((x) => x.length !== 0); return codes.join("-"); } - -export function char2filePath(char: string): string { - return `${twemojiSvgBase}/${char2fileName(char)}.svg`; -} diff --git a/packages/sw/src/scripts/url.ts b/packages/sw/src/scripts/url.ts deleted file mode 100644 index a11f5e28b..000000000 --- a/packages/sw/src/scripts/url.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function query(obj: {}): string { - const params = Object.entries(obj) - .filter(([, v]) => (Array.isArray(v) ? v.length : v !== undefined)) - .reduce((a, [k, v]) => ((a[k] = v), a), {} as Record<string, any>); - - return Object.entries(params) - .map((e) => `${e[0]}=${encodeURIComponent(e[1])}`) - .join("&"); -} - -export function appendQuery(url: string, query: string): string { - return `${url}${ - /\?/.test(url) ? (url.endsWith("?") ? "" : "&") : "?" - }${query}`; -} diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index 74603d67c..6a2ba3bf1 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -1,20 +1,18 @@ -declare let self: ServiceWorkerGlobalScope; - +import { get } from "idb-keyval"; +import * as Acct from "calckey-js/built/acct"; +import type { PushNotificationDataMap } from "@/types"; import { createEmptyNotification, createNotification, } from "@/scripts/create-notification"; import { swLang } from "@/scripts/lang"; -import { swNotificationRead } from "@/scripts/notification-read"; -import { pushNotificationDataMap } from "@/types"; import * as swos from "@/scripts/operations"; -import { acct as getAcct } from "@/filters/user"; -self.addEventListener("install", (ev) => { - ev.waitUntil(self.skipWaiting()); +globalThis.addEventListener("install", () => { + // ev.waitUntil(globalThis.skipWaiting()); }); -self.addEventListener("activate", (ev) => { +globalThis.addEventListener("activate", (ev) => { ev.waitUntil( caches .keys() @@ -25,11 +23,15 @@ self.addEventListener("activate", (ev) => { .map((name) => caches.delete(name)), ), ) - .then(() => self.clients.claim()), + .then(() => globalThis.clients.claim()), ); }); -self.addEventListener("fetch", (ev) => { +function offlineContentHTML(): string { + return `<!doctype html>Offline. Service Worker @${_VERSION_} <button onclick="location.reload()">reload</button>`; +} + +globalThis.addEventListener("fetch", (ev) => { let isHTMLRequest = false; if (ev.request.headers.get("sec-fetch-dest") === "document") { isHTMLRequest = true; @@ -41,90 +43,68 @@ self.addEventListener("fetch", (ev) => { if (!isHTMLRequest) return; ev.respondWith( - fetch(ev.request).catch( - () => - new Response(`Offline. Service Worker @${_VERSION_}`, { status: 200 }), - ), + fetch(ev.request).catch(() => { + return new Response(offlineContentHTML(), { + status: 200, + headers: { + "content-type": "text/html", + }, + }); + }), ); }); -self.addEventListener("push", (ev) => { +globalThis.addEventListener("push", (ev) => { // クライアント取得 ev.waitUntil( - self.clients + globalThis.clients .matchAll({ includeUncontrolled: true, type: "window", }) - .then( - async <K extends keyof pushNotificationDataMap>( - clients: readonly WindowClient[], - ) => { - const data: pushNotificationDataMap[K] = ev.data?.json(); + .then(async () => { + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = + ev.data?.json(); - switch (data.type) { - // case 'driveFileCreated': - case "notification": - case "unreadMessagingMessage": - // 1日以上経過している場合は無視 - if (new Date().getTime() - data.dateTime > 1000 * 60 * 60 * 24) - break; + switch (data.type) { + // case 'driveFileCreated': + case "notification": + case "unreadAntennaNote": + // 1日以上経過している場合は無視 + if (new Date().getTime() - data.dateTime > 1000 * 60 * 60 * 24) + break; - // クライアントがあったらストリームに接続しているということなので通知しない - if (clients.length !== 0) break; + return createNotification(data); + case "readAllNotifications": + await globalThis.registration + .getNotifications() + .then((notifications) => + notifications.forEach( + (n) => n.tag !== "read_notification" && n.close(), + ), + ); + break; + } - return createNotification(data); - case "readAllNotifications": - for (const n of await self.registration.getNotifications()) { - if (n?.data?.type === "notification") n.close(); - } - break; - case "readAllMessagingMessages": - for (const n of await self.registration.getNotifications()) { - if (n?.data?.type === "unreadMessagingMessage") n.close(); - } - break; - case "readNotifications": - for (const n of await self.registration.getNotifications()) { - if (data.body?.notificationIds?.includes(n.data.body.id)) { - n.close(); - } - } - break; - case "readAllMessagingMessagesOfARoom": - for (const n of await self.registration.getNotifications()) { - if ( - n.data.type === "unreadMessagingMessage" && - ("userId" in data.body - ? data.body.userId === n.data.body.userId - : data.body.groupId === n.data.body.groupId) - ) { - n.close(); - } - } - break; - } - - return createEmptyNotification(); - }, - ), + await createEmptyNotification(); + return; + }), ); }); -self.addEventListener( +(globalThis as unknown as ServiceWorkerGlobalScope).addEventListener( "notificationclick", - <K extends keyof pushNotificationDataMap>( - ev: ServiceWorkerGlobalScopeEventMap["notificationclick"], - ) => { + (ev: ServiceWorkerGlobalScopeEventMap["notificationclick"]) => { ev.waitUntil( - (async () => { + (async (): Promise<void> => { if (_DEV_) { console.log("notificationclick", ev.action, ev.notification.data); } const { action, notification } = ev; - const data: pushNotificationDataMap[K] = notification.data; - const { userId: id } = data; + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = + notification.data ?? {}; + const { userId: loginId } = data; let client: WindowClient | null = null; switch (data.type) { @@ -132,57 +112,53 @@ self.addEventListener( switch (action) { case "follow": if ("userId" in data.body) - await swos.api("following/create", id, { + await swos.api("following/create", loginId, { userId: data.body.userId, }); break; case "showUser": if ("user" in data.body) - client = await swos.openUser(getAcct(data.body.user), id); + client = await swos.openUser( + Acct.toString(data.body.user), + loginId, + ); break; case "reply": if ("note" in data.body) - client = await swos.openPost({ reply: data.body.note }, id); + client = await swos.openPost( + { reply: data.body.note }, + loginId, + ); break; case "renote": if ("note" in data.body) - await swos.api("notes/create", id, { + await swos.api("notes/create", loginId, { renoteId: data.body.note.id, }); break; case "accept": switch (data.body.type) { case "receiveFollowRequest": - await swos.api("following/requests/accept", id, { + await swos.api("following/requests/accept", loginId, { userId: data.body.userId, }); break; - case "groupInvited": - await swos.api("users/groups/invitations/accept", id, { - invitationId: data.body.invitation.id, - }); - break; } break; case "reject": switch (data.body.type) { case "receiveFollowRequest": - await swos.api("following/requests/reject", id, { + await swos.api("following/requests/reject", loginId, { userId: data.body.userId, }); break; - case "groupInvited": - await swos.api("users/groups/invitations/reject", id, { - invitationId: data.body.invitation.id, - }); - break; } break; case "showFollowRequests": client = await swos.openClient( "push", "/my/follow-requests", - id, + loginId, ); break; default: @@ -191,35 +167,61 @@ self.addEventListener( client = await swos.openClient( "push", "/my/follow-requests", - id, + loginId, ); break; - case "groupInvited": - client = await swos.openClient("push", "/my/groups", id); - break; case "reaction": - client = await swos.openNote(data.body.note.id, id); + client = await swos.openNote(data.body.note.id, loginId); break; default: if ("note" in data.body) { - client = await swos.openNote(data.body.note.id, id); + client = await swos.openNote(data.body.note.id, loginId); } else if ("user" in data.body) { - client = await swos.openUser(getAcct(data.body.user), id); + client = await swos.openUser( + Acct.toString(data.body.user), + loginId, + ); } break; } } break; - case "unreadMessagingMessage": - client = await swos.openChat(data.body, id); + case "unreadAntennaNote": + client = await swos.openAntenna(data.body.antenna.id, loginId); break; + default: + switch (action) { + case "markAllAsRead": + await globalThis.registration + .getNotifications() + .then((notifications) => + notifications.forEach( + (n) => n.tag !== "read_notification" && n.close(), + ), + ); + await get("accounts").then((accounts) => { + return Promise.all( + accounts.map(async (account) => { + await swos.sendMarkAllAsRead(account.id); + }), + ); + }); + break; + case "settings": + client = await swos.openClient( + "push", + "/settings/notifications", + loginId, + ); + break; + } } if (client) { client.focus(); } if (data.type === "notification") { - swNotificationRead.then((that) => that.read(data)); + await swos.sendMarkAllAsRead(loginId); } notification.close(); @@ -228,24 +230,28 @@ self.addEventListener( }, ); -self.addEventListener( +(globalThis as unknown as ServiceWorkerGlobalScope).addEventListener( "notificationclose", - <K extends keyof pushNotificationDataMap>( - ev: ServiceWorkerGlobalScopeEventMap["notificationclose"], - ) => { - const data: pushNotificationDataMap[K] = ev.notification.data; + (ev: ServiceWorkerGlobalScopeEventMap["notificationclose"]) => { + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = + ev.notification.data; - if (data.type === "notification") { - swNotificationRead.then((that) => that.read(data)); - } + ev.waitUntil( + (async (): Promise<void> => { + if (data.type === "notification") { + await swos.sendMarkAllAsRead(data.userId); + } + return; + })(), + ); }, ); -self.addEventListener( +(globalThis as unknown as ServiceWorkerGlobalScope).addEventListener( "message", (ev: ServiceWorkerGlobalScopeEventMap["message"]) => { ev.waitUntil( - (async () => { + (async (): Promise<void> => { switch (ev.data) { case "clear": // Cache Storage全削除 diff --git a/packages/sw/src/types.ts b/packages/sw/src/types.ts index 984076dbe..f66362565 100644 --- a/packages/sw/src/types.ts +++ b/packages/sw/src/types.ts @@ -1,34 +1,51 @@ import * as Misskey from "calckey-js"; -export type swMessageOrderType = "post" | "push"; +export type SwMessageOrderType = "post" | "push"; export type SwMessage = { type: "order"; - order: swMessageOrderType; - loginId: string; + order: SwMessageOrderType; + loginId?: string; url: string; - [x: string]: any; + [x: string]: unknown; }; // Defined also @/services/push-notification.ts#L7-L14 -type pushNotificationDataSourceMap = { +type PushNotificationDataSourceMap = { notification: Misskey.entities.Notification; - unreadMessagingMessage: Misskey.entities.MessagingMessage; - readNotifications: { notificationIds: string[] }; + unreadAntennaNote: { + antenna: { id: string; name: string }; + note: Misskey.entities.Note; + }; readAllNotifications: undefined; readAllMessagingMessages: undefined; readAllMessagingMessagesOfARoom: { userId: string } | { groupId: string }; }; -export type pushNotificationData< - K extends keyof pushNotificationDataSourceMap, +export type PushNotificationData< + K extends keyof PushNotificationDataSourceMap, > = { type: K; - body: pushNotificationDataSourceMap[K]; + body: PushNotificationDataSourceMap[K]; userId: string; dateTime: number; }; -export type pushNotificationDataMap = { - [K in keyof pushNotificationDataSourceMap]: pushNotificationData<K>; +export type PushNotificationDataMap = { + [K in keyof PushNotificationDataSourceMap]: PushNotificationData<K>; }; + +export type BadgeNames = + | "null" + | "antenna" + | "arrow-back-up" + | "at" + | "chart-arrows" + | "circle-check" + | "medal" + | "messages" + | "plus" + | "quote" + | "repeat" + | "user-plus" + | "users"; From 6c2cd1a157b48bce2b3e7811238c344b98fef2e9 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 16:52:36 -0700 Subject: [PATCH 103/162] dev75 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ca8bf72c..2065d40dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev73", + "version": "14.0.0-dev75", "codename": "aqua", "repository": { "type": "git", From 293880f716f40d2810c3a83757ef484e27986e66 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 16:53:53 -0700 Subject: [PATCH 104/162] chore: :art: format --- packages/client/src/components/MkDonation.vue | 7 ++++++- packages/client/src/components/MkModalPageWindow.vue | 6 +++++- packages/client/src/components/MkPollEditor.vue | 6 +++++- packages/client/src/components/MkPostForm.vue | 12 ++++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index d6f6d4801..49a0115a1 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -46,7 +46,12 @@ }}</MkButton> </div> </div> - <button class="_button" :class="$style.close" @click="close" :aria-label="i18n.t('close')"> + <button + class="_button" + :class="$style.close" + @click="close" + :aria-label="i18n.t('close')" + > <i class="ph-x ph-bold ph-lg"></i> </button> </div> diff --git a/packages/client/src/components/MkModalPageWindow.vue b/packages/client/src/components/MkModalPageWindow.vue index e35c6952b..a29571b4e 100644 --- a/packages/client/src/components/MkModalPageWindow.vue +++ b/packages/client/src/components/MkModalPageWindow.vue @@ -26,7 +26,11 @@ ></i> <span>{{ pageMetadata?.value.title }}</span> </span> - <button class="_button" @click="$refs.modal.close()" :aria-label="i18n.t('close')"> + <button + class="_button" + @click="$refs.modal.close()" + :aria-label="i18n.t('close')" + > <i class="ph-x ph-bold ph-lg"></i> </button> </div> diff --git a/packages/client/src/components/MkPollEditor.vue b/packages/client/src/components/MkPollEditor.vue index 6215e6f2d..de691ba88 100644 --- a/packages/client/src/components/MkPollEditor.vue +++ b/packages/client/src/components/MkPollEditor.vue @@ -14,7 +14,11 @@ @update:modelValue="onInput(i, $event)" > </MkInput> - <button class="_button" @click="remove(i)" :aria-label="i18n.t('remove')"> + <button + class="_button" + @click="remove(i)" + :aria-label="i18n.t('remove')" + > <i class="ph-x ph-bold ph-lg"></i> </button> </li> diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index 98fc00851..b1812c2f1 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -84,7 +84,11 @@ <div v-if="quoteId" class="with-quote"> <i class="ph-quotes ph-bold ph-lg"></i> {{ i18n.ts.quoteAttached - }}<button class="_button" @click="quoteId = null" :aria-label="i18n.t('removeQuote')"> + }}<button + class="_button" + @click="quoteId = null" + :aria-label="i18n.t('removeQuote')" + > <i class="ph-x ph-bold ph-lg"></i> </button> </div> @@ -93,7 +97,11 @@ <div class="visibleUsers"> <span v-for="u in visibleUsers" :key="u.id"> <MkAcct :user="u" /> - <button class="_button" @click="removeVisibleUser(u)" :aria-label="i18n.t('removeRecipient')"> + <button + class="_button" + @click="removeVisibleUser(u)" + :aria-label="i18n.t('removeRecipient')" + > <i class="ph-x ph-bold ph-lg"></i> </button> </span> From 2044196a23f5988750b194c0f7fa469180cb78c7 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:11:59 -0700 Subject: [PATCH 105/162] fix: :lipstick: different default font if cjk --- packages/backend/src/server/web/boot.js | 8 ++++++-- packages/client/src/style.scss | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index d3b7c3b82..9c966036f 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -102,7 +102,11 @@ localStorage.setItem("fontSize", null); fontSize = localStorage.getItem("fontSize"); } - document.documentElement.style.fontSize = fontSize + "px"; + document.documentElement.style.fontSize = `${fontSize}px`; + } + + if (["ja-JP", "ja-KS", "ko-KR", "zh-CN", "zh-TW"].includes(lang)) { + document.documentElement.classList.add("useCJKFont"); } const useSystemFont = localStorage.getItem("useSystemFont"); @@ -123,7 +127,7 @@ } async function addStyle(styleText) { - let css = document.createElement("style"); + const css = document.createElement("style"); css.appendChild(document.createTextNode(styleText)); document.head.appendChild(css); } diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index 9df882ec7..6d24f5ad7 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -39,7 +39,7 @@ html { accent-color: var(--accent); overflow: auto; overflow-wrap: break-word; - font-family: "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif; + font-family: Roboto, HelveticaNeue, Arial, sans-serif; font-size: 14px; line-height: 1.6; text-size-adjust: 100%; @@ -47,6 +47,10 @@ html { scroll-padding: 60px; overflow-x: clip; + &.useCJKFont { + font-family: "Hiragino Maru Gothic Pro", "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif; + } + &.useSystemFont { font-family: system-ui, From cceed733e5c363787a00ff54adabfc06dcd5b72a Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:22:35 -0700 Subject: [PATCH 106/162] refactor: :lipstick: relay icon --- packages/client/src/pages/admin/index.vue | 2 +- packages/client/src/pages/admin/relays.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue index d9feb8574..1a5207510 100644 --- a/packages/client/src/pages/admin/index.vue +++ b/packages/client/src/pages/admin/index.vue @@ -264,7 +264,7 @@ const menuDef = $computed(() => [ active: currentPage?.route.name === "security", }, { - icon: "ph-flow-arrow ph-bold ph-lg", + icon: "ph-arrows-merge ph-bold ph-lg", text: i18n.ts.relays, to: "/admin/relays", active: currentPage?.route.name === "relays", diff --git a/packages/client/src/pages/admin/relays.vue b/packages/client/src/pages/admin/relays.vue index 2565ac16c..34f76db69 100644 --- a/packages/client/src/pages/admin/relays.vue +++ b/packages/client/src/pages/admin/relays.vue @@ -108,7 +108,7 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.relays, - icon: "ph-flow-arrow ph-bold ph-lg", + icon: "ph-arrows-merge ph-bold ph-lg", }); </script> From c0e06611f562c7206da1799fc97065d4d21042e3 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:24:24 -0700 Subject: [PATCH 107/162] refactor: :lipstick: privacy icon --- packages/client/src/pages/settings/index.vue | 2 +- packages/client/src/pages/settings/privacy.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue index ee0d77b99..def40a277 100644 --- a/packages/client/src/pages/settings/index.vue +++ b/packages/client/src/pages/settings/index.vue @@ -100,7 +100,7 @@ const menuDef = computed(() => [ active: currentPage?.route.name === "profile", }, { - icon: "ph-lock-open ph-bold ph-lg", + icon: "ph-keyhole ph-bold ph-lg", text: i18n.ts.privacy, to: "/settings/privacy", active: currentPage?.route.name === "privacy", diff --git a/packages/client/src/pages/settings/privacy.vue b/packages/client/src/pages/settings/privacy.vue index c670934ae..08a388bd8 100644 --- a/packages/client/src/pages/settings/privacy.vue +++ b/packages/client/src/pages/settings/privacy.vue @@ -184,6 +184,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.privacy, - icon: "ph-lock-open ph-bold ph-lg", + icon: "ph-keyhole ph-bold ph-lg", }); </script> From c3c7a4c6d6a5f521d4126bfce89275fa05d3db8a Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:38:44 -0700 Subject: [PATCH 108/162] fix: :lipstick: mkdonation bg --- packages/client/src/components/MkDonation.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 49a0115a1..5dab6b614 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -137,6 +137,7 @@ function openExternal(link) { <style lang="scss" module> .root { + background-color: var(--windowHeader); position: fixed; z-index: v-bind(zIndex); bottom: var(--margin); From bdaf5e90009f27384742648fddd386a4fd87f299 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:52:19 -0700 Subject: [PATCH 109/162] refactor: :recycle: no autobind --- packages/backend/package.json | 2 - .../client/src/directives/user-preview.ts | 16 ++-- pnpm-lock.yaml | 87 ++++++++++++++++--- 3 files changed, 82 insertions(+), 23 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index e249b5d3f..fe8c078a0 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -42,7 +42,6 @@ "ajv": "8.12.0", "archiver": "5.3.1", "argon2": "^0.30.3", - "autobind-decorator": "2.4.0", "autolinker": "4.0.0", "autwh": "0.1.0", "aws-sdk": "2.1413.0", @@ -183,7 +182,6 @@ "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", "@types/ws": "8.5.5", - "autobind-decorator": "2.4.0", "cross-env": "7.0.3", "eslint": "^8.44.0", "execa": "6.1.0", diff --git a/packages/client/src/directives/user-preview.ts b/packages/client/src/directives/user-preview.ts index a0210938a..90c9ba3d0 100644 --- a/packages/client/src/directives/user-preview.ts +++ b/packages/client/src/directives/user-preview.ts @@ -1,5 +1,4 @@ import { defineAsyncComponent, Directive, ref } from "vue"; -import autobind from "autobind-decorator"; import { popup } from "@/os"; export class UserPreview { @@ -14,10 +13,17 @@ export class UserPreview { this.el = el; this.user = user; + this.show = this.show.bind(this); + this.close = this.close.bind(this); + this.onMouseover = this.onMouseover.bind(this); + this.onMouseleave = this.onMouseleave.bind(this); + this.onClick = this.onClick.bind(this); + this.attach = this.attach.bind(this); + this.detach = this.detach.bind(this); + this.attach(); } - @autobind private show() { if (!document.body.contains(this.el)) return; if (this.promise) return; @@ -58,7 +64,6 @@ export class UserPreview { }, 1000); } - @autobind private close() { if (this.promise) { window.clearInterval(this.checkTimer); @@ -67,34 +72,29 @@ export class UserPreview { } } - @autobind private onMouseover() { window.clearTimeout(this.showTimer); window.clearTimeout(this.hideTimer); this.showTimer = window.setTimeout(this.show, 500); } - @autobind private onMouseleave() { window.clearTimeout(this.showTimer); window.clearTimeout(this.hideTimer); this.hideTimer = window.setTimeout(this.close, 500); } - @autobind private onClick() { window.clearTimeout(this.showTimer); this.close(); } - @autobind public attach() { this.el.addEventListener("mouseover", this.onMouseover); this.el.addEventListener("mouseleave", this.onMouseleave); this.el.addEventListener("click", this.onClick); } - @autobind public detach() { this.el.removeEventListener("mouseover", this.onMouseover); this.el.removeEventListener("mouseleave", this.onMouseleave); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff6f98d88..adead9c6f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,9 +132,6 @@ importers: argon2: specifier: ^0.30.3 version: 0.30.3 - autobind-decorator: - specifier: 2.4.0 - version: 2.4.0 autolinker: specifier: 4.0.0 version: 4.0.0 @@ -598,7 +595,7 @@ importers: version: 5.1.6 webpack: specifier: ^5.88.1 - version: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + version: 5.88.1(@swc/core@1.3.68) ws: specifier: 8.13.0 version: 8.13.0 @@ -2988,6 +2985,7 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [android] + requiresBuild: true dependencies: '@swc/wasm': 1.2.130 @@ -3094,6 +3092,7 @@ packages: /@swc/wasm@1.2.130: resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==} + requiresBuild: true /@syuilo/aiscript@0.11.1: resolution: {integrity: sha512-chwOIA3yLUKvOB0G611hjLArKTeOWNmTm3lHERSaDW1d+dS6do56naX6Lkwy2UpnwWC0qzeNSgg35elk6t2gZg==} @@ -5139,7 +5138,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: false @@ -5165,7 +5164,7 @@ packages: /axios@1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -6844,6 +6843,17 @@ packages: dependencies: ms: 2.0.0 + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -6854,6 +6864,7 @@ packages: dependencies: ms: 2.1.3 supports-color: 8.1.1 + dev: true /debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} @@ -8366,6 +8377,16 @@ packages: tabbable: 6.2.0 dev: true + /follow-redirects@1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -9334,7 +9355,7 @@ packages: engines: {node: '>= 4.5.0'} dependencies: agent-base: 4.3.0 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 transitivePeerDependencies: - supports-color dev: false @@ -11259,7 +11280,7 @@ packages: json5: 2.2.3 loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68) dev: true /json5@1.0.2: @@ -11514,7 +11535,7 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 koa-send: 5.0.1 transitivePeerDependencies: - supports-color @@ -12558,7 +12579,7 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.2.4 transitivePeerDependencies: @@ -15537,7 +15558,7 @@ packages: webpack: '>=2' dependencies: '@swc/core': 1.3.68 - webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68) dev: true /swiper@10.0.4: @@ -15656,7 +15677,7 @@ packages: schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.0 - webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68) dev: true /terser@5.19.0: @@ -15995,7 +16016,7 @@ packages: micromatch: 4.0.5 semver: 7.5.4 typescript: 5.1.6 - webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) + webpack: 5.88.1(@swc/core@1.3.68) dev: true /ts-node@10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3): @@ -16912,6 +16933,46 @@ packages: engines: {node: '>=10.13.0'} dev: true + /webpack@5.88.1(@swc/core@1.3.68): + 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.9 + 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.68)(webpack@5.88.1) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + /webpack@5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3): resolution: {integrity: sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==} engines: {node: '>=10.13.0'} From f17446697cb56f2f5b39b787b88f38d261df4af3 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 17:52:23 -0700 Subject: [PATCH 110/162] chore: :art: format --- packages/client/src/scripts/autocomplete.ts | 32 ++++++++++++--------- packages/client/src/style.scss | 3 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/client/src/scripts/autocomplete.ts b/packages/client/src/scripts/autocomplete.ts index 59b8d3485..352b9b035 100644 --- a/packages/client/src/scripts/autocomplete.ts +++ b/packages/client/src/scripts/autocomplete.ts @@ -16,10 +16,14 @@ export class Autocomplete { private opening: boolean; private get text(): string { - return this.textRef.value; + // Use raw .value to get the latest value + // (Because v-model does not update while composition) + return this.textarea.value; } private set text(text: string) { + // Use ref value to notify other watchers + // (Because .value setter never fires input/change events) this.textRef.value = text; } @@ -64,7 +68,7 @@ export class Autocomplete { */ private onInput() { const caretPos = this.textarea.selectionStart; - const text = this.text.substr(0, caretPos).split("\n").pop()!; + const text = this.text.substring(0, caretPos).split("\n").pop()!; const mentionIndex = text.lastIndexOf("@"); const hashtagIndex = text.lastIndexOf("#"); @@ -87,7 +91,7 @@ export class Autocomplete { let opened = false; if (isMention) { - const username = text.substr(mentionIndex + 1); + const username = text.substring(mentionIndex + 1); if (username !== "" && username.match(/^[a-zA-Z0-9_]+$/)) { this.open("user", username); opened = true; @@ -98,7 +102,7 @@ export class Autocomplete { } if (isHashtag && !opened) { - const hashtag = text.substr(hashtagIndex + 1); + const hashtag = text.substring(hashtagIndex + 1); if (!hashtag.includes(" ")) { this.open("hashtag", hashtag); opened = true; @@ -106,7 +110,7 @@ export class Autocomplete { } if (isEmoji && !opened) { - const emoji = text.substr(emojiIndex + 1); + const emoji = text.substring(emojiIndex + 1); if (!emoji.includes(" ")) { this.open("emoji", emoji); opened = true; @@ -114,7 +118,7 @@ export class Autocomplete { } if (isMfmTag && !opened) { - const mfmTag = text.substr(mfmTagIndex + 1); + const mfmTag = text.substring(mfmTagIndex + 1); if (!mfmTag.includes(" ")) { this.open("mfmTag", mfmTag.replace("[", "")); opened = true; @@ -211,9 +215,9 @@ export class Autocomplete { if (type === "user") { const source = this.text; - const before = source.substr(0, caret); + const before = source.substring(0, caret); const trimmedBefore = before.substring(0, before.lastIndexOf("@")); - const after = source.substr(caret); + const after = source.substring(caret); const acct = value.host === null @@ -232,9 +236,9 @@ export class Autocomplete { } else if (type === "hashtag") { const source = this.text; - const before = source.substr(0, caret); + const before = source.substring(0, caret); const trimmedBefore = before.substring(0, before.lastIndexOf("#")); - const after = source.substr(caret); + const after = source.substring(caret); // 挿入 this.text = `${trimmedBefore}#${value} ${after}`; @@ -248,9 +252,9 @@ export class Autocomplete { } else if (type === "emoji") { const source = this.text; - const before = source.substr(0, caret); + const before = source.substring(0, caret); const trimmedBefore = before.substring(0, before.lastIndexOf(":")); - const after = source.substr(caret); + const after = source.substring(caret); // 挿入 this.text = trimmedBefore + value + after; @@ -264,9 +268,9 @@ export class Autocomplete { } else if (type === "mfmTag") { const source = this.text; - const before = source.substr(0, caret); + const before = source.substring(0, caret); const trimmedBefore = before.substring(0, before.lastIndexOf("$")); - const after = source.substr(caret); + const after = source.substring(caret); // 挿入 this.text = `${trimmedBefore}$[${value} ]${after}`; diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index 6d24f5ad7..0b38d94c0 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -48,7 +48,8 @@ html { overflow-x: clip; &.useCJKFont { - font-family: "Hiragino Maru Gothic Pro", "BIZ UDGothic", Roboto, HelveticaNeue, Arial, sans-serif; + font-family: "Hiragino Maru Gothic Pro", "BIZ UDGothic", Roboto, + HelveticaNeue, Arial, sans-serif; } &.useSystemFont { From 241d29fb4d6c5dffdd67b814cf8c8469c51b6af7 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 18:32:23 -0700 Subject: [PATCH 111/162] chore: :art: format --- packages/megalodon/package.json | 3 +- packages/megalodon/src/entities/account.ts | 44 +- packages/megalodon/src/entities/activity.ts | 12 +- .../megalodon/src/entities/announcement.ts | 52 +- .../megalodon/src/entities/application.ts | 10 +- .../src/entities/async_attachment.ts | 22 +- packages/megalodon/src/entities/attachment.ts | 84 +- packages/megalodon/src/entities/card.ts | 28 +- packages/megalodon/src/entities/context.ts | 8 +- .../megalodon/src/entities/conversation.ts | 12 +- packages/megalodon/src/entities/emoji.ts | 14 +- .../megalodon/src/entities/featured_tag.ts | 12 +- packages/megalodon/src/entities/field.ts | 10 +- packages/megalodon/src/entities/filter.ts | 18 +- packages/megalodon/src/entities/history.ts | 10 +- .../megalodon/src/entities/identity_proof.ts | 14 +- packages/megalodon/src/entities/instance.ts | 70 +- packages/megalodon/src/entities/list.ts | 8 +- packages/megalodon/src/entities/marker.ts | 26 +- packages/megalodon/src/entities/mention.ts | 12 +- .../megalodon/src/entities/notification.ts | 18 +- packages/megalodon/src/entities/poll.ts | 20 +- .../megalodon/src/entities/poll_option.ts | 8 +- .../megalodon/src/entities/preferences.ts | 14 +- .../src/entities/push_subscription.ts | 26 +- packages/megalodon/src/entities/reaction.ts | 14 +- .../megalodon/src/entities/relationship.ts | 30 +- packages/megalodon/src/entities/report.ts | 14 +- packages/megalodon/src/entities/results.ts | 10 +- .../src/entities/scheduled_status.ts | 12 +- packages/megalodon/src/entities/source.ts | 14 +- packages/megalodon/src/entities/stats.ts | 10 +- packages/megalodon/src/entities/status.ts | 66 +- .../megalodon/src/entities/status_edit.ts | 22 +- .../megalodon/src/entities/status_params.ts | 20 +- packages/megalodon/src/entities/tag.ts | 12 +- packages/megalodon/src/entities/token.ts | 12 +- packages/megalodon/src/entities/urls.ts | 6 +- packages/megalodon/src/misskey/api_client.ts | 1263 +++++++++-------- packages/megalodon/src/misskey/entity.ts | 2 +- .../megalodon/src/misskey/notification.ts | 26 +- packages/megalodon/src/misskey/web_socket.ts | 802 ++++++----- 42 files changed, 1504 insertions(+), 1386 deletions(-) diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index 43479b2e7..bd1b80c1d 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -5,7 +5,8 @@ "typings": "./lib/src/index.d.ts", "scripts": { "build": "tsc -p ./", - "lint": "eslint --ext .js,.ts src", + "lint": "pnpm rome check --apply src/**/*.ts", + "format": "pnpm rome format --write src/**/*.ts", "doc": "typedoc --out ../docs ./src", "test": "NODE_ENV=test jest -u --maxWorkers=3" }, diff --git a/packages/megalodon/src/entities/account.ts b/packages/megalodon/src/entities/account.ts index 77f0e71d5..06a85eb98 100644 --- a/packages/megalodon/src/entities/account.ts +++ b/packages/megalodon/src/entities/account.ts @@ -2,26 +2,26 @@ /// <reference path="source.ts" /> /// <reference path="field.ts" /> 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<Emoji> - moved: Account | null - fields: Array<Field> - bot: boolean | null - source?: Source - } + 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<Emoji>; + moved: Account | null; + fields: Array<Field>; + bot: boolean | null; + source?: Source; + }; } diff --git a/packages/megalodon/src/entities/activity.ts b/packages/megalodon/src/entities/activity.ts index 2494916a9..6bc0b6d80 100644 --- a/packages/megalodon/src/entities/activity.ts +++ b/packages/megalodon/src/entities/activity.ts @@ -1,8 +1,8 @@ namespace Entity { - export type Activity = { - week: string - statuses: string - logins: string - registrations: string - } + 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 index 00fa8a04b..7c7983163 100644 --- a/packages/megalodon/src/entities/announcement.ts +++ b/packages/megalodon/src/entities/announcement.ts @@ -3,32 +3,32 @@ /// <reference path="reaction.ts" /> 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<AnnouncementAccount> - statuses: Array<AnnouncementStatus> - tags: Array<Tag> - emojis: Array<Emoji> - reactions: Array<Reaction> - } + 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<AnnouncementAccount>; + statuses: Array<AnnouncementStatus>; + tags: Array<Tag>; + emojis: Array<Emoji>; + reactions: Array<Reaction>; + }; - export type AnnouncementAccount = { - id: string - username: string - url: string - acct: string - } + export type AnnouncementAccount = { + id: string; + username: string; + url: string; + acct: string; + }; - export type AnnouncementStatus = { - id: string - url: string - } + export type AnnouncementStatus = { + id: string; + url: string; + }; } diff --git a/packages/megalodon/src/entities/application.ts b/packages/megalodon/src/entities/application.ts index 3af64fcf9..9b98b1277 100644 --- a/packages/megalodon/src/entities/application.ts +++ b/packages/megalodon/src/entities/application.ts @@ -1,7 +1,7 @@ namespace Entity { - export type Application = { - name: string - website?: string | null - vapid_key?: string | null - } + 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 index b383f90c5..9cc17acc5 100644 --- a/packages/megalodon/src/entities/async_attachment.ts +++ b/packages/megalodon/src/entities/async_attachment.ts @@ -1,14 +1,14 @@ /// <reference path="attachment.ts" /> 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 - } + 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 index aab1deade..082c79edd 100644 --- a/packages/megalodon/src/entities/attachment.ts +++ b/packages/megalodon/src/entities/attachment.ts @@ -1,49 +1,49 @@ namespace Entity { - export type Sub = { - // For Image, Gifv, and Video - width?: number - height?: number - size?: string - aspect?: number + export type Sub = { + // For Image, Gifv, and Video + width?: number; + height?: number; + size?: string; + aspect?: number; - // For Gifv and Video - frame_rate?: string + // For Gifv and Video + frame_rate?: string; - // For Audio, Gifv, and Video - duration?: number - bitrate?: number - } + // For Audio, Gifv, and Video + duration?: number; + bitrate?: number; + }; - export type Focus = { - x: number - y: 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 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 - } + 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 index b39cbb8f2..356d99aee 100644 --- a/packages/megalodon/src/entities/card.ts +++ b/packages/megalodon/src/entities/card.ts @@ -1,16 +1,16 @@ namespace Entity { - export type Card = { - url: string - title: string - description: string - type: 'link' | 'photo' | 'video' | 'rich' - image?: string - author_name?: string - author_url?: string - provider_name?: string - provider_url?: string - html?: string - width?: number - height?: number - } + 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 index 3f2eda58f..a794a7c5a 100644 --- a/packages/megalodon/src/entities/context.ts +++ b/packages/megalodon/src/entities/context.ts @@ -1,8 +1,8 @@ /// <reference path="status.ts" /> namespace Entity { - export type Context = { - ancestors: Array<Status> - descendants: Array<Status> - } + export type Context = { + ancestors: Array<Status>; + descendants: Array<Status>; + }; } diff --git a/packages/megalodon/src/entities/conversation.ts b/packages/megalodon/src/entities/conversation.ts index cdadf1e0f..2bdc19666 100644 --- a/packages/megalodon/src/entities/conversation.ts +++ b/packages/megalodon/src/entities/conversation.ts @@ -2,10 +2,10 @@ /// <reference path="status.ts" /> namespace Entity { - export type Conversation = { - id: string - accounts: Array<Account> - last_status: Status | null - unread: boolean - } + export type Conversation = { + id: string; + accounts: Array<Account>; + last_status: Status | null; + unread: boolean; + }; } diff --git a/packages/megalodon/src/entities/emoji.ts b/packages/megalodon/src/entities/emoji.ts index c2bc5a1ef..10c32ab0b 100644 --- a/packages/megalodon/src/entities/emoji.ts +++ b/packages/megalodon/src/entities/emoji.ts @@ -1,9 +1,9 @@ namespace Entity { - export type Emoji = { - shortcode: string - static_url: string - url: string - visible_in_picker: boolean - category: string - } + 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 index 06ae6d7a9..fc9f8c69c 100644 --- a/packages/megalodon/src/entities/featured_tag.ts +++ b/packages/megalodon/src/entities/featured_tag.ts @@ -1,8 +1,8 @@ namespace Entity { - export type FeaturedTag = { - id: string - name: string - statuses_count: number - last_status_at: string - } + 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 index 03e4604b0..de4b6b2b7 100644 --- a/packages/megalodon/src/entities/field.ts +++ b/packages/megalodon/src/entities/field.ts @@ -1,7 +1,7 @@ namespace Entity { - export type Field = { - name: string - value: string - verified_at: string | null - } + 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 index ffbacb728..55b7305cc 100644 --- a/packages/megalodon/src/entities/filter.ts +++ b/packages/megalodon/src/entities/filter.ts @@ -1,12 +1,12 @@ namespace Entity { - export type Filter = { - id: string - phrase: string - context: Array<FilterContext> - expires_at: string | null - irreversible: boolean - whole_word: boolean - } + export type Filter = { + id: string; + phrase: string; + context: Array<FilterContext>; + expires_at: string | null; + irreversible: boolean; + whole_word: boolean; + }; - export type FilterContext = string + export type FilterContext = string; } diff --git a/packages/megalodon/src/entities/history.ts b/packages/megalodon/src/entities/history.ts index 070969426..4676357d6 100644 --- a/packages/megalodon/src/entities/history.ts +++ b/packages/megalodon/src/entities/history.ts @@ -1,7 +1,7 @@ namespace Entity { - export type History = { - day: string - uses: number - accounts: number - } + 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 index ff857addb..3b42e6f41 100644 --- a/packages/megalodon/src/entities/identity_proof.ts +++ b/packages/megalodon/src/entities/identity_proof.ts @@ -1,9 +1,9 @@ namespace Entity { - export type IdentityProof = { - provider: string - provider_username: string - updated_at: string - proof_url: string - profile_url: string - } + 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 index e0aaf99b1..9c0f572db 100644 --- a/packages/megalodon/src/entities/instance.ts +++ b/packages/megalodon/src/entities/instance.ts @@ -3,39 +3,39 @@ /// <reference path="stats.ts" /> namespace Entity { - export type Instance = { - uri: string - title: string - description: string - email: string - version: string - thumbnail: string | null - urls: URLs - stats: Stats - languages: Array<string> - 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<string> - 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 - } - } - } + export type Instance = { + uri: string; + title: string; + description: string; + email: string; + version: string; + thumbnail: string | null; + urls: URLs; + stats: Stats; + languages: Array<string>; + 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<string>; + 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 index 2cee0db3c..97e75286b 100644 --- a/packages/megalodon/src/entities/list.ts +++ b/packages/megalodon/src/entities/list.ts @@ -1,6 +1,6 @@ namespace Entity { - export type List = { - id: string - title: string - } + export type List = { + id: string; + title: string; + }; } diff --git a/packages/megalodon/src/entities/marker.ts b/packages/megalodon/src/entities/marker.ts index 33cb98a10..7ee99282c 100644 --- a/packages/megalodon/src/entities/marker.ts +++ b/packages/megalodon/src/entities/marker.ts @@ -1,15 +1,15 @@ namespace Entity { - export type Marker = { - home?: { - last_read_id: string - version: number - updated_at: string - } - notifications?: { - last_read_id: string - version: number - updated_at: string - unread_count?: number - } - } + 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 index 046912971..4fe36a655 100644 --- a/packages/megalodon/src/entities/mention.ts +++ b/packages/megalodon/src/entities/mention.ts @@ -1,8 +1,8 @@ namespace Entity { - export type Mention = { - id: string - username: string - url: string - acct: string - } + 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 index d42dfe375..fae32c795 100644 --- a/packages/megalodon/src/entities/notification.ts +++ b/packages/megalodon/src/entities/notification.ts @@ -2,14 +2,14 @@ /// <reference path="status.ts" /> namespace Entity { - export type Notification = { - account: Account - created_at: string - id: string - status?: Status - emoji?: string - type: NotificationType - } + export type Notification = { + account: Account; + created_at: string; + id: string; + status?: Status; + emoji?: string; + type: NotificationType; + }; - export type NotificationType = string + export type NotificationType = string; } diff --git a/packages/megalodon/src/entities/poll.ts b/packages/megalodon/src/entities/poll.ts index c4f8f4f6d..2539d68b2 100644 --- a/packages/megalodon/src/entities/poll.ts +++ b/packages/megalodon/src/entities/poll.ts @@ -1,14 +1,14 @@ /// <reference path="poll_option.ts" /> namespace Entity { - export type Poll = { - id: string - expires_at: string | null - expired: boolean - multiple: boolean - votes_count: number - options: Array<PollOption> - voted: boolean - own_votes: Array<number> - } + export type Poll = { + id: string; + expires_at: string | null; + expired: boolean; + multiple: boolean; + votes_count: number; + options: Array<PollOption>; + voted: boolean; + own_votes: Array<number>; + }; } diff --git a/packages/megalodon/src/entities/poll_option.ts b/packages/megalodon/src/entities/poll_option.ts index ae4c63849..e818a8607 100644 --- a/packages/megalodon/src/entities/poll_option.ts +++ b/packages/megalodon/src/entities/poll_option.ts @@ -1,6 +1,6 @@ namespace Entity { - export type PollOption = { - title: string - votes_count: number | null - } + 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 index cb5797c4c..7994dc568 100644 --- a/packages/megalodon/src/entities/preferences.ts +++ b/packages/megalodon/src/entities/preferences.ts @@ -1,9 +1,9 @@ namespace Entity { - export type Preferences = { - 'posting:default:visibility': 'public' | 'unlisted' | 'private' | 'direct' - 'posting:default:sensitive': boolean - 'posting:default:language': string | null - 'reading:expand:media': 'default' | 'show_all' | 'hide_all' - 'reading:expand:spoilers': boolean - } + 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 index fe7464e8e..ad1146a24 100644 --- a/packages/megalodon/src/entities/push_subscription.ts +++ b/packages/megalodon/src/entities/push_subscription.ts @@ -1,16 +1,16 @@ namespace Entity { - export type Alerts = { - follow: boolean - favourite: boolean - mention: boolean - reblog: boolean - poll: boolean - } + 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 - } + 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 index ccdc2d26a..2ad4f9d3a 100644 --- a/packages/megalodon/src/entities/reaction.ts +++ b/packages/megalodon/src/entities/reaction.ts @@ -1,11 +1,11 @@ /// <reference path="account.ts" /> namespace Entity { - export type Reaction = { - count: number - me: boolean - name: string - url?: string - accounts?: Array<Account> - } + export type Reaction = { + count: number; + me: boolean; + name: string; + url?: string; + accounts?: Array<Account>; + }; } diff --git a/packages/megalodon/src/entities/relationship.ts b/packages/megalodon/src/entities/relationship.ts index 5f10b9c98..91802d5c8 100644 --- a/packages/megalodon/src/entities/relationship.ts +++ b/packages/megalodon/src/entities/relationship.ts @@ -1,17 +1,17 @@ namespace Entity { - export type Relationship = { - id: string - following: boolean - followed_by: boolean - delivery_following?: boolean - blocking: boolean - blocked_by: boolean - muting: boolean - muting_notifications: boolean - requested: boolean - domain_blocking: boolean - showing_reblogs: boolean - endorsed: boolean - notifying: boolean - } + 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 index 28f029981..6862a5fab 100644 --- a/packages/megalodon/src/entities/report.ts +++ b/packages/megalodon/src/entities/report.ts @@ -1,9 +1,9 @@ namespace Entity { - export type Report = { - id: string - action_taken: string - comment: string - account_id: string - status_ids: Array<string> - } + export type Report = { + id: string; + action_taken: string; + comment: string; + account_id: string; + status_ids: Array<string>; + }; } diff --git a/packages/megalodon/src/entities/results.ts b/packages/megalodon/src/entities/results.ts index fe168de67..4448e5335 100644 --- a/packages/megalodon/src/entities/results.ts +++ b/packages/megalodon/src/entities/results.ts @@ -3,9 +3,9 @@ /// <reference path="tag.ts" /> namespace Entity { - export type Results = { - accounts: Array<Account> - statuses: Array<Status> - hashtags: Array<Tag> - } + export type Results = { + accounts: Array<Account>; + statuses: Array<Status>; + hashtags: Array<Tag>; + }; } diff --git a/packages/megalodon/src/entities/scheduled_status.ts b/packages/megalodon/src/entities/scheduled_status.ts index fb6f63f10..78dfb8ed2 100644 --- a/packages/megalodon/src/entities/scheduled_status.ts +++ b/packages/megalodon/src/entities/scheduled_status.ts @@ -1,10 +1,10 @@ /// <reference path="attachment.ts" /> /// <reference path="status_params.ts" /> namespace Entity { - export type ScheduledStatus = { - id: string - scheduled_at: string - params: StatusParams - media_attachments: Array<Attachment> - } + export type ScheduledStatus = { + id: string; + scheduled_at: string; + params: StatusParams; + media_attachments: Array<Attachment>; + }; } diff --git a/packages/megalodon/src/entities/source.ts b/packages/megalodon/src/entities/source.ts index d87cf55d8..913b02fda 100644 --- a/packages/megalodon/src/entities/source.ts +++ b/packages/megalodon/src/entities/source.ts @@ -1,10 +1,10 @@ /// <reference path="field.ts" /> namespace Entity { - export type Source = { - privacy: string | null - sensitive: boolean | null - language: string | null - note: string - fields: Array<Field> - } + export type Source = { + privacy: string | null; + sensitive: boolean | null; + language: string | null; + note: string; + fields: Array<Field>; + }; } diff --git a/packages/megalodon/src/entities/stats.ts b/packages/megalodon/src/entities/stats.ts index 76f0bad34..6471df039 100644 --- a/packages/megalodon/src/entities/stats.ts +++ b/packages/megalodon/src/entities/stats.ts @@ -1,7 +1,7 @@ namespace Entity { - export type Stats = { - user_count: number - status_count: number - domain_count: number - } + 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 index 7fd72e20c..8c8148fd5 100644 --- a/packages/megalodon/src/entities/status.ts +++ b/packages/megalodon/src/entities/status.ts @@ -9,37 +9,37 @@ /// <reference path="reaction.ts" /> 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<Attachment> - mentions: Array<Mention> - tags: Array<Tag> - card: Card | null - poll: Poll | null - application: Application | null - language: string | null - pinned: boolean | null - emoji_reactions: Array<Reaction> - quote: Status | null - bookmarked: boolean - } + 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<Attachment>; + mentions: Array<Mention>; + tags: Array<Tag>; + card: Card | null; + poll: Poll | null; + application: Application | null; + language: string | null; + pinned: boolean | null; + emoji_reactions: Array<Reaction>; + quote: Status | null; + bookmarked: boolean; + }; } diff --git a/packages/megalodon/src/entities/status_edit.ts b/packages/megalodon/src/entities/status_edit.ts index 30bbee8e6..4040b4ff9 100644 --- a/packages/megalodon/src/entities/status_edit.ts +++ b/packages/megalodon/src/entities/status_edit.ts @@ -9,15 +9,15 @@ /// <reference path="reaction.ts" /> 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<Attachment> - poll: Poll | null - } + export type StatusEdit = { + account: Account; + content: string; + plain_content: string | null; + created_at: string; + emojis: Emoji[]; + sensitive: boolean; + spoiler_text: string; + media_attachments: Array<Attachment>; + poll: Poll | null; + }; } diff --git a/packages/megalodon/src/entities/status_params.ts b/packages/megalodon/src/entities/status_params.ts index 6de12423c..18908c01c 100644 --- a/packages/megalodon/src/entities/status_params.ts +++ b/packages/megalodon/src/entities/status_params.ts @@ -1,12 +1,12 @@ namespace Entity { - export type StatusParams = { - text: string - in_reply_to_id: string | null - media_ids: Array<string> | null - sensitive: boolean | null - spoiler_text: string | null - visibility: 'public' | 'unlisted' | 'private' | 'direct' - scheduled_at: string | null - application_id: string - } + export type StatusParams = { + text: string; + in_reply_to_id: string | null; + media_ids: Array<string> | 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 index ff5b93381..ccc88aece 100644 --- a/packages/megalodon/src/entities/tag.ts +++ b/packages/megalodon/src/entities/tag.ts @@ -1,10 +1,10 @@ /// <reference path="history.ts" /> namespace Entity { - export type Tag = { - name: string - url: string - history: Array<History> | null - following?: boolean - } + export type Tag = { + name: string; + url: string; + history: Array<History> | null; + following?: boolean; + }; } diff --git a/packages/megalodon/src/entities/token.ts b/packages/megalodon/src/entities/token.ts index 6fa28e39b..1583edafb 100644 --- a/packages/megalodon/src/entities/token.ts +++ b/packages/megalodon/src/entities/token.ts @@ -1,8 +1,8 @@ namespace Entity { - export type Token = { - access_token: string - token_type: string - scope: string - created_at: number - } + 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 index 4a980d589..1ee9ed67c 100644 --- a/packages/megalodon/src/entities/urls.ts +++ b/packages/megalodon/src/entities/urls.ts @@ -1,5 +1,5 @@ namespace Entity { - export type URLs = { - streaming_api: string - } + export type URLs = { + streaming_api: string; + }; } diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 1c198ecc9..22cac2a1c 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -1,645 +1,716 @@ -import axios, { AxiosResponse, AxiosRequestConfig } from 'axios' -import dayjs from 'dayjs' -import FormData from 'form-data' +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' +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 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 - } + 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; - } + 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(/`/g, "`") + .replace(/\r?\n/g, "<br>"); + emoji = (e: Entity.Emoji): MegalodonEntity.Emoji => { + return { + shortcode: e.name, + static_url: e.url, + url: e.url, + visible_in_picker: true, + category: e.category, + }; + }; - // 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(/`/g, '`') - .replace(/\r?\n/g, '<br>'); + field = (f: Entity.Field): MegalodonEntity.Field => ({ + name: f.name, + value: this.escapeMFM(f.value), + verified_at: null, + }); - emoji = (e: Entity.Emoji): MegalodonEntity.Emoji => { - return { - shortcode: e.name, - static_url: e.url, - url: e.url, - visible_in_picker: true, - category: e.category - } - } + 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, + }; + }; - field = (f: Entity.Field): MegalodonEntity.Field => ({ - name: f.name, - value: this.escapeMFM(f.value), - verified_at: null - }) + 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, "<br>") ?? "", + 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, + }; + }; - 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 - } - } + 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, + }; + }; - 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, '<br>') ?? '', - 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, - } - } + 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"; + } + }; - 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 - } - } + 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"; + } + }; - 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' - } - } + 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"; + }; - 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' - } - } + 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, + }; + }; - 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' - } + follower = (f: Entity.Follower): MegalodonEntity.Account => { + return this.user(f.follower); + }; - 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 - } - } + following = (f: Entity.Following): MegalodonEntity.Account => { + return this.user(f.followee); + }; - follower = (f: Entity.Follower): MegalodonEntity.Account => { - return this.user(f.follower) - } + 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, + }; + }; - following = (f: Entity.Following): MegalodonEntity.Account => { - return this.user(f.followee) - } + choice = (c: Entity.Choice): MegalodonEntity.PollOption => { + return { + title: c.text, + votes_count: c.votes, + }; + }; - 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 - } - } + 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)), + }; + }; - choice = (c: Entity.Choice): MegalodonEntity.PollOption => { - return { - title: c.text, - votes_count: c.votes - } - } + note = (n: Entity.Note, host: string): MegalodonEntity.Status => { + host = host.replace("https://", ""); - 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)) - } - } + return { + id: n.id, + uri: n.uri ? n.uri : `https://${host}/notes/${n.id}`, + url: n.uri ? n.uri : `https://${host}/notes/${n.id}`, + account: this.user(n.user), + in_reply_to_id: n.replyId, + in_reply_to_account_id: n.reply?.userId ?? null, + reblog: n.renote ? this.note(n.renote, host) : null, + content: n.text ? this.escapeMFM(n.text) : "", + plain_content: n.text ? n.text : null, + created_at: n.createdAt, + emojis: n.emojis.map((e) => this.emoji(e)), + replies_count: n.repliesCount, + reblogs_count: n.renoteCount, + favourites_count: this.getTotalReactions(n.reactions), + 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, + emoji_reactions: this.mapReactions(n.reactions, n.myReaction), + bookmarked: false, + quote: n.renote && n.text ? this.note(n.renote, host) : null, + }; + }; - note = (n: Entity.Note, host: string): MegalodonEntity.Status => { - host = host.replace('https://', '') + mapReactions = ( + r: { [key: string]: number }, + myReaction?: string, + ): Array<MegalodonEntity.Reaction> => { + return Object.keys(r).map((key) => { + if (myReaction && key === myReaction) { + return { + count: r[key], + me: true, + name: key, + }; + } + return { + count: r[key], + me: false, + name: key, + }; + }); + }; - return { - id: n.id, - uri: n.uri ? n.uri : `https://${host}/notes/${n.id}`, - url: n.uri ? n.uri : `https://${host}/notes/${n.id}`, - account: this.user(n.user), - in_reply_to_id: n.replyId, - in_reply_to_account_id: n.reply?.userId ?? null, - reblog: n.renote ? this.note(n.renote, host) : null, - content: n.text ? this.escapeMFM(n.text) : '', - plain_content: n.text ? n.text : null, - created_at: n.createdAt, - emojis: n.emojis.map(e => this.emoji(e)), - replies_count: n.repliesCount, - reblogs_count: n.renoteCount, - favourites_count: this.getTotalReactions(n.reactions), - 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, - emoji_reactions: this.mapReactions(n.reactions, n.myReaction), - bookmarked: false, - quote: n.renote && n.text ? this.note(n.renote, host) : null - } - } + getTotalReactions = (r: { [key: string]: number }): number => { + return Object.values(r).length > 0 + ? Object.values(r).reduce( + (previousValue, currentValue) => previousValue + currentValue, + ) + : 0; + }; - mapReactions = (r: { [key: string]: number }, myReaction?: string): Array<MegalodonEntity.Reaction> => { - return Object.keys(r).map(key => { - if (myReaction && key === myReaction) { - return { - count: r[key], - me: true, - name: key - } - } - return { - count: r[key], - me: false, - name: key - } - }) - } + reactions = ( + r: Array<Entity.Reaction>, + ): Array<MegalodonEntity.Reaction> => { + const result: Array<MegalodonEntity.Reaction> = []; + 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; + }; - getTotalReactions = (r: { [key: string]: number }): number => { - return Object.values(r).length > 0 ? Object.values(r).reduce((previousValue, currentValue) => previousValue + currentValue) : 0 - } + noteToConversation = ( + n: Entity.Note, + host: string, + ): MegalodonEntity.Conversation => { + const accounts: Array<MegalodonEntity.Account> = [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, + }; + }; - reactions = (r: Array<Entity.Reaction>): Array<MegalodonEntity.Reaction> => { - const result: Array<MegalodonEntity.Reaction> = [] - 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 - } + list = (l: Entity.List): MegalodonEntity.List => ({ + id: l.id, + title: l.name, + }); - noteToConversation = (n: Entity.Note, host: string): MegalodonEntity.Conversation => { - const accounts: Array<MegalodonEntity.Account> = [this.user(n.user)] - if (n.reply) { - accounts.push(this.user(n.reply.user)) - } - return { - id: n.id, - accounts: accounts, - last_status: this.note(n, host), - unread: false - } - } - - list = (l: Entity.List): MegalodonEntity.List => ({ - id: l.id, - title: l.name - }) - - encodeNotificationType = (e: MegalodonEntity.NotificationType): MisskeyEntity.NotificationType => { - switch (e) { - case NotificationType.Follow: - return MisskeyNotificationType.Follow - case NotificationType.Mention: - return MisskeyNotificationType.Reply - case NotificationType.Favourite: - case NotificationType.EmojiReaction: - return MisskeyNotificationType.Reaction - case NotificationType.Reblog: - return MisskeyNotificationType.Renote + encodeNotificationType = ( + e: MegalodonEntity.NotificationType, + ): MisskeyEntity.NotificationType => { + switch (e) { + case NotificationType.Follow: + return MisskeyNotificationType.Follow; + case NotificationType.Mention: + return MisskeyNotificationType.Reply; + case NotificationType.Favourite: + case NotificationType.EmojiReaction: + return MisskeyNotificationType.Reaction; + case NotificationType.Reblog: + return MisskeyNotificationType.Renote; case NotificationType.Poll: - return MisskeyNotificationType.PollEnded - case NotificationType.FollowRequest: - return MisskeyNotificationType.ReceiveFollowRequest - default: - return e - } - } + 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.EmojiReaction + decodeNotificationType = ( + e: MisskeyEntity.NotificationType, + ): MegalodonEntity.NotificationType => { + switch (e) { + case MisskeyNotificationType.Follow: + return NotificationType.Follow; + case MisskeyNotificationType.Mention: + case MisskeyNotificationType.Reply: + return NotificationType.Mention; + case MisskeyNotificationType.Renote: + case MisskeyNotificationType.Quote: + return NotificationType.Reblog; + case MisskeyNotificationType.Reaction: + return NotificationType.EmojiReaction; case MisskeyNotificationType.PollEnded: - return NotificationType.Poll - case MisskeyNotificationType.ReceiveFollowRequest: - return NotificationType.FollowRequest - case MisskeyNotificationType.FollowRequestAccepted: - return NotificationType.Follow - default: - return e - } - } + 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: `<h1>${this.escapeMFM(a.title)}</h1>${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: [], + }); - - announcement = (a: Entity.Announcement): MegalodonEntity.Announcement => ({ - id: a.id, - content: `<h1>${this.escapeMFM(a.title)}</h1>${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) - }) + 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 - }) + account: this.note(n.note, host).account, + }); } - } - if (n.reaction) { - notification = Object.assign(notification, { - emoji: n.reaction - }) - } - return notification - } + } + if (n.reaction) { + notification = Object.assign(notification, { + emoji: n.reaction, + }); + } + return notification; + }; - stats = (s: Entity.Stats): MegalodonEntity.Stats => { - return { - user_count: s.usersCount, - status_count: s.notesCount, - domain_count: s.instances - } - } + 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 - } - } + 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 - } - } - } + 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' - ] + 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<T = any>(path: string, params?: any, headers?: { [key: string]: string }): Promise<Response<T>> - cancel(): void - socket(channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', listId?: string): WebSocket - } + /** + * Interface + */ + export interface Interface { + post<T = any>( + path: string, + params?: any, + headers?: { [key: string]: string }, + ): Promise<Response<T>>; + 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 + /** + * 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 - } + /** + * @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<T>(path: string, params: any = {}, headers: { [key: string]: string } = {}): Promise<Response<T>> { - 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 - }) - } - } + /** + * POST request to mastodon REST API. + * @param path relative path from baseUrl + * @param params Form data + * @param headers Request header object + */ + public async post<T>( + path: string, + params: any = {}, + headers: { [key: string]: string } = {}, + ): Promise<Response<T>> { + 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<T>(this.baseUrl + path, bodyParams, options).then((resp: AxiosResponse<T>) => { - const res: Response<T> = { - data: resp.data, - status: resp.status, - statusText: resp.statusText, - headers: resp.headers - } - return res - }) - } + return axios + .post<T>(this.baseUrl + path, bodyParams, options) + .then((resp: AxiosResponse<T>) => { + const res: Response<T> = { + 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() - } + /** + * 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 - } - } + /** + * 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 +export default MisskeyAPI; diff --git a/packages/megalodon/src/misskey/entity.ts b/packages/megalodon/src/misskey/entity.ts index d0bfd15aa..72a80f9d9 100644 --- a/packages/megalodon/src/misskey/entity.ts +++ b/packages/megalodon/src/misskey/entity.ts @@ -25,4 +25,4 @@ /// <reference path="entities/session.ts" /> /// <reference path="entities/stats.ts" /> -export default MisskeyEntity +export default MisskeyEntity; diff --git a/packages/megalodon/src/misskey/notification.ts b/packages/megalodon/src/misskey/notification.ts index e44b6159c..eb7c2d23d 100644 --- a/packages/megalodon/src/misskey/notification.ts +++ b/packages/megalodon/src/misskey/notification.ts @@ -1,16 +1,18 @@ -import MisskeyEntity from './entity' +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 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 +export default MisskeyNotificationType; diff --git a/packages/megalodon/src/misskey/web_socket.ts b/packages/megalodon/src/misskey/web_socket.ts index d3642864a..0cbfc2bfe 100644 --- a/packages/megalodon/src/misskey/web_socket.ts +++ b/packages/megalodon/src/misskey/web_socket.ts @@ -1,329 +1,365 @@ -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' +import WS from "ws"; +import dayjs, { Dayjs } from "dayjs"; +import { v4 as uuid } from "uuid"; +import { EventEmitter } from "events"; +import { WebSocketInterface } from "../megalodon"; +import proxyAgent, { ProxyConfig } from "../proxy_config"; +import MisskeyAPI from "./api_client"; /** * WebSocket * Misskey is not support http streaming. It supports websocket instead of streaming. * So this class connect to Misskey server with WebSocket. */ -export default class WebSocket extends EventEmitter implements WebSocketInterface { - public url: string - public channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list' - public parser: any - public headers: { [key: string]: string } - public proxyConfig: ProxyConfig | false = false - public listId: string | null = null - private _converter: MisskeyAPI.Converter - private _accessToken: string - private _reconnectInterval: number - private _reconnectMaxAttempts: number - private _reconnectCurrentAttempts: number - private _connectionClosed: boolean - private _client: WS | null = null - private _channelID: string - private _pongReceivedTimestamp: Dayjs - private _heartbeatInterval: number = 60000 - private _pongWaiting: boolean = false +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://misskey.io/streaming - * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. - * @param accessToken The access token. - * @param listId This parameter is required when you specify list as channel. - */ - constructor( - url: string, - channel: 'user' | 'localTimeline' | 'hybridTimeline' | 'globalTimeline' | 'conversation' | 'list', - accessToken: string, - listId: string | undefined, - userAgent: string, - proxyConfig: ProxyConfig | false = false, - converter: MisskeyAPI.Converter - ) { - super() - this.url = url - this.parser = new Parser() - this.channel = channel - this.headers = { - 'User-Agent': userAgent - } - if (listId === undefined) { - this.listId = null - } else { - this.listId = listId - } - this.proxyConfig = proxyConfig - this._accessToken = accessToken - this._reconnectInterval = 10000 - this._reconnectMaxAttempts = Infinity - this._reconnectCurrentAttempts = 0 - this._connectionClosed = false - this._channelID = uuid() - this._pongReceivedTimestamp = dayjs() - this._converter = converter - } + /** + * @param url Full url of websocket: e.g. wss://misskey.io/streaming + * @param channel Channel name is user, localTimeline, hybridTimeline, globalTimeline, conversation or list. + * @param accessToken The access token. + * @param listId This parameter is required when you specify list as channel. + */ + constructor( + url: string, + channel: + | "user" + | "localTimeline" + | "hybridTimeline" + | "globalTimeline" + | "conversation" + | "list", + accessToken: string, + listId: string | undefined, + userAgent: string, + proxyConfig: ProxyConfig | false = false, + converter: MisskeyAPI.Converter, + ) { + super(); + this.url = url; + this.parser = new Parser(); + this.channel = channel; + this.headers = { + "User-Agent": userAgent, + }; + if (listId === undefined) { + this.listId = null; + } else { + this.listId = listId; + } + this.proxyConfig = proxyConfig; + this._accessToken = accessToken; + this._reconnectInterval = 10000; + this._reconnectMaxAttempts = Infinity; + this._reconnectCurrentAttempts = 0; + this._connectionClosed = false; + this._channelID = uuid(); + this._pongReceivedTimestamp = dayjs(); + this._converter = converter; + } - /** - * Start websocket connection. - */ - public start() { - this._connectionClosed = false - this._resetRetryParams() - this._startWebSocketConnection() - } + /** + * Start websocket connection. + */ + public start() { + this._connectionClosed = false; + this._resetRetryParams(); + this._startWebSocketConnection(); + } - private baseUrlToHost(baseUrl: string): string { - return baseUrl.replace('https://', '') - } + 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) - } + /** + * 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() - } + /** + * 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 - } + /** + * 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() - } - } + if (this.parser) { + this.parser.removeAllListeners(); + } + } - /** - * Resets the parameters used in reconnect. - */ - private _resetRetryParams() { - this._reconnectCurrentAttempts = 0 - } + /** + * 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 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 - } - } + /** + * 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. - */ + /** + * 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 - } + 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) - } + 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') - } - } + /** + * 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) - }) - } + /** + * 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) - }) - } + /** + * 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) - } - } - } + /** + * 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); + } + } + } } /** @@ -331,84 +367,92 @@ export default class WebSocket extends EventEmitter implements WebSocketInterfac * 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 - } + /** + * @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 - } + 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 - } + 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 - } + 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 - } - } + 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; + } + } } From 242f564115e5ec583d79c0a56b341b7a9fdb5a73 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 19:00:26 -0700 Subject: [PATCH 112/162] refactor: :zap: use blurhash-as for encoding and decoding --- packages/backend/package.json | 2 +- packages/backend/src/misc/get-file-info.ts | 11 ++++++-- packages/client/package.json | 1 + .../src/components/MkImgWithBlurhash.vue | 12 +++++---- pnpm-lock.yaml | 25 ++++++++++++++----- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index fe8c078a0..b021f3f40 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -47,7 +47,7 @@ "aws-sdk": "2.1413.0", "axios": "^1.4.0", "bcryptjs": "2.4.3", - "blurhash": "2.0.5", + "blurhash-as": "^0.10.0", "bull": "4.10.4", "cacheable-lookup": "7.0.0", "calckey-js": "workspace:*", diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 76964890e..8cc24026d 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -10,11 +10,12 @@ import FFmpeg from "fluent-ffmpeg"; import isSvg from "is-svg"; import { type predictionType } from "nsfwjs"; import sharp from "sharp"; -import { encode } from "blurhash"; +import * as blurhash from "blurhash-as"; import { detectSensitive } from "@/services/detect-sensitive.js"; import { createTempDir } from "./create-temp.js"; const pipeline = util.promisify(stream.pipeline); +blurhash.init(); export type FileInfo = { size: number; @@ -432,7 +433,13 @@ function getBlurhash(path: string): Promise<string> { let hash; try { - hash = encode(new Uint8ClampedArray(buffer), width, height, 7, 7); + hash = blurhash.encode( + new Uint8ClampedArray(buffer), + width, + height, + 7, + 7, + ); } catch (e) { return reject(e); } diff --git a/packages/client/package.json b/packages/client/package.json index 95fb9f9b2..014f2f646 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -30,6 +30,7 @@ "autobind-decorator": "2.4.0", "autosize": "5.0.2", "blurhash": "2.0.5", + "blurhash-as": "^0.10.0", "broadcast-channel": "5.1.0", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", "calckey-js": "workspace:*", diff --git a/packages/client/src/components/MkImgWithBlurhash.vue b/packages/client/src/components/MkImgWithBlurhash.vue index 5a0cefec2..06f7b56a9 100644 --- a/packages/client/src/components/MkImgWithBlurhash.vue +++ b/packages/client/src/components/MkImgWithBlurhash.vue @@ -4,12 +4,12 @@ ref="canvas" :width="size" :height="size" - :title="title" + :title="title ?? ''" /> <img v-if="src" :src="src" - :title="title" + :title="title ?? ''" :type="type" :alt="alt" :class="{ cover }" @@ -21,7 +21,8 @@ <script lang="ts" setup> import { onMounted } from "vue"; -import { decodeBlurHash } from "fast-blurhash"; +import * as blurhash from "blurhash-as/browser"; +import wasmURL from "blurhash-as/build/optimized.wasm?url"; const props = withDefaults( defineProps<{ @@ -46,9 +47,10 @@ const props = withDefaults( const canvas = $ref<HTMLCanvasElement>(); let loaded = $ref(false); -function draw() { +async function draw() { if (props.hash == null || canvas == null) return; - const pixels = decodeBlurHash(props.hash, props.size, props.size); + blurhash.setURL(wasmURL); + const pixels = await blurhash.decode(props.hash, props.size, props.size); const ctx = canvas.getContext("2d"); const imageData = ctx!.createImageData(props.size, props.size); imageData.data.set(pixels); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adead9c6f..15f08733f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,9 +147,9 @@ importers: bcryptjs: specifier: 2.4.3 version: 2.4.3 - blurhash: - specifier: 2.0.5 - version: 2.0.5 + blurhash-as: + specifier: ^0.10.0 + version: 0.10.0 bull: specifier: 4.10.4 version: 4.10.4 @@ -736,6 +736,9 @@ importers: blurhash: specifier: 2.0.5 version: 2.0.5 + blurhash-as: + specifier: ^0.10.0 + version: 0.10.0 broadcast-channel: specifier: 5.1.0 version: 5.1.0 @@ -780,7 +783,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b + version: github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -1078,6 +1081,9 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 + /@assemblyscript/loader@0.27.5: + resolution: {integrity: sha512-DGEJQIKh/pMseal4i26haGutxNfs3nGzwY0MNseoFKcE3DKIXQ25deWpNOqIJQPvjS4FKH+oUpzsTv0oa17+xg==} + /@babel/code-frame@7.22.5: resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} @@ -5411,8 +5417,15 @@ packages: resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} dev: true + /blurhash-as@0.10.0: + resolution: {integrity: sha512-0xkq5uhvdQZfbytKAPtuy3vkkGdsZJxxqL3l6lWIgTIoEdH85jU/0HRENFDH5AW3MwChc6CnfXB4RUvvoRbJeA==} + engines: {node: '>=10'} + dependencies: + '@assemblyscript/loader': 0.27.5 + /blurhash@2.0.5: resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} + dev: true /bmp-js@0.1.0: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} @@ -17486,8 +17499,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b} + github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/d3c8c6a77d4362b3b3180099f1d2eac344ce245c} name: emojilib version: 3.0.10 dev: true From 3b9db11ef2f2532eca343562d7fd805dbfdef644 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 19:00:50 -0700 Subject: [PATCH 113/162] dev76 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2065d40dc..56a33faf2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev75", + "version": "14.0.0-dev76", "codename": "aqua", "repository": { "type": "git", From 12a974de13b133b60c2895874fc48e860570bc4b Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 19:06:57 -0700 Subject: [PATCH 114/162] Revert "refactor: :zap: use blurhash-as for encoding and decoding" This reverts commit ae059881fbc28eb3dc2c90fea3694720b8dda505. --- packages/backend/package.json | 2 +- packages/backend/src/misc/get-file-info.ts | 11 ++------ packages/client/package.json | 1 - .../src/components/MkImgWithBlurhash.vue | 12 ++++----- pnpm-lock.yaml | 25 +++++-------------- 5 files changed, 14 insertions(+), 37 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index b021f3f40..fe8c078a0 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -47,7 +47,7 @@ "aws-sdk": "2.1413.0", "axios": "^1.4.0", "bcryptjs": "2.4.3", - "blurhash-as": "^0.10.0", + "blurhash": "2.0.5", "bull": "4.10.4", "cacheable-lookup": "7.0.0", "calckey-js": "workspace:*", diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 8cc24026d..76964890e 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -10,12 +10,11 @@ import FFmpeg from "fluent-ffmpeg"; import isSvg from "is-svg"; import { type predictionType } from "nsfwjs"; import sharp from "sharp"; -import * as blurhash from "blurhash-as"; +import { encode } from "blurhash"; import { detectSensitive } from "@/services/detect-sensitive.js"; import { createTempDir } from "./create-temp.js"; const pipeline = util.promisify(stream.pipeline); -blurhash.init(); export type FileInfo = { size: number; @@ -433,13 +432,7 @@ function getBlurhash(path: string): Promise<string> { let hash; try { - hash = blurhash.encode( - new Uint8ClampedArray(buffer), - width, - height, - 7, - 7, - ); + hash = encode(new Uint8ClampedArray(buffer), width, height, 7, 7); } catch (e) { return reject(e); } diff --git a/packages/client/package.json b/packages/client/package.json index 014f2f646..95fb9f9b2 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -30,7 +30,6 @@ "autobind-decorator": "2.4.0", "autosize": "5.0.2", "blurhash": "2.0.5", - "blurhash-as": "^0.10.0", "broadcast-channel": "5.1.0", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", "calckey-js": "workspace:*", diff --git a/packages/client/src/components/MkImgWithBlurhash.vue b/packages/client/src/components/MkImgWithBlurhash.vue index 06f7b56a9..5a0cefec2 100644 --- a/packages/client/src/components/MkImgWithBlurhash.vue +++ b/packages/client/src/components/MkImgWithBlurhash.vue @@ -4,12 +4,12 @@ ref="canvas" :width="size" :height="size" - :title="title ?? ''" + :title="title" /> <img v-if="src" :src="src" - :title="title ?? ''" + :title="title" :type="type" :alt="alt" :class="{ cover }" @@ -21,8 +21,7 @@ <script lang="ts" setup> import { onMounted } from "vue"; -import * as blurhash from "blurhash-as/browser"; -import wasmURL from "blurhash-as/build/optimized.wasm?url"; +import { decodeBlurHash } from "fast-blurhash"; const props = withDefaults( defineProps<{ @@ -47,10 +46,9 @@ const props = withDefaults( const canvas = $ref<HTMLCanvasElement>(); let loaded = $ref(false); -async function draw() { +function draw() { if (props.hash == null || canvas == null) return; - blurhash.setURL(wasmURL); - const pixels = await blurhash.decode(props.hash, props.size, props.size); + const pixels = decodeBlurHash(props.hash, props.size, props.size); const ctx = canvas.getContext("2d"); const imageData = ctx!.createImageData(props.size, props.size); imageData.data.set(pixels); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15f08733f..adead9c6f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,9 +147,9 @@ importers: bcryptjs: specifier: 2.4.3 version: 2.4.3 - blurhash-as: - specifier: ^0.10.0 - version: 0.10.0 + blurhash: + specifier: 2.0.5 + version: 2.0.5 bull: specifier: 4.10.4 version: 4.10.4 @@ -736,9 +736,6 @@ importers: blurhash: specifier: 2.0.5 version: 2.0.5 - blurhash-as: - specifier: ^0.10.0 - version: 0.10.0 broadcast-channel: specifier: 5.1.0 version: 5.1.0 @@ -783,7 +780,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c + version: github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -1081,9 +1078,6 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 - /@assemblyscript/loader@0.27.5: - resolution: {integrity: sha512-DGEJQIKh/pMseal4i26haGutxNfs3nGzwY0MNseoFKcE3DKIXQ25deWpNOqIJQPvjS4FKH+oUpzsTv0oa17+xg==} - /@babel/code-frame@7.22.5: resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} @@ -5417,15 +5411,8 @@ packages: resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} dev: true - /blurhash-as@0.10.0: - resolution: {integrity: sha512-0xkq5uhvdQZfbytKAPtuy3vkkGdsZJxxqL3l6lWIgTIoEdH85jU/0HRENFDH5AW3MwChc6CnfXB4RUvvoRbJeA==} - engines: {node: '>=10'} - dependencies: - '@assemblyscript/loader': 0.27.5 - /blurhash@2.0.5: resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==} - dev: true /bmp-js@0.1.0: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} @@ -17499,8 +17486,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/d3c8c6a77d4362b3b3180099f1d2eac344ce245c} + github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b} name: emojilib version: 3.0.10 dev: true From b57f04c709a7e5d36a25534ada5546800b72c8df Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Thu, 13 Jul 2023 19:07:06 -0700 Subject: [PATCH 115/162] dev77 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56a33faf2..b38da39fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev76", + "version": "14.0.0-dev77", "codename": "aqua", "repository": { "type": "git", From cdcdc457dfc059ba6186fff3dc4b329287eeed89 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Fri, 14 Jul 2023 00:14:57 -0400 Subject: [PATCH 116/162] fix: Follow Request labeling resolves #10368 --- locales/en-US.yml | 2 +- packages/backend/src/models/repositories/user.ts | 2 +- packages/client/src/components/MkFollowButton.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 415d87230..1cead0fbf 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -105,7 +105,7 @@ privacy: "Privacy" makeFollowManuallyApprove: "Follow requests require approval" defaultNoteVisibility: "Default visibility" follow: "Follow" -followRequest: "Follow" +followRequest: "Follow Request" followRequests: "Follow requests" unfollow: "Unfollow" followRequestPending: "Follow request pending" diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 5ca36e3d3..e4aab896d 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -453,6 +453,7 @@ export const UserRepository = db.getRepository(User).extend({ isAdmin: user.isAdmin || falsy, isModerator: user.isModerator || falsy, isBot: user.isBot || falsy, + isLocked: user.isLocked, isCat: user.isCat || falsy, speakAsCat: user.speakAsCat || falsy, instance: user.host @@ -497,7 +498,6 @@ export const UserRepository = db.getRepository(User).extend({ : null, bannerBlurhash: user.banner?.blurhash || null, bannerColor: null, // 後方互換性のため - isLocked: user.isLocked, isSilenced: user.isSilenced || falsy, isSuspended: user.isSuspended || falsy, description: profile!.description, diff --git a/packages/client/src/components/MkFollowButton.vue b/packages/client/src/components/MkFollowButton.vue index e8dd63a35..bb0ce0b69 100644 --- a/packages/client/src/components/MkFollowButton.vue +++ b/packages/client/src/components/MkFollowButton.vue @@ -46,7 +46,7 @@ </template> <template v-else-if="!isFollowing && user.isLocked"> <span>{{ (state = i18n.ts.followRequest) }}</span - ><i class="ph-plus ph-bold ph-lg"></i> + ><i class="ph-lock-open ph-bold ph-lg"></i> </template> <template v-else-if="!isFollowing && !user.isLocked"> <span>{{ (state = i18n.ts.follow) }}</span From 774a3fafef102d247aa0adea6ad2899ddb74661c Mon Sep 17 00:00:00 2001 From: jolupa <jolupameister@gmail.com> Date: Thu, 13 Jul 2023 14:29:41 +0000 Subject: [PATCH 117/162] chore: Translated using Weblate (Catalan) Currently translated at 100.0% (1830 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ca/ --- locales/ca-ES.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index f855f6732..a60f514d4 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -2157,3 +2157,6 @@ xl: XL donationLink: Enllaç a la pàgina de donacions neverShow: No tornis a mostrar remindMeLater: Potser després +removeMember: Elimina el membre +removeQuote: Elimina la cita +removeRecipient: Elimina el destinatari From 21ea3f1aad02e170c1076273cd5526646b4c893e Mon Sep 17 00:00:00 2001 From: Erik Spjelkavik <erik.spjelkavik@gmail.com> Date: Thu, 13 Jul 2023 10:44:13 +0000 Subject: [PATCH 118/162] =?UTF-8?q?chore:=20Translated=20using=20Weblate?= =?UTF-8?q?=20(Norwegian=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 4.3% (79 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/nb_NO/ --- locales/no-NO.yml | 83 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/locales/no-NO.yml b/locales/no-NO.yml index 83e189b9c..5f02d5f19 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -1,2 +1,83 @@ ---- _lang_: "Norsk Bokmål" +search: Søk +monthAndDay: '{day}/{month}' +fetchingAsApObject: Henter fra fediverset +ok: OK +gotIt: Jeg forstår! +profile: Profil +timeline: Tidslinje +save: Lagre +addToList: Legg til liste +searchPlaceholder: Søk Calckey +username: Brukernavn +password: Passord +notifications: Meldinger +forgotPassword: Glemt passord +cancel: Avbryt +noNotes: Ingen poster +instance: Server +settings: Innstillinger +noAccountDescription: Denne brukeren har ikke fylt ut bio'en sin ennå. +login: Logg inn +loggingIn: Logger inn +signup: Oppretter bruker +uploading: Laster opp.. +enterUsername: Skriv inn brukernavn +noNotifications: Ingen meldinger +users: Brukere +addUser: Legg til en bruker +favorite: Legg til i bokmerker +cantFavorite: Kunne ikke legges til i bokmerker. +pin: Fest til profilen +copyContent: Kopier innhold +deleteAndEdit: Slett og rediger +sendMessage: Send en melding +copyUsername: Kopier brukernavn +reply: Svar +loadMore: Last mer +showLess: Lukk +receiveFollowRequest: Følgeforespørsel mottatt +directNotes: Direktemelding +importAndExport: Importer/eksporter data +importRequested: Du har bedt om en importering. Dette vil ta litt tid. +lists: Lister +listsDesc: Lister lar deg lage tidslinjer med utvalgte brukere. De kan hentes frem + fra tidslinje-siden. +deleted: Slettet +editNote: Rediger notat +followsYou: Følger deg +createList: Lag liste +newer: nyere +older: eldre +download: Last ned +unfollowConfirm: Er du sikker på at du ikke lenger vil følge {name}? +noLists: Du har ingen lister +following: Følger +files: Filer +note: Post +notes: Poster +followers: Følgere +otherSettings: Andre innstillinger +addInstance: Legg til en server +alreadyFavorited: Allerede lagt til i bokmerker. +delete: Slett +openInWindow: Åpne i vindu +basicSettings: Grunnleggende innstillinger +headlineMisskey: En desentralisert sosialt media-plattform, basert på åpen kildekode, + som alltid vil være gratis! 🚀 +introMisskey: Velkommen! Calckey er en desentralisert sosialt media-plattform, basert + på åpen kildekode, som alltid vil være gratis! 🚀 +exportRequested: Du har bedt om en eksportering. Dette vil ta litt tid. Den vil bli + lagt til på disken din når den er ferdig. +noThankYou: Nei takk +favorites: Bokmerker +unfavorite: Fjern fra bokmerker +favorited: Lagt til i bokmerker. +copyLink: Kopier lenke +searchUser: Søk etter en bruker +jumpToPrevious: Gå til foregående +showMore: Vis mer +followRequestAccepted: Følgeforespørsel godtatt +import: Importer +export: Eksporter +logout: Logger ut From 2dfb2d3833ec757b3a615a1309226584f061b6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Al=C3=A9xia?= <alexiacordeiro@tutanota.com> Date: Thu, 13 Jul 2023 20:10:55 +0000 Subject: [PATCH 119/162] chore: Translated using Weblate (Portuguese (Brazil)) Currently translated at 5.6% (103 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/pt_BR/ --- locales/pt_BR.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/locales/pt_BR.yml b/locales/pt_BR.yml index 2cc22c86a..6a7a1d9e3 100644 --- a/locales/pt_BR.yml +++ b/locales/pt_BR.yml @@ -85,3 +85,10 @@ noLists: Você não possui nenhuma lista following: Seguindo followers: Seguidores followsYou: Segue você +fetchingAsApObject: Buscando do Fediverse +timeline: Linha do tempo +favorite: Adicionar aos marcadores +favorites: Marcadores +unfavorite: Remover dos marcadores +favorited: Adicionado aos marcadores. +alreadyFavorited: Já foi adicionado aos marcadores. From f37fb9cff1c76088d303f9988a45b8a81156dfd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Al=C3=A9xia=20Cordeiro=20Oliveira?= <alexiacordeiro@protonmail.com> Date: Thu, 13 Jul 2023 20:12:34 +0000 Subject: [PATCH 120/162] chore: Translated using Weblate (Portuguese (Brazil)) Currently translated at 5.6% (103 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/pt_BR/ --- locales/pt_BR.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/locales/pt_BR.yml b/locales/pt_BR.yml index 6a7a1d9e3..f991be913 100644 --- a/locales/pt_BR.yml +++ b/locales/pt_BR.yml @@ -92,3 +92,21 @@ favorites: Marcadores unfavorite: Remover dos marcadores favorited: Adicionado aos marcadores. alreadyFavorited: Já foi adicionado aos marcadores. +download: Download +pageLoadError: Ocorreu um erro ao carregar a página. +pageLoadErrorDescription: Isso normalmente é causado por erros de rede ou pelo cache + do navegador. Tente limpar o cache e, depois de esperar um pouquinho, tente novamente. +serverIsDead: Esse servidos não está respondendo. Por favor espere um pouco e tente + novamente. +youShouldUpgradeClient: Para visualizar essa página, favor reiniciar para atualizar + seu cliente. +enterListName: Insira um nome para a lista +privacy: Privacidade +defaultNoteVisibility: Visibilidade padrão +makeFollowManuallyApprove: Pedidos de seguimento precisam de aprovação +follow: Seguir +followRequest: Seguir +followRequests: Pedidos de seguimento +unfollow: Parar de seguir +followRequestPending: Pedido de seguimento pendente +enterEmoji: Insira um emoji From 4e6b212c2fbc70f8b93f3dc8c97f3167a985d484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?jos=C3=A9=20m?= <correoxm@disroot.org> Date: Fri, 14 Jul 2023 03:41:41 +0000 Subject: [PATCH 121/162] chore: Translated using Weblate (Galician) Currently translated at 0.8% (15 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/gl/ --- locales/gl.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/locales/gl.yml b/locales/gl.yml index 0967ef424..891a81927 100644 --- a/locales/gl.yml +++ b/locales/gl.yml @@ -1 +1,17 @@ -{} +_lang_: Inglés +introMisskey: Benvida! Calckey é unha plataforma de medios sociais de código aberto, + descentralizada e gratuíta para sempre!🚀 +monthAndDay: '{day}/{month}' +notifications: Notificacións +password: Contrasinal +forgotPassword: Esquecín o contrasinal +gotIt: Vale! +cancel: Cancelar +noThankYou: Non, grazas +headlineMisskey: Plataforma de medios sociais de código aberto e descentralizada, + gratuíta para sempre!🚀 +search: Buscar +searchPlaceholder: Buscar en Calckey +username: Identificador +fetchingAsApObject: Descargando desde o Fediverso +ok: OK From 38b3e0f14c4f39ce556657b05c68ed49057c617d Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Fri, 14 Jul 2023 00:25:01 -0400 Subject: [PATCH 122/162] fix: error in user card if no user desc --- packages/client/src/components/MkUserInfo.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index 55979a229..76ae8a9cd 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -93,7 +93,7 @@ const props = defineProps<{ }>(); let isLong = $ref( - props.detailed && + props.detailed && props.user.description && (props.user.description.split("\n").length > 9 || props.user.description.length > 400), ); From 8c1feb363fe937b9802377a0a92b0c3af75ef909 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Fri, 14 Jul 2023 15:31:31 -0400 Subject: [PATCH 123/162] refactor: remove tinycolor from MkFolder + a11y --- packages/client/src/components/MkFolder.vue | 55 +++++++-------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/packages/client/src/components/MkFolder.vue b/packages/client/src/components/MkFolder.vue index bf08ac24a..5acdffe4c 100644 --- a/packages/client/src/components/MkFolder.vue +++ b/packages/client/src/components/MkFolder.vue @@ -1,13 +1,16 @@ <template> - <div v-size="{ max: [500] }" class="ssazuxis"> + <section class="ssazuxis"> <header class="_button" - :style="{ background: bg }" @click="showBody = !showBody" > <div class="title"><slot name="header"></slot></div> <div class="divider"></div> - <button class="_button"> + <button + class="_button" + :aria-expanded="showBody" + :aria-controls="bodyId" + > <template v-if="showBody" ><i class="ph-caret-up ph-bold ph-lg"></i ></template> @@ -23,16 +26,16 @@ @leave="leave" @after-leave="afterLeave" > - <div v-show="showBody"> + <div v-show="showBody" :id="bodyId"> <slot></slot> </div> </transition> - </div> + </section> </template> <script lang="ts"> import { defineComponent } from "vue"; -import tinycolor from "tinycolor2"; +import { getUniqueId } from "@/os"; const localStoragePrefix = "ui:folder:"; @@ -51,7 +54,7 @@ export default defineComponent({ }, data() { return { - bg: null, + bodyId: getUniqueId(), showBody: this.persistKey && localStorage.getItem(localStoragePrefix + this.persistKey) @@ -71,27 +74,6 @@ export default defineComponent({ } }, }, - mounted() { - function getParentBg(el: Element | null): string { - if (el == null || el.tagName === "BODY") return "var(--bg)"; - const bg = el.style.background || el.style.backgroundColor; - if (bg) { - return bg; - } else { - return getParentBg(el.parentElement); - } - } - const rawBg = getParentBg(this.$el); - const bg = tinycolor( - rawBg.startsWith("var(") - ? getComputedStyle(document.documentElement).getPropertyValue( - rawBg.slice(4, -1), - ) - : rawBg, - ); - bg.setAlpha(0.85); - this.bg = bg.toRgbString(); - }, methods: { toggleContent(show: boolean) { this.showBody = show; @@ -161,6 +143,15 @@ export default defineComponent({ transparent ); + &::before { + content: ""; + position: absolute; + inset: 0; + background: var(--bg); + opacity: 0.85; + z-index: -1; + } + > .title { margin: 0; padding: 12px 16px 12px 0; @@ -185,13 +176,5 @@ export default defineComponent({ padding: 12px 0 12px 16px; } } - - &.max-width_500px { - > header { - > .title { - padding: 8px 10px 8px 0; - } - } - } } </style> From c4ad88ca98651e7774fa353f7facef1715f4d058 Mon Sep 17 00:00:00 2001 From: naskya <naskya@noreply.codeberg.org> Date: Fri, 14 Jul 2023 21:48:13 +0000 Subject: [PATCH 124/162] nowrap tab texts in MkNoteDetailed --- packages/client/src/components/MkNoteDetailed.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue index 7b571d8b2..3dfac1f0c 100644 --- a/packages/client/src/components/MkNoteDetailed.vue +++ b/packages/client/src/components/MkNoteDetailed.vue @@ -33,7 +33,12 @@ detailedView ></MkNote> - <MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab"> + <MkTab + v-model="tab" + style="white-space: nowrap" + :style="'underline'" + @update:modelValue="loadTab" + > <option value="replies"> <!-- <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> --> <span v-if="note.repliesCount > 0" class="count">{{ From 47d13dd542c8b730c0659f85c2f8f5443a449780 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 16:51:21 -0700 Subject: [PATCH 125/162] refactor: :children_crossing: filter out https on recommended instances --- locales/ca-ES.yml | 2 +- locales/en-US.yml | 2 +- locales/fr-FR.yml | 3 +-- locales/ja-JP.yml | 2 +- locales/ru-RU.yml | 2 +- locales/zh-TW.yml | 2 +- .../src/server/api/endpoints/admin/update-meta.ts | 10 ++++++++++ 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index f855f6732..091dde9d7 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1382,7 +1382,7 @@ adminCustomCssWarn: Aquesta configuració només s'ha d'utilitzar si sabeu què showUpdates: Mostra una finestra emergent quan Calckey s'actualitzi recommendedInstances: Servidors recomanats recommendedInstancesDescription: Servidors recomanats separats per salts de línia - que apareixen a la línia de temps recomanada. NO afegiu `https://`, NOMÉS el domini. + que apareixen a la línia de temps recomanada. caption: Descripció Automàtica splash: Pantalla de Benvinguda swipeOnDesktop: Permet lliscar a l'estil del mòbil a l'escriptori diff --git a/locales/en-US.yml b/locales/en-US.yml index 415d87230..58c966cad 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1050,7 +1050,7 @@ customSplashIconsDescription: "URLs for custom splash screen icons separated by showUpdates: "Show a popup when Calckey updates" recommendedInstances: "Recommended servers" recommendedInstancesDescription: "Recommended servers separated by line breaks to - appear in the recommended timeline. Do NOT add `https://`, ONLY the domain." + appear in the recommended timeline." caption: "Auto Caption" splash: "Splash Screen" updateAvailable: "There might be an update available!" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 633b393ff..f81ef4520 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1952,8 +1952,7 @@ antennaInstancesDescription: Lister un hôte d'instance par ligne userSaysSomethingReason: '{name} a dit {reason}' breakFollowConfirm: Êtes vous sur de vouloir retirer l'abonné ? recommendedInstancesDescription: Instances recommandées séparées par une nouvelle - ligne pour apparaître dans la timeline recommandée. Ne PAS ajouter `https://`, SEULEMENT - le domaine. + ligne pour apparaître dans la timeline recommandée. sendPushNotificationReadMessage: Supprimer les notifications push une fois que les notifications ou messages concernés ont été lus sendPushNotificationReadMessageCaption: Une notification contenant le texte "{emptyPushNotificationMessage}" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fe03d1f41..0e8fab2c0 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -946,7 +946,7 @@ customSplashIconsDescription: "ユーザがページをロード/リロードす URL。画像は静的なURLで、できればすべて192x192にリサイズしてください。" showUpdates: "Calckeyの更新時にポップアップを表示する" recommendedInstances: "おすすめサーバー" -recommendedInstancesDescription: "おすすめタイムラインに表示するサーバーを改行区切りで入力してください。`https://`は書かず、ドメインのみを入力してください。" +recommendedInstancesDescription: "おすすめタイムラインに表示するサーバーを改行区切りで入力してください。" caption: "自動キャプション" splash: "スプラッシュスクリーン" updateAvailable: "アップデートがありますよ!" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 8b3e05a17..bfef68d10 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1847,7 +1847,7 @@ customMOTDDescription: Пользовательские сообщения дл разрывами строк, будут отображаться случайным образом каждый раз, когда пользователь загружает / перезагружает страницу. recommendedInstancesDescription: Рекомендуемые инстансы, разделенные разрывами строк, - должны отображаться на рекомендуемой ленте. НЕ добавляйте `https://`, ТОЛЬКО домен. + должны отображаться на рекомендуемой ленте. caption: Автоматическая подпись splash: Заставка updateAvailable: Возможно, доступно обновление! diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 2803d7846..d1bad4ad1 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1839,7 +1839,7 @@ pushNotification: 推送通知 subscribePushNotification: 啟用推送通知 unsubscribePushNotification: 禁用推送通知 pushNotificationAlreadySubscribed: 推送通知已經啟用 -recommendedInstancesDescription: 以每行分隔的推薦伺服器出現在推薦的時間線中。 不要添加 `https://`,只添加域名。 +recommendedInstancesDescription: 以每行分隔的推薦伺服器出現在推薦的時間線中。 searchPlaceholder: 在聯邦網路上搜尋 cw: 內容警告 selectChannel: 選擇一個頻道 diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 16e49a85a..ce2c5c802 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -221,6 +221,16 @@ export default define(meta, paramDef, async (ps, me) => { if (Array.isArray(ps.recommendedInstances)) { set.recommendedInstances = ps.recommendedInstances.filter(Boolean); + if (set.recommendedInstances?.length > 0) { + set.recommendedInstances.forEach((instance, index) => { + if (/^https?:\/\//i.test(instance)) { + set.recommendedInstances![index] = instance.replace( + /^https?:\/\//i, + "", + ); + } + }); + } } if (Array.isArray(ps.hiddenTags)) { From d0058174bc470678a2dd5637ce47905ce6a36b56 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 16:51:49 -0700 Subject: [PATCH 126/162] chore: :art: format --- packages/client/src/components/MkFolder.vue | 7 ++----- packages/client/src/components/MkUserInfo.vue | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/client/src/components/MkFolder.vue b/packages/client/src/components/MkFolder.vue index 5acdffe4c..4bd490de9 100644 --- a/packages/client/src/components/MkFolder.vue +++ b/packages/client/src/components/MkFolder.vue @@ -1,12 +1,9 @@ <template> <section class="ssazuxis"> - <header - class="_button" - @click="showBody = !showBody" - > + <header class="_button" @click="showBody = !showBody"> <div class="title"><slot name="header"></slot></div> <div class="divider"></div> - <button + <button class="_button" :aria-expanded="showBody" :aria-controls="bodyId" diff --git a/packages/client/src/components/MkUserInfo.vue b/packages/client/src/components/MkUserInfo.vue index 76ae8a9cd..843cf65e9 100644 --- a/packages/client/src/components/MkUserInfo.vue +++ b/packages/client/src/components/MkUserInfo.vue @@ -93,7 +93,8 @@ const props = defineProps<{ }>(); let isLong = $ref( - props.detailed && props.user.description && + props.detailed && + props.user.description && (props.user.description.split("\n").length > 9 || props.user.description.length > 400), ); From 12365f15a526644fdd7a1264265c991c9a9193b7 Mon Sep 17 00:00:00 2001 From: jolupa <jolupameister@gmail.com> Date: Fri, 14 Jul 2023 04:51:08 +0000 Subject: [PATCH 127/162] chore: Translated using Weblate (Catalan) Currently translated at 100.0% (1830 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ca/ --- locales/ca-ES.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index a60f514d4..9ff2bbd86 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -95,7 +95,7 @@ privacy: "Privadesa" makeFollowManuallyApprove: "Les sol·licituds de seguiment requereixen aprovació" defaultNoteVisibility: "Visibilitat per defecte" follow: "Segueix" -followRequest: "Segueix" +followRequest: "Sol·licitud de Seguiment" followRequests: "Sol·licituds de seguiment" unfollow: "Deixa de seguir" followRequestPending: "Sol·licituds de seguiment pendents" From 97f9357c7e5a6454dd5df69427688e535b7e5ab7 Mon Sep 17 00:00:00 2001 From: naskya <m@naskya.net> Date: Fri, 14 Jul 2023 18:47:04 +0000 Subject: [PATCH 128/162] chore: Translated using Weblate (Japanese) Currently translated at 100.0% (1830 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ja/ --- locales/ja-JP.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fe03d1f41..64a3ca9ca 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1070,6 +1070,10 @@ _aboutMisskey: morePatrons: "他にも多くの方が支援してくれています。ありがとうございます! 🥰" patrons: "支援者" patronsList: 寄付額ではなく時系列順に並んでいます。上記のリンクから寄付を行ってここにあなたのIDを載せましょう! + pleaseDonateToCalckey: Calckey開発への寄付をご検討ください。 + pleaseDonateToHost: また、このサーバー {host} の運営者への寄付もご検討ください。 + donateHost: '{host} に寄付する' + donateTitle: Calckeyを気に入りましたか? _nsfw: respect: "閲覧注意のメディアは隠す" ignore: "閲覧注意のメディアを隠さない" @@ -1950,3 +1954,8 @@ removeReaction: リアクションを取り消す alt: 代替テキスト swipeOnMobile: ページ間のスワイプを有効にする reactionPickerSkinTone: 優先する絵文字のスキン色 +xl: 特大 +donationLink: 寄付ページへのリンク +removeMember: メンバーを削除 +removeQuote: 引用を削除 +removeRecipient: 宛先を削除 From 00052e956262e37c28bd20bf3065ca5ae420e36a Mon Sep 17 00:00:00 2001 From: Rauf <raufsen11@gmail.com> Date: Fri, 14 Jul 2023 13:42:43 +0000 Subject: [PATCH 129/162] chore: Translated using Weblate (Turkish) Currently translated at 54.4% (996 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/tr/ --- locales/tr-TR.yml | 1030 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1030 insertions(+) diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index a0a45f34c..d6fecb6e8 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -81,3 +81,1033 @@ headlineMisskey: Sonsuza kadar ücretsiz, açık kaynak kodlu, merkeziyetsiz sos loadMore: Daha fazla yükle instance: Sunucu fetchingAsApObject: Fedevren'den çekiliyor +removeReaction: Tepkini sil +rememberNoteVisibility: Gönderi görünürlüğü ayarlarını hatırla +attachCancel: Eklentiyi kaldır +suspend: Askıya Al +unsuspend: Askıya Almayı Kaldır +unmute: Susturmayı Kaldır +blockConfirm: Bu hesabı engellemek istediğinize emin misiniz? +unblockConfirm: Bu hesabın engelini kaldırmak istediğinize emin misiniz? +settingGuide: Tavsiye edilen ayarlar +cacheRemoteFilesDescription: Bu ayar devre dışı bırakıldığında, uzak dosyalar doğrudan + uzak sunucudan yüklenir. Bunun devre dışı bırakılması depolama kullanımını azaltacak, + ancak küçük resimler oluşturulmayacağından trafiği artıracaktır. +flagAsCatDescription: Kedi kulaklarına sahip olacak ve bir kedi gibi konuşacaksın! +flagSpeakAsCat: Kedi gibi konuş +setWallpaper: Arkaplan ayarla +removeWallpaper: Arkaplanı sil +operations: Operasyonlar +clearCachedFiles: Ön belleği temizle +clearCachedFilesConfirm: Önbelleğe alınan tüm uzak dosyaları silmek istediğinizden + emin misiniz? +blockedInstancesDescription: Engellemek istediğiniz sunucuların ana bilgisayar adlarını + listeleyin. Listelenen sunucular artık bu sunucularla iletişim kuramayacak. +blockedUsers: Engellenmiş kullanıcılar +editProfile: Profilini düzenle +intro: Calckey'in indirilmesi tamamlandı! Lütfen yönetici hesap oluşturun. +instanceUsers: Sunucunun kullanıcıları +changePassword: Şifreyi değiştir +security: Güvenlik +newPasswordRetype: Yeni şifreyi tekrarla +uploadFromUrlRequested: Yükleme istendi +syncDeviceDarkMode: Karanlık modu cihazının ayarları ile senkronize et +renameFolder: Bu klasörü yeniden adlandır +emptyFolder: Bu klasör boş +unableToDelete: Silinemiyor +inputNewDescription: Yeni başlık gir +hasChildFilesOrFolders: Bu klasör boş olduğundan silinemez. +disconnectedFromServer: Sunucuyla bağlantı kesildi +reload: Yenile +disablingTimelinesInfo: Yöneticiler ve Moderatörler, etkinleştirilmemiş olsalar bile + tüm zaman çizelgelerine her zaman erişebilir. +pinnedUsersDescription: '"Keşfet" sekmesinde sabitlenecek kullanıcı adlarını satır + sonlarıyla ayırarak listeleyin.' +pinnedPages: Sabitlenmiş Sayfalar +pinnedPagesDescription: Bu sunucunun üst sayfasına sabitlemek istediğiniz Sayfaların + yollarını satır sonları ile ayırarak girin. +enableHcaptcha: hCaptcha'yı Aktif Et +notifyAntenna: Yeni gönderileribildir +recentlyUpdatedUsers: En son aktif kullanıcılar +about: Hakkında +twoStepAuthentication: İki-adımlı doğrulama +securityKeyName: Key name +help: Yardım +inputMessageHere: Mesajını buraya gir +ownedGroups: Gruplarım +joinedGroups: Katılınmış gruplar +invites: Davetler +members: Kullanıcılar +transfer: Transfer +messagingWithGroup: Grup sohbeti +next: Sonraki +retype: Tekrar gir +dashboard: Panel +objectStorageBucket: Bucket +objectStorageBucketDesc: Sağlayıcınız tarafından kullanınan bucket ismini yazın. +showFixedPostForm: Gönderim formunu zaman çizelgesinin en üstünde görüntüleyin +newNoteRecived: Yeni gönderiler mevcut +none: Hiçbiri +details: Detaylar +recentUsed: Son kullanılan +installedApps: Yetkilendirilmiş Uygulamalar +removeAllFollowing: Takip edilen herkesi çıkar +yourAccountSuspendedDescription: Bu hesap, sunucunun hizmet şartlarını veya benzerlerini + ihlal ettiği için askıya alındı. Daha ayrıntılı bir neden öğrenmek istiyorsanız + yöneticiyle iletişime geçin. Lütfen yeni bir hesap oluşturmayın. +addedRelays: Eklenen Röleler +serviceworkerInfo: Push bildirimleri için aktif olması gerekiyor. +author: Sahip +tokenRequested: Hesaba erişim ver +useFullReactionPicker: Tam boyutunda tepki seçici kullan +small: Küçük +enableAll: Hepsine izin ver +disableAll: Hepsini kapat +regexpError: Regex hatası +emailConfigInfo: Kayıt sırasında veya şifrenizi unutursanız e-postanızı onaylamak + için kullanılır +smtpSecure: SMTP bağlantıları için SSL/TSL kullan +regexpErrorDescription: '{tab} kelimenizin {line} satırındaki normal ifadede bir hata + oluştu:' +instanceMute: Sunucu Susturmaları +reporter: Rapor eden +userSaysSomethingReason: '{name}, {reason} söyledi' +userSaysSomethingReasonRenote: '{name}, {reason} içeren bir gönderiyi öne çıkardı' +userSaysSomethingReasonQuote: '{name}, {reason} içeren bir gönderiden alıntı yaptı' +notificationSettingDesc: Görünecek bildirimleri seç. +other: Diğer +sample: Örnek +notSet: Ayarlanmadı +emailVerified: Mail doğrulandı +showGapBetweenNotesInTimeline: Zaman tünelinde gönderiler arasındaki boşluğu göster +sendErrorReports: Hata raporları gönder +followingCount: Takip edilen hesap sayısı +no: Hayır +myTheme: Temam +backgroundColor: Arkaplan rengi +accentColor: Vurgu rengi +textColor: Yazı rengi +createdAt: Oluşturuldu +updatedAt: Güncellendi +saveConfirm: Kaydet? +registry: Kayıt +currentVersion: Şuanki Sürüm +accountDeletionInProgress: Hesap silme şu anda devam ediyor +unresolved: Çözülmedi +newVersionOfClientAvailable: Yeni istemci sürümü mevcut. +shareWithNote: Gönderi ile paylaş +whatIsNew: Değişiklikleri göster +translate: Çevir +breakFollow: Takipçiyi sil +breakFollowConfirm: Takipçiyi kaldırmak istediğinizden emin misiniz? +unfollowConfirm: "{name}'i takibi bırakmak istediğinizden emin misiniz?" +importRequested: Bir içe aktarma isteğinde bulundunuz. Bu biraz zaman alabilir. +somethingHappened: Bir hata ile karşılaşıldı +retry: Tekrar Dene +youShouldUpgradeClient: Bu sayfayı görüntülemek için, lütfen istemcinizi güncelleyin. +reactionSetting: Tepki seçicide gösterilecek tepkiler +unmarkAsSensitive: NSFW işaretini kaldır +enterFileName: Dosya adı gir +noJobs: Hiçbir iş yok +instanceFollowing: Sunucuda takip ediliyor +instanceFollowers: Sunucunun takipçileri +currentPassword: Şuanki şifre +newPassword: Yeni şifre +saved: Kaydedildi +uploadFromUrlDescription: Yüklemek istediğiniz dosyanın URL'si +noMoreHistory: Başka geçmiş yok +startMessaging: Yeni sohbet oluştur +manageGroups: Grupları düzenle +nUsersRead: '{n} tarafından okundu' +images: Görseller +birthday: Doğumgünü +light: Aydınlık +dark: Karanlık +lightThemes: Aydınlık temalar +selectFiles: Dosyalar seç +selectFolders: Klasörler seç +renameFile: Dosyayı yeniden adlandır +folderName: Klasör adı +createFolder: Klasör oluştur +copyUrl: URL'yi Kopyala +maintainerName: Sahip +maintainerEmail: Sahibin e-postası +tosUrl: Kullanım Koşulları URL'si +monthX: '{month}' +basicInfo: Basit bilgi +pinnedUsers: Sabitlenmiş kullanıcılar +manageAntennas: Antenleri Düzenle +name: İsim +silence: Sustur +unsilence: Susturmayı geri al +exploreUsersCount: '{count} Kullanıcı var' +exploreFediverse: Fediversi keşfet +popularTags: Popüler etiketler +close: Kapat +group: Grup +text: Yazı +checking: Doğrulanıyor... +tooLong: Çok uzun +weakPassword: Zayıf şifre +normalPassword: Ortalama şifre +disableDrawer: Çekmece tarzı menüler kullanmayın +youHaveNoGroups: Grupların yok +joinOrCreateGroup: Bir gruba davet edil veya kendininkini oluştur. +regenerate: Yeniden Oluştur +fontSize: Yazı boyutu +noFollowRequests: Bekleyen takip isteğiniz yok +openImageInNewTab: Resmi yeni sekmede aç +useObjectStorage: Object Storage kullan +objectStorageUseProxy: Proxy üzerinden bağlan +installedDate: Yetkilendirilme tarihi +scratchpad: Karalama Defteri +deleteAllFiles: Tüm dosyaları isl +useCw: İçeriği gizle +plugins: Eklentiler +manage: Yönetmek +preferencesBackups: Tercih yedekleri +generateAccessToken: Erişim tokeni oluştur +enableEmail: E-posta dağıtımını etkinleştir +regenerateLoginToken: Giriş tokenini yeniden oluştur +regenerateLoginTokenDescription: Oturum açma sırasında dahili olarak kullanılan belirteci + yeniden oluşturur. Normalde bu eylem gerekli değildir. Yeniden oluşturulursa, tüm + cihazların oturumu kapatılacaktır. +followersCount: Takipçi sayısı +yes: Evet +lockedAccountInfo: Gönderi görünürlüğünüzü "Yalnızca takipçiler" olarak ayarlamazsanız, + takipçilerin manuel olarak onaylanmasını isteseniz bile gönderileriniz herkes tarafından + görülebilir. +unlikeConfirm: Beğeniyi kaldırmak istiyor musunuz? +notSpecifiedMentionWarning: Bu gönderi, alıcı olarak dahil edilmeyen kullanıcılardan + bahsetmektedir. +hideOnlineStatus: Çevrimiçi bilgisini gizle +hideOnlineStatusDescription: Çevrimiçi durumunuzu gizlemek, arama gibi bazı özelliklerin + rahatlığını azaltır. +botProtection: Bot Koruması +selectAccount: Hesap seç +recentPosts: En son sayfalar +high: Yüksek +middle: Orta +secureModeInfo: Diğer sunuculardan talepte bulunurken kanıtlamadan geri göndermeyiniz. +previewNoteText: Önizlemeyi göster +customCss: Özel CSS +global: Global +makeReactionsPublic: Tepki geçmişini herkese açık olarak ayarla +clickToFinishEmailVerification: Mail doğrulamasını tamamlamak için lütfen [{ok}]'a + tıklayın. +overridedDeviceKind: Cihaz tipi +smartphone: Akıllı telefon +tablet: Tablet +auto: Otomatik +tenMinutes: 10 dakika +recentNDays: Son {n} gün +noEmailServerWarning: Mail sunucusu ayarlanmadı. +thereIsUnresolvedAbuseReportWarning: Çözülmemiş raporlar var. +statusbar: Durum çubuğu +pleaseSelect: Bir seçenek seçin +lastActiveDate: Son kullanılan +reverse: Tersi +logoutConfirm: Gerçekten oturum kapatılsın mı? +type: Tip +speed: Hız +slow: Yavaş +activeEmailValidationDescription: Tek kullanımlık adreslerin kontrol edilmesi ve gerçekten + iletişim kurup kurulamayacağına göre e-posta adreslerinin daha sıkı doğrulanmasını + sağlar. İşaretlenmediğinde, yalnızca e-postanın biçimi doğrulanır. +move: Taşı +defaultReaction: Giden ve gelen gönderiler için varsayılan emoji tepkisi +indexPosts: Dizin Gönderileri +youGotNewFollower: takip etti +receiveFollowRequest: Takip isteği alındı +followRequestAccepted: Takip isteği onaylandı +mention: Bahset +download: İndir +lists: Listeler +noLists: Hiç listen yok +cantRenote: Bu gönderi yükseltilemez. +cantReRenote: Yükseltme yükseltilemez. +mute: Sustur +block: Engelle +editWidgetsExit: Tamamlandı +customEmojis: Özel Tepki +cpuAndMemory: İşlemci ve Bellek +selectInstance: Sunucu seç +instances: Sunucular +silencedInstancesDescription: Susturmak istediğiniz sunucuların ana bilgisayar adlarını + listeleyin. Listelenen sunuculardaki hesaplar "Sessiz" olarak değerlendirilir, yalnızca + takip istekleri yapabilir ve takip edilmediği takdirde yerel hesaplardan bahsedemez. + Bu, engellenen sunucuları etkilemeyecektir. +muteAndBlock: Susturmalar ve Engeller +noteDeleteConfirm: Bu gönderiyi silmek istediğine emin misin? +resetAreYouSure: Gerçekten sıfırla? +remoteUserCaution: Uzak kullanıcılardan gelen bilgiler eksik olabilir. +yearsOld: '{age} yaşında' +removed: Başarıyla silindi +reject: Reddet +unwatch: İzlemeyi bırak +accept: Kabul et +normal: Normal +thisMonth: Ay +enableRecaptcha: reCAPTCHA'yı Aktif Et +antennas: Antenler +recaptchaSiteKey: Site key +withFileAntenna: Sadece dosyalı gönderiler +antennaInstancesDescription: Sunucu başı bir satır kullanın +moderator: Moderatör +moderation: Moderasyon +lastUsed: En son kullanılan +unregister: Kaydı sil +passwordLessLogin: Şifresiz giriş +uploadFolder: Yüklemeler için varsayılan klasör +markAsReadAllUnreadNotes: Tüm gönderileri okundu olarak işaretle +notFound: Bulunamadı +groups: Gruplar +quoteQuestion: Alıntı olarak eklensin mi? +signinRequired: Lütfen devam etmeden önce kayıt olun +noMessagesYet: Şuana kadar mesaj yok +newMessageExists: Yeni mesaj yok +invitations: Davetler +invitationCode: Davet kodu +signinWith: '{x} ile giriş yap' +strongPassword: Güçlü şifre +passwordNotMatched: Uyuşmuyor +signinFailed: Giriş yapılamadı. Şifre ve ya kullanıcı adı yanlış. +tapSecurityKey: Güvenlik anahtarınıza dokunun +or: veya +noHistory: Geçmiş bulunamadı +language: Dil +clientSettings: İstemci Ayarları +accountSettings: Hesap Ayarları +listen: Dinle +chooseEmoji: Emoji seç +promotion: Terfi Edildi +nothing: Burada görüntülenecek bir şey yok +lastUsedDate: Son kullanılma tarihi +updateRemoteUser: Uzak kullanıcı bilgilerini güncelle +width: Genişlik +height: Uzunluk +permission: İzinler +email: Mail +smtpSecureInfo: STARTTLS kullanırken bunu kapatın +alwaysMarkSensitive: Varsayılan olarak NSFW olarak işaretle +noteFavoritesCount: İşaretlenen gönderilerin sayısı +pageLikesCount: Beğenilen Sayfaların sayısı +duplicate: Kopyasını Oluştur +clearCache: Önbelleği Temizle +onlineUsersCount: '{n} kullanıcı aktif' +nUsers: '{n} Kullanıcı' +nNotes: '{n} Gönderi' +useReactionPickerForContextMenu: Sağ tık ile tepki seçiciyi aç +typingUsers: '{users} yazıyor' +jumpToSpecifiedDate: Spesifik tarihe atla +showingPastTimeline: Şuan eski bir zaman çizelgesini görüntülüyorsunuz +clear: Temizle +fullView: Tam görünüm +emailNotConfiguredWarning: Mail adresi seçilmedi. +privateMode: Özel Mod +fast: Hızlı +learnMore: Daha fazla bilgi edin +localOnly: Sadece yerel +delayed: Ertelenmiş +useGlobalSetting: Global ayaralrı kullan +switchAccount: Hesap değiştir +notRecommended: Tavsiye edilmiyor +onlineStatus: Çevrimiçi bilgisi +active: Aktif +instanceBlocking: Federasyon Yönetmek +enabled: Aktif +disabled: Deaktif +quickAction: Hızlı işlemler +configure: Yapılandır +blockedInstances: Engellenmiş Sunucular +silencedInstances: Susturulmuş Sunucular +lookup: Görüntüle +inputNewFolderName: Yeni klasör ismi gir +noteOf: Gönderi {user} tarafından +onlyOneFileCanBeAttached: Bir mesaja sadece 1 dosya ekleyebilirsin +install: İndir +uninstall: kALDIR +send: Gönder +noCrawleDescription: Arama motorlarından profil sayfanızı, gönderilerinizi, Sayfalarınızı + vb. indekslememesini isteyin. +emailNotification: Mail bildirimleri +goBack: Geri +online: Çevrimiçi +translatedFrom: "{x}'den çevrildi" +cropImage: Resmi kırp +deleteAccount: Hesabı Sil +navbar: Gezinti çubuğu +account: Hesap +instanceDefaultThemeDescription: Tema kodunu nesne biçiminde girin. +alt: ALT +mutePeriod: Sessiz süresi +indefinitely: Kalıcı olarak +oneHour: Bir saat +oneWeek: Bir hafta +colored: Renkli +sensitiveMediaDetection: Resim NSFW Belirleme +subscribePushNotification: Push bildirimlerini aktif et +pushNotificationAlreadySubscribed: Push bildirimler zaten açık +sendPushNotificationReadMessage: İlgili bildirimler veya mesajlar okunduktan sonra + push bildirimlerini silin +sendPushNotificationReadMessageCaption: Kısa bir süre için "{emptyPushNotificationMessage}" + metnini içeren bir bildirim görüntülenecektir. Bu, mümkünse cihazınızın pil kullanımını + artırabilir. +enterSendsMessage: Mesaj göndermek için Mesajlaşma'da Geri Dön'e basın (Ctrl + Return) +customMOTDDescription: Bir kullanıcı sayfayı her yüklediğinde/yeniden yüklediğinde + rastgele gösterilecek satır sonlarıyla ayrılmış MOTD (açılış ekranı) için özel mesajlar. +customSplashIconsDescription: Bir kullanıcı sayfayı her yüklediğinde/yeniden yüklediğinde + rastgele gösterilecek satır sonlarıyla ayrılmış özel açılış ekranı simgeleri için + URL'ler. Lütfen resimlerin statik bir URL'de olduğundan ve tercihen tümü 192x192 + olarak yeniden boyutlandırıldığından emin olun. +updateAvailable: Bir güncelleme mevcut olabilir! +splash: Açılış Ekranı +moveTo: Şimdiki hesabını yeni bir hesaba taşı +swipeOnMobile: Sayfalar arasında kaydırmaya izin ver +swipeOnDesktop: Masaüstünde mobil stil kaydırmaya izin ver +migration: Taşıma +moveAccount: Hesabını taşı! +moveFrom: Daha eski bir hesaptan bu hesaba taşıyın +moveFromLabel: 'Taşındığınız hesap:' +importAndExport: İçeri/Dışarı Aktar +manageLists: Listeleri düzenle +error: Hata +pageLoadError: Sayfayı yüklerken bir hata ile karşılaşıldı. +serverIsDead: Sunucu yanıt vermiyor. Biraz bekleyip tekrar deneyin. +defaultNoteVisibility: Varsayılan görünürlük +follow: Takip et +reactionSettingDescription2: Yeniden sıralamak için sürükleyin, silmek için tıklayın, + eklemek için "+"ya basın. +you: Sen +clickToShow: Görmek için tıkla +sensitive: NSFW +add: Ekle +reaction: Tepkiler +markAsSensitive: NSFW olarak işaretle +unblock: Engeli Kaldır +addAccount: Hesap ekle +network: İnternet +disk: Depolama +instanceInfo: Sunucu Bilgisi +statistics: İstatistikler +hiddenTagsDescription: Trendlerden gizlemek ve keşfetmek istediğiniz etiketlerin (# + olmadan)etiketlerini listeleyin. Gizli etiketler başka yollarla keşfedilebilir. +mutedUsers: Susturulmuş kullanıcılar +uploadFromUrlMayTakeTime: Yüklemenin tamamlanması zaman alabilir. +activity: Aktivite +theme: Temalar +themeForLightMode: Aydınlık modda kullanmak için temalar +reloadConfirm: Zaman çizelgesini yenilemek ister misiniz? +instanceName: Sunucu adı +circularReferenceFolder: Hedef klasör, taşımak istediğiniz klasörün bir alt klasörüdür. +instanceDescription: Sunucu açıklaması +driveCapacityPerLocalAccount: Kullanıcı başı Driver kapasitesi +driveCapacityPerRemoteAccount: Uzak kullanıcı başı Driver kapasitesi +inMb: Megabayt cinsinden +pinnedClipId: Sabitlenecek atacın ID'si +withFiles: Dosyaları içer +recentlyRegisteredUsers: Yeni katılmış kullanıcılar +recentlyDiscoveredUsers: Yeni keşfedilmiş kullanıcılar +nUsersMentioned: '{n} kullanıcı tarafından bahsedildi' +securityKey: Security key +title: Başlık +total: Toplam +sounds: Sesler +objectStorageRegionDesc: "'xx-east-1' gibi bir bölge belirtin. Hizmetiniz bölgeler + arasında ayrım yapmıyorsa, bunu boş bırakın veya 'us-east-1' girin." +objectStorageUseSSL: SSL Kullan +popout: Açılır Pencere +volume: Ses +showInPage: Sayfada göster +masterVolume: Ana ses +undeck: Desteden çık +useBlurEffectForModal: Modallar için bulanıklık efekti uygula +leaveConfirm: Kaydedilmemiş değişiklikler var. Devam etmek istiyor musunuz? +testEmail: Email dağıtımını test et +wordMute: Kelime susturması +userSaysSomething: '{name} bir şey söyledi' +channel: Kanallar +create: Oluştur +useGlobalSettingDesc: Açıksa, hesap bildirim ayarlarınız kullanılacaktır. Kapatılırsa, + bireysel yapılandırmalar yapılabilir. +setMultipleBySeparatingWithSpace: Birden çok girişi boşluklarla ayırın. +fileIdOrUrl: Dosya ID veya URL'si +behavior: Davranış +abuseReported: Raporunuz gönderildi. Teşekkürler. +reporteeOrigin: Ana Raporcu +reporterOrigin: Ana Rapor Eden +defaultNavigationBehaviour: Varsayılan gezinme davranışı +editTheseSettingsMayBreakAccount: Bunları düzenlemek hesabınıza zarar verebilir. +renotedCount: Alınan yükseltme sayısı +driveFilesCount: Drive dosya sayısı +deleteConfirm: Sil? +invalidValue: Geçersiz değer. +instanceSecurity: Sunucu Güvenliği +searchResult: Arama sonuçları +useBlurEffect: Kullanıcı arayüzünde bulanıklaştırma efektleri kullanın +misskeyUpdated: Calckey güncellendi! +lastCommunication: Son iletişim +itsOn: Etkinleştirilmiş +emailRequiredForSignup: Kayıt olmak için mail gerekiyor +leaveGroup: Gruptan ayrıl +useDrawerReactionPickerForMobile: Reaksiyon seçiciyi mobil cihazda çekmece olarak + göster +leaveGroupConfirm: '"{name}"den ayrılmak istediğinizden emin misiniz?' +instanceDefaultLightTheme: Sunucu genelinde varsayılan aydınlık tema +document: Dökümanlar +numberOfPageCacheDescription: Bu sayının arttırılması, kullanıcılar için kolaylık + sağlayacaktır ancak daha fazla sunucu yükünün yanı sıra daha fazla bellek kullanılmasına + neden olacaktır. +refreshInterval: 'Güncelleme aralığı ' +label: Etiket +replayTutorial: Eğiticiyi tekrar oynat +moveAccountDescription: Bu süreç geri döndürülemez. Taşımadan önce yeni hesabınızda + bu hesap için bir takma ad ayarladığınızdan emin olun. Lütfen @person@server.com + şeklinde biçimlendirilmiş hesabın etiketini girin +emojis: Emoji +flagAsCat: Kedi misin? +selectChannel: Kanal seç +emojiName: Emoji adı +showOnRemote: Uzak sunucuda görüntüle +flagSpeakAsCatDescription: Gönderileriniz kedi modundayken nyanifiye edilecek +flagShowTimelineReplies: Yanıtları zaman çizelgesinde göster +silenceThisInstance: Bu sunucuyu sustur +proxyAccountDescription: Vekil hesabı, belirli koşullar altında kullanıcılar için + uzaktan takipçi işlevi gören bir hesaptır. Örneğin, bir kullanıcı listeye bir uzak + kullanıcı eklediğinde, o kullanıcıyı takip eden yerel bir kullanıcı yoksa uzak kullanıcının + etkinliği sunucuya teslim edilmeyecektir, bu nedenle onun yerine vekil hesabı takip + edilecektir. +clearQueueConfirmTitle: Bu sırayı temizlemek istediğine emin misin? +software: Yazılım +version: Sürüm +federating: Federasyon +preview: Ön izleme +retypedNotMatch: Girişler uyuşmuyor. +attachFile: Dosya ekle +noSuchUser: Kullanıcı bulunamadı +removeAreYouSure: '"{x}" kaldırmak istediğinize emin misiniz?' +keepOriginalUploading: Orjinal resmi sakla +messageRead: Oku +deleteAreYouSure: '"{x}" silmek istediğinize emin misiniz?' +messaging: Sohbet +upload: Yükle +fromUrl: URL'den +agreeTo: '{0} kabul ediyorum' +tos: Kullanım Koşulları +drive: Drive +selectFolder: Klasör seç +inputNewFileName: Yeni dosya ismi gir +whenServerDisconnected: Sunucuyla bağlantı kesildiğinde +avatar: Avatar +rename: Yeniden Adlandır +banner: Afiş +nsfw: NSFW +doNothing: Görmezden Gel +watch: İzle +connectService: Bağlan +registration: Kayıt +hcaptcha: hCaptcha +pinnedNotes: Sabitlenmiş gönderiler +hcaptchaSiteKey: Site key +hcaptchaSecretKey: Secret key +antennaSource: Anten kaynağı +antennaKeywords: Dinlenecek anahtar kelimeler +antennaExcludeKeywords: Hariç tutulacak anahtar kelimeler +antennaKeywordsDescription: AND koşulu için boşluklarla veya OR koşulu için satır + sonlarıyla ayırın. +caseSensitive: Büyük harf duyarlı +enableServiceworker: Tarayıcınız için Push-Bildirimleri Etkinleştirin +unsilenceConfirm: Bu kullanıcının susturma işlemini geri almak istediğinizden emin + misiniz? +userList: Listeler +antennaUsersDescription: Kullanıcı başı bir satır kullanın +administrator: Yönetici +token: Token +cacheClear: Önbelleği temizle +createGroup: Grup oluştur +newPasswordIs: Yeni şifren "{password}" +share: Paylaş +enable: Etkinleştir +groupName: Grup adı +available: Mevcut +unavailable: Mevcut değil +weekOverWeekChanges: Geçen haftadan beri değişiklikler +usernameInvalidFormat: Büyük ve küçük harfleri, sayıları ve alt çizgileri kullanabilirsiniz. +tooShort: Çok kısa +passwordMatched: Uyuşuyor +dayOverDayChanges: Dünden beri değişiklikler +appearance: Görünüm +objectStorageBaseUrl: Ana URL +objectStoragePrefix: Prefix +unableToProcess: Operasyon tamamlanamadı +deleteAllFilesConfirm: Tüm dosyaları silmek istediğine emin misin? +disablePagesScript: Sayfalardan AiScript'i deaktive et +expandOnNoteClick: Gönderileri basarak aç +expandOnNoteClickDesc: Kapatılırsa, gönderileri hala menüden veya sağtıklayarak açabilirsin. +removeAllFollowingDescription: Bunu gerçekleştirmek, {host} üzerindeki tüm hesapları + takip etmeyi bırakır. +deck: Deste +pluginTokenRequestedDescription: Bu eklenti, burada ayarlanan izinleri kullanabilecektir. +notificationType: Bildirim tipi +channelFederationWarn: Kanallar başka sunuculara federe edilmiyor +forwardReport: Raporu uzak sunucuya ilet +openInNewTab: Yeni sekmede aç +clip: Ataç +optional: Opsiyonel +manageAccessTokens: Erişim tokenlerini düzenle +clipsDesc: Ataçlar, paylaşılabilen kategorize yer imleri gibidir. Tek tek gönderiler + menüsünden ataçlar oluşturabilirsiniz. +makeExplorable: Hesabını "Keşfet" 'te göster +accountInfo: Hesap Bilgisi +makeExplorableDescription: Bunu kapatırsanız, hesabınız "Keşfet" bölümünde görünmez. +saveAs: Olarak kaydet... +advanced: Gelişmiş +value: Değer +youAreRunningUpToDateClient: En son istemci sürümünü kullanıyorsunuz. +accounts: Hesaplar +switch: Değiştir +popularPosts: Popüler sayfalar +inChannelSearch: Kanalda ara +administration: Yönetim +ads: Reklamlar +low: Düşük +seperateRenoteQuote: Ayrı destek ve fiyat teklifi düğmeleri +sent: Gönderildi +customMOTD: Özel MOTD +showUpdates: Calckey güncellendiğinde bir açılır pencere göster +logoImageUrl: Logo resim URL'si +showAdminUpdates: Yeni bir Calckey sürümünün mevcut olduğunu belirtin (yalnızca yönetici) +newer: asla +older: daha eski +exportRequested: Bir dışarı aktarma talebinde bulundunuz. Bu biraz zaman alabilir. + Tamamlandığında Drive'ınıza eklenecektir. +notes: Gönderiler +following: Takip Ediyor +followers: Takipçiler +followsYou: Seni takip ediyor +pageLoadErrorDescription: Buna normalde ağ hataları veya tarayıcının önbelleği neden + olur. Önbelleği temizlemeyi deneyin ve biraz bekledikten sonra tekrar deneyin. +quote: Alıntıla +pinnedNote: Sabitlenmiş gönderi +renote: Yükselt +unrenote: Yükseltmeyi geri al +emojiUrl: Emoji URL +suspendConfirm: Bu hesabı askıya almak istediğinize emin misiniz? +addEmoji: Ekle +autoAcceptFollowed: Takip ettiğiniz kullanıcıların takip isteklerini otomatik olarak + onaylayın +general: Genel +accountMoved: 'Bu kullanıcı yeni bir hesapa taşındı:' +wallpaper: Arkaplan +searchWith: 'Arat: {q}' +youHaveNoLists: Hiçbir listen yok +followConfirm: '{name} kullanıcısını takip etmek istediğine emin misin?' +metadata: Metadata +monitor: İzlengeç +jobQueue: İş Sırası +noUsers: Kullanıcı bulunamadı +noInstances: Sunucu bulunamadı +pinLimitExceeded: Daha fazla gönderi sabitleyemezsin +defaultValueIs: 'Varsayılan: {value}' +noCustomEmojis: Emoji yok +blocked: Engellenmiş +default: Varsayılan +all: Tümü +subscribing: Abone Olunuyor +publishing: Yayınlanmak +notResponding: Cevap vermiyor +more: Daha fazla! +featured: Önerilen +usernameOrUserId: Kullanıcı adı veya kullanıcı id'si +fromDrive: Drive'dan +uploadFromUrl: URL'den yükle +announcements: Duyurular +explore: Keşfet +imageUrl: Resim URL'si +thisYear: Yıl +deleteFolder: Bu klasörü sil +addFile: Dosya ekle +dayX: '{day}' +enableLocalTimeline: Yerel zaman çizgisini aktif et +disconnectService: Bağlantıyı kes +enableGlobalTimeline: Global zaman çizgisini aktif et +enableRegistration: Yeni kullanıcı kaydını aktif et +invite: Davet et +bannerUrl: Afiş resmi URL +backgroundImageUrl: Arkaplan URL'si +recaptcha: reCAPTCHA +iconUrl: Ikon URL +recaptchaSecretKey: Secret key +avoidMultiCaptchaConfirm: Birden fazla Captcha sistemi kullanmak aralarında etkileşime + neden olabilir. Şu anda etkin olan diğer Captcha sistemlerini devre dışı bırakmak + ister misiniz? Etkin kalmalarını istiyorsanız, iptal düğmesine basın. +aboutMisskey: Calckey Hakkında +popularUsers: Popüler kullanıcılar +notFoundDescription: Bu URL'ye karşılık gelen sayfa bulunamadı. +reduceUiAnimation: Arayüz animasyonlarını azalt +markAsReadAllNotifications: Tüm bildirimleri okundu olarak işaretle +markAsReadAllTalkMessages: Tüm mesajları okundu olarak işaretle +inviteToGroup: Gruba davet et +quoteAttached: Alıntıla +useOsNativeEmojis: Sistem Emojilerini Kullan +signinHistory: Giriş geçmişleri +disableAnimatedMfm: Animasyonlu MFM'yi devre dışı bırak +uiLanguage: Arayüz dili +groupInvited: Bir gruba davet edildin +createAccount: Hesap Oluştur +existingAccount: Var olan hesap +aboutX: '{x} Hakkında' +doing: İşleniyor... +category: Kategori +deleteAll: Hepsini sil +objectStorageEndpoint: Endpoint +output: Çıkış +userSuspended: Bu kullanıcı askıya alındı. +userSilenced: Bu kullanıcı susturuldu. +yourAccountSuspendedTitle: Bu hesap askıya alındı +relays: Röleler +inboxUrl: Gelen URL +menu: Menü +divider: Ayraç +addItem: Öğe Ekle +enableInfiniteScroll: Otomatik olarak daha fazla yükle +enablePlayer: Video oynatıcıyı aç +disablePlayer: Video oynatıcıyı kapat +expandTweet: Tweeti Büyüt +large: Büyük +medium: Orta +smtpConfig: SMTP Sunucusu Ayarları +smtpHost: Adres +emailServer: Mail sunucusu +edit: Düzenle +emailAddress: Mail adresi +smtpPort: Port +emptyToDisableSmtpAuth: SMTP doğrulamasını kapatmak için kullanıcı adı ve şifreyi + boş bırakın +makeActive: Aktif +display: Gösterim +copy: Kopyala +metrics: Metrikler +pollVotesCount: Gönderilen oylama sayısı +loadRawImages: Küçük resimleri göstermek yerine orijinal resimleri yükleyin +switchUi: Düzen +sentReactionsCount: Gönderilen tepki sayısı +receivedReactionsCount: Alınan tepki sayısı +pollVotedCount: Alınan oylama sayısı +pageLikedCount: Beğeni alan Sayfa sayısı +contact: Bağlantı +useSystemFont: Sistemin varsayılan yazı tipini kullan +usageAmount: Kullanım +inUse: Kullanılan +userInfo: Kullanıcı bilgisi +unknown: Bilinmiyor +customCssWarn: Bu ayar yalnızca ne işe yaradığını biliyorsanız kullanılmalıdır. Uygun + olmayan değerlerin girilmesi, istemcinin normal şekilde çalışmamasına neden olabilir. +memo: Not +allowedInstancesDescription: Her biri yeni bir satırla ayrılmış, federasyon için beyaz + listeye eklenecek sunucu ana bilgisayarları (yalnızca özel modda geçerlidir). +expiration: Bitiş +troubleshooting: Sorun giderme +usernameInfo: Hesabınızı bu sunucudaki diğerlerinden ayıran bir ad. Alfabeyi (a~z, + A~Z), rakamları (0~9) veya alt çizgileri (_) kullanabilirsiniz. Kullanıcı adları + daha sonra değiştirilemez. +size: Boyut +numberOfColumn: Sütun Sayısı +driveCapOverrideCaption: 0 veya daha düşük bir değer girerek kapasiteyi varsayılana + sıfırlayın. +requireAdminForView: Bunu görüntülemek için bir yönetici hesabıyla oturum açmalısınız. +userSaysSomethingReasonReply: '{name}, {reason} içeren bir gönderiye cevap verdi' +overview: Genel Bakış +logs: Günlükler +database: Veri Tabanı +reportAbuseOf: '{name} kullanıcısını raporla' +openInSideView: Yan görünümde aç +createNew: Yeni oluştur +createNewClip: Yeni ataç oluştur +unclip: Atacı Kaldır +notesCount: Gönderi sayısı +repliesCount: Gönderilen yanıt sayısı +renotesCount: Göndeirlen yükseltme sayısı +repliedCount: Alınan yanıt sayısı +driveUsage: Drive kullanımı +noCrawle: Tarayıcı dizine eklemeyi reddet +needReloadToApply: Bunun yansıtılması için bir yeniden yükleme gereklidir. +showTitlebar: Başlık çubuğunu göster +latestVersion: En Son Sürüm +capacity: Kapasite +userPagePinTip: Tek tek gönderiler menüsünden "Profile sabitle"yi seçerek gönderileri + burada görüntüleyebilirsiniz. +offline: Çevrimdışı +priority: Öncelik +ratio: Oran +secureMode: Güvenli Mod (Yetkili Getirme) +aiChanMode: Klasik kullanıcı arayüzünde Ai-chan +recommended: Önerilen +received: Alındı +classic: Ortalanmış +muteThread: Konuyu sessize al +deleteAccountConfirm: Bu, hesabınızı geri alınamaz bir şekilde silecektir. İlerle? +hide: Gizle +pubSub: Pub/Sub Hesapları +filter: Filtre +controlPanel: Kontrol Paneli +continueThread: Konuya devam et +incorrectPassword: Yanlış şifre. +voteConfirm: '"{choice}" için oyunuzu onaylıyor musunuz?' +failedToFetchAccountInformation: Hesap bilgileri getirilemedi +rateLimitExceeded: Hız limiti aşıldı +renotedBy: '{user} Yükseltti' +host: Host +objectStorage: Object Storage +objectStorageUseSSLDesc: API bağlantıları için HTTPS kullanmayacaksanız bunu kapatın +objectStorageUseProxyDesc: API bağlantıları için Proxy kullanmayacaksanız bunu kapatın +objectStorageSetPublicRead: Yüklendiğinde "public-read" kullan +serverLogs: Sunucu günlüğü +abuseReports: Raporlar +reportAbuse: Rapor +verificationEmailSent: Bir doğrulama maili gönderildi. Doğrulamayı tamamlamak için + lütfen verilen bağlantıyı takip edin. +hashtags: Etiketler +resolved: Çözüldü +flagShowTimelineRepliesDescription: Açıksa, kullanıcıların zaman çizelgesindeki diğer + kullanıcıların gönderilerine verdiği yanıtları gösterir. +clearQueueConfirmText: Kuyrukta kalan teslim edilmemiş gönderiler birleştirilmeyecektir. + Genellikle bu işleme gerek yoktur. +image: Resim +video: Video +showMore: Daha Fazla +showLess: Kapat +selectAntenna: Anten seç +selectWidget: Araç seç +unsuspendConfirm: Bu hesabın askıya almasını kaldırmak istediğinize emin misiniz? +selectList: Liste seç +editWidgets: Araçları düzenle +showEmojisInReactionNotifications: Tepki bildirimlerinde emojileri göster +renoteMute: Yükseltmeleri sustur +renoteUnmute: Yükseltmeleri susturmayı kaldır +loginFailed: Giriş yapılamadı +proxyAccount: Vekil Hesap +selectUser: Kullanıcı seç +recipient: Alıcı(lar) +annotation: Yorumlar +federation: Federasyon +registeredAt: Kayıtlı +latestRequestSentAt: Gönderilen son istek +latestRequestReceivedAt: Alınan son istek +latestStatus: Son durum +storageUsage: Depolama kullanımı +charts: Grafikler +perHour: Saat Başı +perDay: Gün Başı +stopActivityDelivery: Etkinlik göndermeyi durdur +blockThisInstance: Bu sunucuyu engelle +themeForDarkMode: Karanlık modda kullanmak için temalar +fileName: Dosya adı +selectFile: Dosya seç +emptyDrive: Drive'n boş +promote: Terfi +numberOfDays: Gün sayısı +hideThisNote: Bu gönderiyi gizle +file: Dosya +enableEmojiReactions: Emoji tepkilerini aç +cw: İçerik uyarısı +makeFollowManuallyApprove: Takip istekleri onay gerektirir +today: Bugün +enableRecommendedTimeline: Tavsiye edilen zaman çizgisini aktive et +state: Durum +sort: Sırala +script: Skript +keepCw: İçerik uyarılarını sakla +manageAccounts: Hesapları Düzenle +makeReactionsPublicDescription: Bu, tüm geçmiş tepkilerinizin listesini herkesin görebileceği + bir hale getirecektir. +unmuteThread: İleti dizisinin sesini aç +ffVisibility: Takipçiler/Takipçiler Görünürlüğü +reflectMayTakeTime: Bunun yansıması biraz zaman alabilir. +cropImageAsk: Bu resmi kırpmak istediğinize emin misiniz? +check: Kontrol Et +driveCapOverrideLabel: Bu kullanıcı için drive kapasitesini değiştirin +numberOfPageCache: Önbelleğe alınan sayfa sayısı +license: Lisans +indexFrom: Post ID'den itibaren dizin +xl: XL +notificationSetting: Bildirim ayarları +fillAbuseReportDescription: Lütfen bu raporla ilgili ayrıntıları doldurun. Belirli + bir gönderiyle ilgiliyse, lütfen URL'sini ekleyin. +forwardReportIsAnonymous: Uzak sunucuda, hesabınız yerine raportör olarak anonim bir + sistem hesabı görüntülenecektir. +abuseMarkAsResolved: Raporu çözüldü olarak işaretle +instanceTicker: Göndeirlerdeki sunucu bilgisi +waitingFor: '{x} bekleniyor' +random: Rastgele +public: Herkese açık +i18nInfo: Calckey, gönüllüler tarafından çeşitli dillere çevriliyor. {link} adresinden + yardımcı olabilirsiniz. +disableShowingAnimatedImages: Animasyonlu görüntüleri oynatma +clips: Ataçlar +experimentalFeatures: Deneysel özellikler +developer: Geliştirici +left: Sol +center: Orta +wide: Geniş +narrow: Dar +reloadToApplySetting: Bu ayar yalnızca bir sayfa yeniden yüklendikten sonra geçerli + olacaktır. Şimdi yeniden yüklensin mi? +editCode: Kodu düzenle +apply: Uygula +receiveAnnouncementFromInstance: Bu sunucudan bildirimleri al +publish: Paylaş +quitFullView: Tam görünümden çık +addDescription: Açıklama ekle +info: Hakkında +noMaintainerInformationWarning: Yönetici bilgileri yapılandırılmadı. +noBotProtectionWarning: Bot koruması yapılandırılmamış. +postToGallery: Yeni galeri gönderisi oluştur +gallery: Galeri +privateModeInfo: Etkinleştirildiğinde, yalnızca beyaz listedeki sunucular sunucunuzla + birleşebilir. Tüm gönderiler halktan gizlenecektir. +itsOff: Etkinsizleştirilmiş +ffVisibilityDescription: Kimleri takip ettiğinizi ve kimlerin sizi takip ettiğini + kimlerin görebileceğini yapılandırmanıza izin verir. +welcomeBackWithName: Tekrar hoş geldin {name} +themeColor: Sunucu Kayan Yazı Rengi +audio: Ses +recentNHours: Son {n} saat +isSystemAccount: Bu hesap sistem tarafından oluşturulur ve otomatik olarak işletilir. + Lütfen bu hesabı denetlemeyin, düzenlemeyin, silmeyin veya başka bir şekilde kurcalamayın, + aksi takdirde sunucunuz bozulabilir. +typeToConfirm: Lütfen onaylamak için {x} girin +remoteOnly: Sadece uzak +failedToUpload: Yükleme başarısız +cannotUploadBecauseInappropriate: Bu dosya, bazı bölümleri potansiyel olarak NSFW + olarak algılandığından yüklenemedi. +cannotUploadBecauseNoFreeSpace: Drive kapasitesi yetersiz olduğundan yükleme başarısız + oldu. +cannotUploadBecauseExceedsFileSizeLimit: Bu dosya, izin verilen maksimum boyutu aştığı + için yüklenemedi. +beta: Beta +enableAutoSensitive: Otomatik NSFW İşaretleme +enableAutoSensitiveDescription: Mümkün olduğunda Makine Öğrenimi yoluyla NSFW ortamının + otomatik olarak algılanmasına ve işaretlenmesine olanak tanır. Bu seçenek devre + dışı bırakılsa bile, sunucu çapında etkinleştirilebilir. +shuffle: Karıştır +pushNotification: Push bildirimleri +unsubscribePushNotification: Push bildirimlerini kapat +pushNotificationNotSupported: Tarayıcınız veya sunucunuz push bildirimleri desteklemiyor +caption: Otomatik Başlık +moveToLabel: 'Taşıyacağın hesap:' +moveFromDescription: Bu, eski hesabınızın bir takma adını belirleyecek ve böylece + o hesaptan bu mevcut hesaba geçebileceksiniz. Bunu eski hesabınızdan taşınmadan + ÖNCE yapın. Lütfen @person@server.com şeklinde biçimlendirilmiş hesabın etiketini + girin +migrationConfirm: "Hesabınızı {account} hesabına taşımak istediğinizden kesinlikle + emin misiniz? Bunu yaptığınızda, geri alamazsınız ve hesabınızı bir daha normal + şekilde kullanamazsınız.\nAyrıca, lütfen bu cari hesabı, taşındığınız hesap olarak + ayarladığınızdan emin olun." +indexFromDescription: Her gönderiyi dizine eklemek için boş bırakın +indexNotice: Şimdi indeksleniyor. Bu muhtemelen biraz zaman alacaktır, lütfen sunucunuzu + en az bir saat yeniden başlatmayın. +customKaTeXMacro: Özel KaTeX makroları +directNotes: Direkt Mesajlar +import: İçeri Aktar +export: Dışarı Aktar +mentions: Bahsetmeler +files: Dosyalar +driveFileDeleteConfirm: '"{name}" dosyasını silmek istediğinizden emin misiniz? Ek + olarak içeren tüm gönderilerden kaldırılacaktır.' +createList: Liste oluştur +listsDesc: Listeler, belirtilen kullanıcılarla zaman çizelgesi oluşturmanıza olanak + tanır. Zaman Çizelgesi sayfasından erişilebilirler. +note: Gönder +enterListName: Liste için isim gir +unfollow: Takipten Çık +privacy: Gizlilik +followRequestPending: Takip isteği bekleniyor +enterEmoji: Bir emoji gir +followRequest: Takip İsteği +followRequests: Takip istekleri +renoted: Yükseldi. +emoji: Emoji +cacheRemoteFiles: Uzak dosyaları önbellekle +flagAsBot: Bu hesabı robot olarak işaretle +flagAsBotDescription: Bu hesap bir program tarafından kontrol ediliyorsa bu seçeneği + etkinleştirin. Etkinleştirilirse, diğer geliştiricilerin diğer botlarla sonsuz etkileşim + zincirlerini önlemesi ve Calckey'nin dahili sistemlerini bu hesabı bir bot olarak + ele alacak şekilde ayarlaması için bir bayrak görevi görür. +clearQueue: Sırayı Temizle +hiddenTags: Gizlenmiş Etiketler +done: Tamamlandı +processing: İşleniyor +silenced: Susturulmuş +darkThemes: Karanlık temalar +suspended: Askıya Alınmış +keepOriginalUploadingDescription: Orijinal olarak yüklenen görüntüyü olduğu gibi kaydeder. + Kapatılırsa, yükleme sırasında web'de görüntülenecek bir sürüm oluşturulur. +start: Başla +home: Ev +location: Konum +registeredDate: Katılım tarihi +yearX: '{year}' +pages: Sayfalar +integration: Entegrasyonlar +antennasDesc: "Antenler, belirlediğiniz kriterlere uyan yeni gönderiler görüntüler!\n + Zaman çizelgeleri sayfasından erişilebilirler." +notesAndReplies: Gönderiler ve yanıtlar +withReplies: Yanıtları da içer +connectedTo: Aşağıdaki hesap(lar) bağlı +silenceConfirm: Bu kullanıcıyı susturmak istediğinize emin misiniz? +messagingWithUser: Özel sohbet +resetPassword: Şifreyi sıfırla +registerSecurityKey: Yeni security key tanımla +docSource: Bu dökümanın kaynağı +ascendingOrder: Artan +tags: Etiketler +descendingOrder: Azalan +scratchpadDescription: Karalama defteri, AiScript deneyleri için bir ortam sağlar. + İçinde Calckey ile etkileşime girerek sonuçlarını yazabilir, çalıştırabilir ve kontrol + edebilirsiniz. +local: Yerel +remote: Uzak +addRelay: Röle Ekle +accessibility: Erişilebilirlik +showFeaturedNotesInTimeline: Önerilen gönderileri zaman çizelgesinde göster +objectStorageBaseUrlDesc: "Referans olarak kullanılan URL. İkisinden birini kullanıyorsanız, + CDN veya Proxy'nizin URL'sini belirtin.\nS3 için 'https://<bucket>.s3.amazonaws.com' + kullanın ve GCS veya eşdeğer hizmetler için 'https://storage.googleapis.com/<bucket>' + vb. kullanın." +objectStoragePrefixDesc: Dosyalar bu prefix ile dizinler altında saklanacaktır. +objectStorageEndpointDesc: AWS S3 kullanıyorsanız bunu boş bırakın, aksi halde kullandığınız + hizmete bağlı olarak uç noktayı "<host>" veya "<host>:<port>" olarak belirtin. +objectStorageRegion: Region +invisibleNote: Gizli Gönderi +deletedNote: Silinmiş Gönderi +visibility: Görünürlük +poll: Oylama +themeEditor: Tema düzenleyicisi +enterFileDescription: Başlık gir +description: Açıklama +describeFile: Başlık ekle +system: Sistem +desktop: Masaüstü +confirmToUnclipAlreadyClippedNote: Bu gönderi zaten "{name}" atacının bir parçası. + Bunun yerine onu bu ataçtan kaldırmak istiyor musunuz? +sendErrorReportsDescription: "Açıldığında, bir sorun oluştuğunda ayrıntılı hata bilgileri + Calckey ile paylaşılarak Calckey kalitesinin artırılmasına yardımcı olur.\nBu, işletim + sisteminizin sürümü, kullandığınız tarayıcı, Calckey'deki etkinliğiniz vb. bilgileri + içerecektir." +closeAccount: Hesabı kapat +markAllAsRead: Okunmuş olarak işaretle +allowedInstances: Beyaz Listedeki Sunucular +squareAvatars: Kare avatarları göster +unread: Okunmaımş +instanceDefaultDarkTheme: Sunucu genelinde varsayılan karanlık tema +oneDay: Bir gün +showAds: Reklamları göster +adminCustomCssWarn: Bu ayar yalnızca ne işe yaradığını biliyorsanız kullanılmalıdır. + Yanlış değerler girilmesi, HERKESİN istemcilerinin normal şekilde çalışmamasına + neden olabilir. Lütfen CSS'nizi kullanıcı ayarlarınızda test ederek düzgün çalıştığından + emin olun. +customSplashIcons: Özel açılış ekranı simgeleri (url'ler) +recommendedInstancesDescription: Önerilen zaman çizelgesinde görünmesi için satır + sonlarıyla ayrılmış önerilen sunucular. `https://` EKLEMEYİN, YALNIZCA etki alanı. +recommendedInstances: Önerilen sunucular From 7eec1a9dab94bdae94e9bbb306e8b0588575ef6c Mon Sep 17 00:00:00 2001 From: Xalis Ratt <xalisratt@linux.pl> Date: Fri, 14 Jul 2023 14:21:56 +0000 Subject: [PATCH 130/162] chore: Translated using Weblate (Ukrainian) Currently translated at 74.9% (1372 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/uk/ --- locales/uk-UA.yml | 384 +++++++++++++++++++++++++++++++++------------- 1 file changed, 277 insertions(+), 107 deletions(-) diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 712c0fd03..4df6dd212 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -1,7 +1,9 @@ ---- _lang_: "Українська" headlineMisskey: "Мережа об'єднана записами" -introMisskey: "Ласкаво просимо! Calckey - децентралізована служба мікроблогів з відкритим кодом.\nСтворюйте \"нотатки\", щоб поділитися тим, що відбувається, і розповісти всім про себе 📡\nЗа допомогою \"реакцій\" ви також можете швидко висловити свої почуття щодо нотаток інших 👍\nДосліджуймо новий світ! 🚀" +introMisskey: "Ласкаво просимо! Calckey - децентралізована служба мікроблогів з відкритим + кодом.\nСтворюйте \"нотатки\", щоб поділитися тим, що відбувається, і розповісти + всім про себе 📡\nЗа допомогою \"реакцій\" ви також можете швидко висловити свої + почуття щодо нотаток інших 👍\nДосліджуймо новий світ! 🚀" monthAndDay: "{month}/{day}" search: "Пошук" notifications: "Сповіщення" @@ -14,16 +16,16 @@ gotIt: "Зрозуміло!" cancel: "Скасувати" enterUsername: "Введіть ім'я користувача" renotedBy: "Поширено {user}" -noNotes: "Немає нотаток" +noNotes: "Немає записів" noNotifications: "Немає сповіщень" -instance: "Інстанс" +instance: "Сервер" settings: "Налаштування" basicSettings: "Основні налаштування" otherSettings: "Інші налаштування" openInWindow: "Відкрити у вікні" profile: "Профіль" timeline: "Стрічка" -noAccountDescription: "Цей користувач ще нічого не написав про себе" +noAccountDescription: "Цей користувач ще нічого не написав про себе." login: "Увійти" loggingIn: "Здійснюємо вхід..." logout: "Вийти" @@ -44,7 +46,8 @@ copyContent: "Скопіювати контент" copyLink: "Скопіювати посилання" delete: "Видалити" deleteAndEdit: "Видалити й редагувати" -deleteAndEditConfirm: "Ви впевнені, що хочете видалити цю нотатку та відредагувати її? Ви втратите всі реакції, поширення та відповіді на неї." +deleteAndEditConfirm: "Ви впевнені, що хочете видалити цей запис та відредагувати + його? Ви втратите всі реакції, поширення та відповіді на нього." addToList: "Додати до списку" sendMessage: "Надіслати повідомлення" copyUsername: "Скопіювати ім’я користувача" @@ -64,9 +67,11 @@ import: "Імпорт" export: "Експорт" files: "Файли" download: "Завантажити" -driveFileDeleteConfirm: "Ви впевнені, що хочете видалити файл {name}? Нотатки із цим файлом також буде видалено." +driveFileDeleteConfirm: "Ви впевнені, що хочете видалити файл {name}? Його буде видалено + з усіх записів які містили його." unfollowConfirm: "Ви впевнені, що хочете відписатися від {name}?" -exportRequested: "Експортування розпочато. Це може зайняти деякий час. Після завершення експорту отриманий файл буде додано на диск." +exportRequested: "Експортування розпочато. Це може зайняти деякий час. Після завершення + експорту отриманий файл буде додано на диск." importRequested: "Імпортування розпочато. Це може зайняти деякий час." lists: "Списки" noLists: "Немає списків" @@ -80,10 +85,12 @@ manageLists: "Управління списками" error: "Помилка" somethingHappened: "Щось пішло не так" retry: "Спробувати знову" -pageLoadError: "Помилка при завантаженні сторінки" -pageLoadErrorDescription: "Зазвичай це пов’язано з помилками мережі або кешем браузера. Очистіть кеш або почекайте трохи й спробуйте ще раз." +pageLoadError: "Помилка при завантаженні сторінки." +pageLoadErrorDescription: "Зазвичай це пов’язано з помилками мережі або кешем браузера. + Очистіть кеш або почекайте трохи й спробуйте ще раз." serverIsDead: "Відповіді від сервера немає. Зачекайте деякий час і повторіть спробу." -youShouldUpgradeClient: "Перезавантажте та використовуйте нову версію клієнта, щоб переглянути цю сторінку." +youShouldUpgradeClient: "Перезавантажте та використовуйте нову версію клієнта, щоб + переглянути цю сторінку." enterListName: "Введіть назву списку" privacy: "Конфіденційність" makeFollowManuallyApprove: "Підтверджувати підписників уручну" @@ -95,10 +102,10 @@ unfollow: "Відписатись" followRequestPending: "Очікуючі запити на підписку" enterEmoji: "Введіть емодзі" renote: "Поширити" -unrenote: "Відміна поширення" -renoted: "Поширити запис." -cantRenote: "Неможливо поширити." -cantReRenote: "Поширення не можливо поширити." +unrenote: "скасувати поширення" +renoted: "Поширено." +cantRenote: "Цей запис неможливо поширити." +cantReRenote: "Поширення неможливо поширити." quote: "Цитата" pinnedNote: "Закріплений запис" pinned: "Закріпити" @@ -108,7 +115,8 @@ sensitive: "NSFW" add: "Додати" reaction: "Реакції" reactionSetting: "Налаштування реакцій" -reactionSettingDescription2: "Перемістити щоб змінити порядок, Клацнути мишою щоб видалити, Натиснути \"+\" щоб додати." +reactionSettingDescription2: "Перемістити щоб змінити порядок, Клацнути мишою щоб + видалити, Натиснути \"+\" щоб додати." rememberNoteVisibility: "Пам’ятати параметри видимісті" attachCancel: "Видалити вкладення" markAsSensitive: "Позначити як NSFW" @@ -137,14 +145,20 @@ emojiUrl: "URL емодзі" addEmoji: "Додати емодзі" settingGuide: "Рекомендована конфігурація" cacheRemoteFiles: "Кешувати дані з інших інстансів" -cacheRemoteFilesDescription: "Якщо кешування вимкнено, віддалені файли завантажуються безпосередньо з віддаленого інстансу. Це зменшує використання сховища, але збільшує трафік, оскільки не генеруются ескізи." +cacheRemoteFilesDescription: "Якщо кешування вимкнено, віддалені файли завантажуються + безпосередньо з віддаленого серверу. Це зменшує використання сховища, але збільшує + трафік, оскільки не генеруются ескізи." flagAsBot: "Акаунт бота" -flagAsBotDescription: "Ввімкніть якщо цей обліковий запис використовується ботом. Ця опція позначить обліковий запис як бота. Це потрібно щоб виключити безкінечну інтеракцію між ботами а також відповідного підлаштування Calckey." +flagAsBotDescription: "Ввімкніть якщо цей обліковий запис використовується ботом. + Ця опція позначить обліковий запис як бота. Це потрібно щоб виключити безкінечну + інтеракцію між ботами а також відповідного підлаштування Calckey." flagAsCat: "Акаунт кота" flagAsCatDescription: "Ввімкніть, щоб позначити, що обліковий запис є котиком." flagShowTimelineReplies: "Показувати відповіді на нотатки на часовій шкалі" -flagShowTimelineRepliesDescription: "Показує відповіді користувачів на нотатки інших користувачів на часовій шкалі." -autoAcceptFollowed: "Автоматично приймати запити на підписку від користувачів, на яких ви підписані" +flagShowTimelineRepliesDescription: "Показує відповіді користувачів на нотатки інших + користувачів на часовій шкалі." +autoAcceptFollowed: "Автоматично приймати запити на підписку від користувачів, на + яких ви підписані" addAccount: "Додати акаунт" loginFailed: "Не вдалося увійти" showOnRemote: "Переглянути в оригіналі" @@ -156,13 +170,17 @@ searchWith: "Пошук: {q}" youHaveNoLists: "У вас немає списків" followConfirm: "Підписатися на {name}?" proxyAccount: "Проксі-акаунт" -proxyAccountDescription: "Обліковий запис проксі – це обліковий запис, який діє як віддалений підписник для користувачів за певних умов. Наприклад, коли користувач додає віддаленого користувача до списку, активність віддаленого користувача не буде доставлена на сервер, якщо жоден локальний користувач не стежить за цим користувачем, то замість нього буде використовуватися обліковий запис проксі-сервера." +proxyAccountDescription: "Обліковий запис проксі – це обліковий запис, який діє як + віддалений підписник для користувачів за певних умов. Наприклад, коли користувач + додає віддаленого користувача до списку, активність віддаленого користувача не буде + доставлена на сервер, якщо жоден локальний користувач не стежить за цим користувачем, + то замість нього буде використовуватися обліковий запис проксі-сервера." host: "Хост" selectUser: "Виберіть користувача" recipient: "Отримувач" annotation: "Коментарі" federation: "Федіверс" -instances: "Інстанс" +instances: "Сервери" registeredAt: "Приєднався(лась)" latestRequestSentAt: "Останній запит надіслано" latestRequestReceivedAt: "Останній запит прийнято" @@ -172,7 +190,7 @@ charts: "Графіки" perHour: "Щогодинно" perDay: "Щоденно" stopActivityDelivery: "Припинити розсилання активності" -blockThisInstance: "Заблокувати цей інстанс" +blockThisInstance: "Заблокувати цей сервер" operations: "Операції" software: "Програмне забезпечення" version: "Версія" @@ -182,15 +200,17 @@ jobQueue: "Черга завдань" cpuAndMemory: "ЦП та пам'ять" network: "Мережа" disk: "Диск" -instanceInfo: "Про цей інстанс" +instanceInfo: "Про цей сервер" statistics: "Статистика" clearQueue: "Очистити чергу" clearQueueConfirmTitle: "Ви впевнені, що хочете очистити чергу?" -clearQueueConfirmText: "Будь-які невідправлені нотатки, що залишилися в черзі, не будуть передані. Зазвичай ця операція НЕ потрібна." +clearQueueConfirmText: "Будь-які невідправлені записи, що залишилися в черзі, не будуть + передані. Зазвичай ця операція НЕ потрібна." clearCachedFiles: "Очистити кеш" clearCachedFilesConfirm: "Ви впевнені, що хочете видалити всі кешовані файли?" -blockedInstances: "Заблоковані інстанси" -blockedInstancesDescription: "Вкажіть інстанси, які потрібно заблокувати. Перелічені інстанси більше не зможуть спілкуватися з цим інстансом." +blockedInstances: "Заблоковані сервери" +blockedInstancesDescription: "Вкажіть сервери, які потрібно заблокувати. Перелічені + сервери більше не зможуть спілкуватися з цим сервером." muteAndBlock: "Заглушення і блокування" mutedUsers: "Заглушені користувачі" blockedUsers: "Заблоковані користувачі" @@ -213,8 +233,8 @@ subscribing: "Підписка" publishing: "Публікація" notResponding: "Не відповідає" instanceFollowing: "Підписка на інстанс" -instanceFollowers: "Підписники інстансу" -instanceUsers: "Користувачі цього інстансу" +instanceFollowers: "Підписники серверу" +instanceUsers: "Користувачі цього серверу" changePassword: "Змінити пароль" security: "Безпека" retypedNotMatch: "Введені дані не збігаються." @@ -238,7 +258,8 @@ saved: "Збережено" messaging: "Чати" upload: "Завантажити" keepOriginalUploading: "Зберегти оригінальне зображення" -keepOriginalUploadingDescription: "Зберігає початково завантажене зображення як є. Якщо вимкнено, версія для відображення в Інтернеті буде створена під час завантаження." +keepOriginalUploadingDescription: "Зберігає початково завантажене зображення як є. + Якщо вимкнено, версія для відображення в Інтернеті буде створена під час завантаження." fromDrive: "З диска" fromUrl: "З посилання" uploadFromUrl: "Завантажити з посилання" @@ -288,7 +309,7 @@ inputNewFileName: "Введіть ім'я нового файлу" inputNewDescription: "Введіть новий заголовок" inputNewFolderName: "Введіть ім'я нової теки" circularReferenceFolder: "Ви намагаєтесь перемістити папку в її підпапку." -hasChildFilesOrFolders: "Ця тека не порожня і не може бути видалена" +hasChildFilesOrFolders: "Ця тека не порожня і не може бути видалена." copyUrl: "Копіювати URL" rename: "Перейменувати" avatar: "Аватар" @@ -304,8 +325,8 @@ unwatch: "Не стежити" accept: "Прийняти" reject: "Відхилити" normal: "Нормальний" -instanceName: "Назва інстансу" -instanceDescription: "Описання інстансу" +instanceName: "Назва серверу" +instanceDescription: "Опис серверу" maintainerName: "Ім'я адміністратора" maintainerEmail: "Email адміністратора" tosUrl: "URL умов використання" @@ -316,12 +337,13 @@ dayX: "{day}" monthX: "{month}" yearX: "{year}" pages: "Сторінки" -integration: "Інтеграція" +integration: "Інтеграції" connectService: "Під’єднати" disconnectService: "Відключитися" enableLocalTimeline: "Увімкнути локальну стрічку" enableGlobalTimeline: "Увімкнути глобальну стрічку" -disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті." +disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх + стрічок, навіть якщо вони вимкнуті." registration: "Реєстрація" enableRegistration: "Дозволити реєстрацію" invite: "Запросити" @@ -333,11 +355,13 @@ bannerUrl: "URL банера" backgroundImageUrl: "URL-адреса фонового зображення" basicInfo: "Основна інформація" pinnedUsers: "Закріплені користувачі" -pinnedUsersDescription: "Впишіть в список користувачів, яких хочете закріпити на сторінці \"Знайти\", ім'я в стовпчик." +pinnedUsersDescription: "Впишіть в список користувачів, яких хочете закріпити на сторінці + \"Знайти\", ім'я в стовпчик." pinnedPages: "Закріплені сторінки" -pinnedPagesDescription: "Введіть шляхи сторінок, які ви бажаєте закріпити на головній сторінці цього інстанса, розділені новими рядками." -pinnedClipId: "Ідентифікатор закріпленої замітки." -pinnedNotes: "Закріплена нотатка" +pinnedPagesDescription: "Введіть шляхи сторінок, які ви бажаєте закріпити на головній + сторінці цього інстанса, розділені новими рядками." +pinnedClipId: "Ідентифікатор закріпленої замітки" +pinnedNotes: "Закріплений запис" hcaptcha: "hCaptcha" enableHcaptcha: "Увімкнути hCaptcha" hcaptchaSiteKey: "Ключ сайту" @@ -346,22 +370,25 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "Увімкнути reCAPTCHA" recaptchaSiteKey: "Ключ сайту" recaptchaSecretKey: "Секретний ключ" -avoidMultiCaptchaConfirm: "Використання кількох систем Captcha може спричинити перешкоди між ними. Бажаєте вимкнути інші активні системи Captcha? Якщо ви хочете, щоб вони залишалися ввімкненими, натисніть «Скасувати»." +avoidMultiCaptchaConfirm: "Використання кількох систем Captcha може спричинити перешкоди + між ними. Бажаєте вимкнути інші активні системи Captcha? Якщо ви хочете, щоб вони + залишалися ввімкненими, натисніть «Скасувати»." antennas: "Антени" manageAntennas: "Налаштування антен" name: "Ім'я" antennaSource: "Джерело антени" antennaKeywords: "Ключові слова антени" antennaExcludeKeywords: "Винятки" -antennaKeywordsDescription: "Розділення ключових слів пробілами для \"І\" або з нової лінійки для \"АБО\"" -notifyAntenna: "Сповіщати про нові нотатки" -withFileAntenna: "Тільки нотатки з вкладеними файлами" +antennaKeywordsDescription: "Відокремте пробілами для умови \"І\" або перенесенням + до нового рядка для умови \"АБО\"." +notifyAntenna: "Сповіщати про нові записи" +withFileAntenna: "Тільки записи з вкладеними файлами" enableServiceworker: "Ввімкнути ServiceWorker" antennaUsersDescription: "Список імя користувачів в стопчик" caseSensitive: "З урахуванням регістру" withReplies: "Включаючи відповіді" connectedTo: "Наступні акаунти під'єднані" -notesAndReplies: "Нотатки та відповіді" +notesAndReplies: "Записи та відповіді" withFiles: "Файли" silence: "Заглушити" silenceConfirm: "Ви впевнені, що хочете заглушити цього користувача?" @@ -397,7 +424,7 @@ notFoundDescription: "Сторінка за вказаною адресою не uploadFolder: "Місце для завантаження за замовчуванням" cacheClear: "Очистити кеш" markAsReadAllNotifications: "Позначити всі сповіщення як прочитані" -markAsReadAllUnreadNotes: "Позначити всі нотатки як прочитані" +markAsReadAllUnreadNotes: "Позначити всі записи як прочитані" markAsReadAllTalkMessages: "Позначити всі повідомлення як прочитані" help: "Допомога" inputMessageHere: "Введіть повідомлення тут" @@ -418,7 +445,7 @@ text: "Текст" enable: "Увімкнути" next: "Далі" retype: "Введіть ще раз" -noteOf: "Нотатка {user}" +noteOf: "Запис {user}" inviteToGroup: "Запрошення до групи" quoteAttached: "Цитата" quoteQuestion: "Ви хочете додати цитату?" @@ -431,7 +458,8 @@ invitationCode: "Код запрошення" checking: "Перевірка…" available: "Доступно" unavailable: "Недоступно" -usernameInvalidFormat: "літери, цифри та _ є прийнятними" +usernameInvalidFormat: "Ви можете використовувати великі та малі літери, цифри та + підкреслення." tooShort: "Занадто короткий" tooLong: "Занадто довгий" weakPassword: "Слабкий пароль" @@ -454,7 +482,7 @@ joinOrCreateGroup: "Отримуйте запрошення до груп або noHistory: "Історія порожня" signinHistory: "Історія входів" disableAnimatedMfm: "Відключити анімації MFM" -doing: "Виконується" +doing: "Виконується..." category: "Категорія" tags: "Теги" docSource: "Джерело цього документа" @@ -476,29 +504,34 @@ accountSettings: "Налаштування акаунта" promotion: "Виділене" promote: "Виділити" numberOfDays: "Кількість днів" -hideThisNote: "Сховати цю нотатку" -showFeaturedNotesInTimeline: "Показувати популярні нотатки у стрічці" +hideThisNote: "Сховати цей запис" +showFeaturedNotesInTimeline: "Показувати популярні записи у стрічці" objectStorage: "Object Storage" useObjectStorage: "Використовувати object storage" objectStorageBaseUrl: "Base URL" -objectStorageBaseUrlDesc: "Це початкова частина адреси, що використовується CDN або проксі, наприклад для S3: https://<bucket>.s3.amazonaws.com, або GCS: 'https://storage.googleapis.com/<bucket>'" +objectStorageBaseUrlDesc: "Це початкова частина адреси, що використовується CDN або + проксі, наприклад для S3: https://<bucket>.s3.amazonaws.com, або GCS: 'https://storage.googleapis.com/<bucket>'" objectStorageBucket: "Bucket" objectStorageBucketDesc: "Будь ласка вкажіть назву відра в налаштованому сервісі." objectStoragePrefix: "Prefix" objectStoragePrefixDesc: "Файли будуть зберігатись у розташуванні з цим префіксом." -objectStorageEndpoint: "Endpoint" -objectStorageEndpointDesc: "Залиште пустим при використанні AWS S3. Інакше введіть кінцевий пункт як '<host>' або '<host>:<port>' слідуючи інструкціям сервісу, який використовується." +objectStorageEndpoint: "Кінцевий пункт" +objectStorageEndpointDesc: "Залиште пустим при використанні AWS S3. Інакше введіть + кінцевий пункт як '<host>' або '<host>:<port>' слідуючи інструкціям сервісу, який + використовується." objectStorageRegion: "Region" -objectStorageRegionDesc: "Введіть регіон у формі 'xx-east-1'. Залиште пустим, якщо ваш сервіс не різниться відповідно до регіонів, або введіть 'us-east-1'." +objectStorageRegionDesc: "Введіть регіон у формі 'xx-east-1'. Залиште пустим, якщо + ваш сервіс не різниться відповідно до регіонів, або введіть 'us-east-1'." objectStorageUseSSL: "Використовувати SSL" objectStorageUseSSLDesc: "Вимкніть коли не використовується HTTPS для з'єднання API" objectStorageUseProxy: "Використовувати Proxy" -objectStorageUseProxyDesc: "Вимкніть коли проксі не використовується для з'єднання ObjectStorage" +objectStorageUseProxyDesc: "Вимкніть коли проксі не використовується для з'єднання + ObjectStorage" objectStorageSetPublicRead: "Встановіть 'публічне читання' при завантаженні" serverLogs: "Журнал сервера" deleteAll: "Видалити все" -showFixedPostForm: "Показати форму запису над стрічкою новин." -newNoteRecived: "Є нові нотатки" +showFixedPostForm: "Показати форму запису над стрічкою новин" +newNoteRecived: "Є нові записи" sounds: "Звуки" listen: "Слухати" none: "Відсутній" @@ -521,7 +554,8 @@ sort: "Сортування" ascendingOrder: "За зростанням" descendingOrder: "За спаданням" scratchpad: "Чернетка" -scratchpadDescription: "Scratchpad надає середовище для експериментів з AiScript. Ви можете писати, виконувати його і тестувати взаємодію з Calckey." +scratchpadDescription: "Scratchpad надає середовище для експериментів з AiScript. + Ви можете писати, виконувати його і тестувати взаємодію з Calckey." output: "Вихід" script: "Скрипт" disablePagesScript: "Вимкнути AiScript на Сторінках" @@ -529,11 +563,14 @@ updateRemoteUser: "Оновити інформацію про віддалено deleteAllFiles: "Видалити всі файли" deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?" removeAllFollowing: "Скасувати всі підписки" -removeAllFollowingDescription: "Скасувати підписку на всі акаунти з {host}. Будь ласка, робіть це, якщо інстанс більше не існує." +removeAllFollowingDescription: "Скасувати підписку на всі акаунти з {host}. Будь ласка, + робіть це, якщо сервер більше не існує." userSuspended: "Обліковий запис заблокований." userSilenced: "Обліковий запис приглушений." yourAccountSuspendedTitle: "Цей обліковий запис заблоковано" -yourAccountSuspendedDescription: "Цей обліковий запис було заблоковано через порушення умов надання послуг сервера. Зв'яжіться з адміністратором, якщо ви хочете дізнатися докладнішу причину. Будь ласка, не створюйте новий обліковий запис." +yourAccountSuspendedDescription: "Цей обліковий запис було заблоковано через порушення + умов надання послуг сервера. Зв'яжіться з адміністратором, якщо ви хочете дізнатися + докладнішу причину. Будь ласка, не створюйте новий обліковий запис." menu: "Меню" divider: "Розділювач" addItem: "Додати елемент" @@ -542,8 +579,8 @@ addRelay: "Додати ретранслятор" inboxUrl: "Inbox URL" addedRelays: "Додані ретранслятори" serviceworkerInfo: "Повинен бути ввімкнений для push-сповіщень." -deletedNote: "Видалена нотатка" -invisibleNote: "Приховані записи" +deletedNote: "Видалений запис" +invisibleNote: "Прихований запис" enableInfiniteScroll: "Увімкнути нескінченну прокрутку" visibility: "Видимість" poll: "Опитування" @@ -573,12 +610,14 @@ permission: "Права" enableAll: "Увімкнути все" disableAll: "Вимкнути все" tokenRequested: "Надати доступ до акаунту" -pluginTokenRequestedDescription: "Цей плагін зможе використовувати дозволи які тут вказані." +pluginTokenRequestedDescription: "Цей плагін зможе використовувати дозволи які тут + вказані." notificationType: "Тип сповіщення" edit: "Редагувати" emailServer: "Сервер електронної пошти" enableEmail: "Увімкнути функцію доставки пошти" -emailConfigInfo: "Використовується для підтвердження електронної пошти підчас реєстрації, а також для відновлення паролю." +emailConfigInfo: "Використовується для підтвердження електронної пошти під час реєстрації, + а також для відновлення паролю" email: "E-mail" emailAddress: "E-mail адреса" smtpConfig: "Налаштування сервера SMTP" @@ -586,14 +625,16 @@ smtpHost: "Хост" smtpPort: "Порт" smtpUser: "Ім'я користувача" smtpPass: "Пароль" -emptyToDisableSmtpAuth: "Залиште назву користувача і пароль пустими для вимкнення підтвердження SMTP" +emptyToDisableSmtpAuth: "Залиште назву користувача і пароль пустими для вимкнення + підтвердження SMTP" smtpSecure: "Використовувати безумовне шифрування SSL/TLS для з'єднань SMTP" -smtpSecureInfo: "Вимкніть при використанні STARTTLS " +smtpSecureInfo: "Вимкніть при використанні STARTTLS" testEmail: "Тестовий email" wordMute: "Блокування слів" regexpError: "Помилка регулярного виразу" -regexpErrorDescription: "Сталася помилка в регулярному виразі в рядку {line} вашого слова {tab} слова що ігноруються:" -instanceMute: "Приглушення інстансів" +regexpErrorDescription: "Сталася помилка в регулярному виразі в рядку {line} вашого + слова {tab} слова що ігноруються:" +instanceMute: "Приглушення серверів" userSaysSomething: "{name} щось сказав(ла)" makeActive: "Активувати" display: "Відображення" @@ -606,12 +647,15 @@ database: "База даних" channel: "Канали" create: "Створити" notificationSetting: "Параметри сповіщень" -notificationSettingDesc: "Виберіть типи сповіщень для відображення" +notificationSettingDesc: "Оберіть типи сповіщень для відображення." useGlobalSetting: "Застосувати глобальнi параметри" -useGlobalSettingDesc: "Якщо увімкнено, то будуть використовуватись налаштування повідомлень облікового запису, інакше можливо налаштувати індивідуально." +useGlobalSettingDesc: "Якщо увімкнено, то будуть використовуватись налаштування повідомлень + облікового запису, інакше можливо налаштувати індивідуально." other: "Інше" regenerateLoginToken: "Оновити Login Token" -regenerateLoginTokenDescription: "Регенерувати внутрішній ключ використовуваний під час входу. Зазвичай цього не потрібно робити. При регенерації всі пристрої вийдуть з системи." +regenerateLoginTokenDescription: "Регенерувати внутрішній ключ використовуваний під + час входу. Зазвичай цього не потрібно робити. При регенерації всі пристрої вийдуть + з системи." setMultipleBySeparatingWithSpace: "Можна вказати кілька значень, відділивши їх пробілом." fileIdOrUrl: "Ідентифікатор файлу або посилання" behavior: "Поведінка" @@ -619,19 +663,22 @@ sample: "Приклад" abuseReports: "Скарги" reportAbuse: "Поскаржитись" reportAbuseOf: "Поскаржитись на {name}" -fillAbuseReportDescription: "Будь ласка вкажіть подробиці скарги. Якщо скарга стосується запису, вкажіть посилання на нього." +fillAbuseReportDescription: "Будь ласка вкажіть подробиці скарги. Якщо скарга стосується + запису, вкажіть посилання на нього." abuseReported: "Дякуємо, вашу скаргу було відправлено. " reporter: "Репортер" reporteeOrigin: "Про кого повідомлено" reporterOrigin: "Хто повідомив" forwardReport: "Переслати звіт на віддалений інстанс" -forwardReportIsAnonymous: "Замість вашого облікового запису анонімний системний обліковий запис буде відображатися як доповідач на віддаленому інстансі" +forwardReportIsAnonymous: "Замість вашого облікового запису, анонімний системний обліковий + запис буде відображатися як доповідач на віддаленому сервері." send: "Відправити" abuseMarkAsResolved: "Позначити скаргу як вирішену" openInNewTab: "Відкрити в новій вкладці" openInSideView: "Відкрити збоку" defaultNavigationBehaviour: "Поведінка навігації за замовчуванням" -editTheseSettingsMayBreakAccount: "Зміна цих параметрів може призвести до пошкодження вашого акаунта." +editTheseSettingsMayBreakAccount: "Зміна цих параметрів може призвести до пошкодження + вашого акаунта." instanceTicker: "Мітка з назвою інстанса в нотатках" waitingFor: "Чекаємо на {x}" random: "Випадковий" @@ -643,10 +690,11 @@ createNew: "Створити новий" optional: "Необов'язково" createNewClip: "Створити нотатку" public: "Публічний" -i18nInfo: "Calckey перекладається на різні мови волонтерами. Ви можете допомогти: {link}" +i18nInfo: "Calckey перекладається на різні мови волонтерами. Ви можете допомогти за + посиланням: {link}." manageAccessTokens: "Керування токенами доступу" accountInfo: "Інформація про акаунт" -notesCount: "Кількість нотаток" +notesCount: "Кількість записів" repliesCount: "Кількість надісланих відповідей" renotesCount: "Кількість поширень" repliedCount: "Кількість отриманих відповідей" @@ -662,15 +710,19 @@ no: "Ні" driveFilesCount: "Кількість файлів на диску" driveUsage: "Використання місця на диску" noCrawle: "Заборонити індексацію" -noCrawleDescription: "Просити пошукові системи не індексувати ваш профіль, нотатки, сторінки тощо." -lockedAccountInfo: "Якщо видимість вашого запису не встановлена як \"Тільки підписники\", то кожен зможе побачити ваш запис, навіть якщо ви вимагаєте підтвердження підписок вручну." -alwaysMarkSensitive: "Позначати NSFW за замовчуванням" +noCrawleDescription: "Просити пошукові системи не індексувати ваш профіль, записи, + сторінки тощо." +lockedAccountInfo: "Якщо видимість вашого запису не встановлена як \"Тільки підписники\"\ + , то кожен зможе побачити ваш запис, навіть якщо ви вимагаєте підтвердження підписок + вручну." +alwaysMarkSensitive: "Позначати як NSFW за замовчуванням" loadRawImages: "Відображати вкладені зображення повністю замість ескізів" disableShowingAnimatedImages: "Не програвати анімовані зображення" -verificationEmailSent: "Електронний лист з підтвердженням відісланий. Будь ласка перейдіть по посиланню в листі для підтвердження." +verificationEmailSent: "Електронний лист з підтвердженням відісланий. Будь ласка перейдіть + по посиланню в листі для підтвердження." notSet: "Не налаштовано" -emailVerified: "Електронну пошту підтверджено." -noteFavoritesCount: "Кількість улюблених нотаток" +emailVerified: "Електронну пошту підтверджено" +noteFavoritesCount: "Кількість улюблених записів" pageLikesCount: "Кількість отриманих вподобань сторінки" pageLikedCount: "Кількість вподобаних сторінок" contact: "Контакт" @@ -679,7 +731,8 @@ clips: "Добірка" experimentalFeatures: "Експериментальні функції" developer: "Розробник" makeExplorable: "Зробіть обліковий запис видимим у розділі \"Огляд\"" -makeExplorableDescription: "Вимкніть, щоб обліковий запис не показувався у розділі \"Огляд\"." +makeExplorableDescription: "Вимкніть, щоб обліковий запис не показувався у розділі + \"Огляд\"." showGapBetweenNotesInTimeline: "Показувати розрив між записами у стрічці новин" duplicate: "Дублікат" left: "Лівий" @@ -694,7 +747,10 @@ onlineUsersCount: "{n} користувачів онлайн" nUsers: "{n} Користувачів" nNotes: "{n} Записів" sendErrorReports: "Надіслати звіт про помилки" -sendErrorReportsDescription: "При увімкненні детальна інформація про помилки буде надана Calckey у разі виникнення проблем, що дасть можливість покращити Calckey." +sendErrorReportsDescription: "Якщо увімкнено, детальна інформація про помилки буде + передаватися до Calckey, коли виникає проблема, це допоможе покращити якість роботи + Calckey.\nЦе буде включати інформацію таку як: версія вашої ОС, який браузер ви + використовуєте, ваша активність в Calckey тощо." myTheme: "Моя тема" backgroundColor: "Фон" accentColor: "Акцент" @@ -718,7 +774,7 @@ capacity: "Ємність" inUse: "Зайнято" editCode: "Редагувати вихідний текст" apply: "Застосувати" -receiveAnnouncementFromInstance: "Отримувати оповіщення з інстансу" +receiveAnnouncementFromInstance: "Отримувати сповіщення з серверу" emailNotification: "Сповіщення електронною поштою" publish: "Опублікувати" inChannelSearch: "Пошук за каналом" @@ -726,12 +782,12 @@ useReactionPickerForContextMenu: "Відкривати палітру реакц typingUsers: "Стук клавіш. Це {users}…" goBack: "Назад" info: "Інформація" -user: "Користувачі" +user: "Користувач" administration: "Управління" expiration: "Опитування закінчується" middle: "Середній" global: "Глобальна" -sent: "Відправити" +sent: "Відправлене" hashtags: "Хештеґ" hide: "Сховати" searchByGoogle: "Пошук" @@ -756,13 +812,15 @@ _registry: domain: "Домен" createKey: "Створити ключ" _aboutMisskey: - about: "Misskey - це програмне забезпечення з відкритим кодом, яке розробляє syuilo з 2014 року." + about: "Misskey - це програмне забезпечення з відкритим кодом, яке розробляє syuilo + з 2014 року." contributors: "Головні помічники" allContributors: "Всі помічники" source: "Вихідний код" translation: "Перекладати Calckey" donate: "Пожертвувати Calckey" - morePatrons: "Ми дуже цінуємо підтримку багатьох інших помічників, не перелічених тут. Дякуємо! 🥰" + morePatrons: "Ми дуже цінуємо підтримку багатьох інших помічників, не перелічених + тут. Дякуємо! 🥰" patrons: "Підтримали" _nsfw: respect: "Приховувати NSFW медіа" @@ -770,10 +828,12 @@ _nsfw: force: "Приховувати всі медіа файли" _mfm: cheatSheet: " Довідка MFM" - intro: "MFM це ексклюзивна мова розмітки тексту в Calckey, яку можна використовувати в багатьох місцях. Тут ви можете переглянути приклади її синтаксису." + intro: "MFM це ексклюзивна мова розмітки тексту в Calckey, яку можна використовувати + в багатьох місцях. Тут ви можете переглянути приклади її синтаксису." dummy: "Calckey розширює світ Федіверсу" mention: "Згадка" - mentionDescription: "За допомогою знака \"@\" перед ім'ям можна згадати конкретного користувача." + mentionDescription: "За допомогою знака \"@\" перед ім'ям можна згадати конкретного + користувача." hashtag: "Хештеґ" hashtagDescription: "За допомогою знака \"решітка\" перед словом задається хештег." url: "URL" @@ -819,7 +879,8 @@ _mfm: x4: "Надзвичайно великий" x4Description: "Показує контент надзвичайно великим." blur: "Розмиття" - blurDescription: "Цей ефект зробить контент розмитим. Контент можна зробити чітким, якщо навести на нього вказівник миші." + blurDescription: "Цей ефект зробить контент розмитим. Контент можна зробити чітким, + якщо навести на нього вказівник миші." font: "Шрифт" fontDescription: "Встановлює шрифт для контенту." rotate: "Обертати" @@ -844,10 +905,14 @@ _menuDisplay: hide: "Сховати" _wordMute: muteWords: "Заглушені слова" - muteWordsDescription: "Розділення ключових слів пробілами для \"І\" або з нової лінійки для \"АБО\"" - muteWordsDescription2: "Для використання RegEx, ключові слова потрібно вписати поміж слешів \"/\"." + muteWordsDescription: "Розділення ключових слів пробілами для \"І\" або з нової + лінійки для \"АБО\"" + muteWordsDescription2: "Для використання RegEx, ключові слова потрібно вписати поміж + слешів \"/\"." softDescription: "Приховати записи які відповідають критеріям зі стрічки подій." - hardDescription: "Приховати записи які відповідають критеріям зі стрічки подій. Також приховані записи не будуть додані до стрічки подій навіть якщо критерії буде змінено." + hardDescription: "Приховати записи які відповідають критеріям зі стрічки подій. + Також приховані записи не будуть додані до стрічки подій навіть якщо критерії + буде змінено." soft: "М'яко" hard: "Жорстко" mutedNotes: "Заблоковані нотатки" @@ -942,21 +1007,32 @@ _tutorial: step1_1: "Ласкаво просимо!" step1_2: "Давайте налаштуємо вас. Ви будете працювати в найкоротші терміни!" step2_1: "Спочатку, будь ласка, заповніть свій профіль" - step2_2: "Надавши деяку інформацію про себе, іншим людям буде легше зрозуміти, чи хочуть вони бачити ваші записи або стежити за вами." + step2_2: "Надавши деяку інформацію про себе, іншим людям буде легше зрозуміти, чи + хочуть вони бачити ваші записи або стежити за вами." step3_1: "Тепер настав час стежити за деякими людьми!" - step3_2: "Ваша домашня і соціальна стрічки ґрунтуються на тому, за ким ви стежите, тому для початку спробуйте стежити за кількома акаунтами.\nНатисніть на гурток із плюсом у правому верхньому кутку профілю, щоб стежити за ним." + step3_2: "Ваша домашня і соціальна стрічки ґрунтуються на тому, за ким ви стежите, + тому для початку спробуйте стежити за кількома акаунтами.\nНатисніть на гурток + із плюсом у правому верхньому кутку профілю, щоб стежити за ним." step4_1: "Давайте вийдемо на вас" - step4_2: "Для свого першого повідомлення деякі люди люблять робити {introduction} повідомлення або просте \"Hello world!\"" + step4_2: "Для свого першого повідомлення деякі люди люблять робити {introduction} + повідомлення або просте \"Hello world!\"" step5_1: "Тимчасові рамки, скрізь тимчасові рамки!" step5_2: "У вашому екземплярі включені {timelines} різних часових ліній." - step5_3: "Головна {icon} часова шкала - це шкала, де ви можете бачити повідомлення ваших підписників." - step5_4: "Місцева {icon} тимчасова шкала - це шкала, де ви можете бачити повідомлення всіх інших користувачів даного екземпляра" - step5_5: "Тимчасова шкала Рекомендовані {icon} - це шкала, де ви можете бачити повідомлення від інстанцій, рекомендованих адміністраторами." - step5_6: "На часовій шкалі Social {icon} відображаються повідомлення від друзів ваших підписників" - step5_7: "Глобальна {icon} часова шкала - це місце, де ви можете бачити повідомлення від усіх інших підключених екземплярів" + step5_3: "Головна {icon} часова шкала - це шкала, де ви можете бачити повідомлення + ваших підписників." + step5_4: "Місцева {icon} тимчасова шкала - це шкала, де ви можете бачити повідомлення + всіх інших користувачів даного екземпляра" + step5_5: "Тимчасова шкала Рекомендовані {icon} - це шкала, де ви можете бачити повідомлення + від інстанцій, рекомендованих адміністраторами." + step5_6: "На часовій шкалі Social {icon} відображаються повідомлення від друзів + ваших підписників" + step5_7: "Глобальна {icon} часова шкала - це місце, де ви можете бачити повідомлення + від усіх інших підключених екземплярів" step6_1: "Отже, що це за місце?" - step6_2: "Ну, ви не просто приєдналися до Кальки. Ви приєдналися до порталу в Fediverse, взаємопов'язаної мережі з тисяч серверів, званих \"інстансами\"." - step6_3: "Кожен сервер працює по-своєму, і не на всіх серверах працює Calckey. Але цей працює! Це трохи складно, але ви швидко розберетеся" + step6_2: "Ну, ви не просто приєдналися до Кальки. Ви приєдналися до порталу в Fediverse, + взаємопов'язаної мережі з тисяч серверів, званих \"інстансами\"." + step6_3: "Кожен сервер працює по-своєму, і не на всіх серверах працює Calckey. Але + цей працює! Це трохи складно, але ви швидко розберетеся" step6_4: "Тепер ідіть, вивчайте і розважайтеся!" _2fa: registerSecurityKey: "Зареєструвати новий ключ безпеки" @@ -1078,7 +1154,8 @@ _profile: youCanIncludeHashtags: "Ви також можете включити хештеги у свій опис." metadata: "Додаткова інформація" metadataEdit: "Редагувати додаткову інформацію" - metadataDescription: "Ви можете вказати до чотирьох пунктів додаткової інформації у своєму профілі." + metadataDescription: "Ви можете вказати до чотирьох пунктів додаткової інформації + у своєму профілі." metadataLabel: "Назва" metadataContent: "Вміст" changeAvatar: "Змінити аватар" @@ -1388,7 +1465,8 @@ _pages: _for: arg1: "Кількість повторень" arg2: "Дія" - typeError: "Паз {slot} приймає \"{expect}\" тип, але надана змінна має тип \"{actual}\"!" + typeError: "Паз {slot} приймає \"{expect}\" тип, але надана змінна має тип \"\ + {actual}\"!" thereIsEmptySlot: "Паз {slot} пустий!" types: string: "Текст" @@ -1453,3 +1531,95 @@ _deck: list: "Списки" mentions: "Згадки" direct: "Особисте" +removeReaction: Видалити вашу реакцію +renoteMute: Ігнорувати поширення +renoteUnmute: Показувати поширення +flagSpeakAsCat: Говорити як кішка +accessibility: Доступність +priority: Пріорітет +high: Високий +customCss: Користувацькі CSS +itsOn: Увімкнено +showingPastTimeline: Наразі відображається стара стрічка +enabled: Увімкнено +noMaintainerInformationWarning: Інформація про супровідника не налаштована. +recommended: Рекомендоване +resolved: Вирішено +itsOff: Вимкнено +emailRequiredForSignup: Вимагати адресу електронної пошти для реєстрації +moderation: Модерація +selectInstance: Оберіть сервер +instanceSecurity: Безпека сервера +searchPlaceholder: Шукати в Calckey +editNote: Відредагувати запис +enableEmojiReactions: Ввімкнути реакції емодзі +low: Низький +emailNotConfiguredWarning: Адрес електронної пошти не встановлено. +unresolved: Не вирішено +offline: Не в мережі +disabled: Вимкнено +configure: Налаштувати +popularPosts: Популярні сторінки +silenced: Ігнорується +manageGroups: Керування групами +active: Активний +whatIsNew: Показати зміни +deleted: Видалено +selectChannel: Виберіть канал +flagSpeakAsCatDescription: Ваші записи будуть няніфіковані у режимі кота +userSaysSomethingReason: '{name} сказав(ла) {reason}' +clear: Очистити +userInfo: Інформація про користувача +selectAccount: Оберіть обліковий запис +switchAccount: Змінити обліковий запис +accounts: Облікові записи +switch: Змінити +noBotProtectionWarning: Захист від ботів не налаштовано. +gallery: Галерея +recentPosts: Недавні сторінки +privateModeInfo: Якщо увімкнено, лише сервери з білого списку можуть федеруватися + з вашим сервером. Всі повідомлення будуть приховані від публіки. +troubleshooting: Вирішення проблем +customCssWarn: Цей параметр слід використовувати лише тоді, коли ви знаєте, що він + робить. Введення неправильних значень може призвести до того, що клієнт перестане + нормально функціонувати. +newer: новіші +older: старіші +addDescription: Додати опис +notSpecifiedMentionWarning: У цьому записі згадуються користувачі, яких не було включено + до списку одержувачів +markAllAsRead: Позначити все як прочитане +userPagePinTip: Ви можете відображати записи тут, вибравши "Прикріпити до профілю" + в меню окремих записів. +unknown: Невідомо +onlineStatus: Онлайн-статус +hideOnlineStatus: Приховати онлайн-статус +online: В мережі +breakFollow: Видалити підписника +translate: Перекласти +translatedFrom: Перекладено з {x} +userSaysSomethingReasonQuote: '{name} цитував запис з {reason}' +userSaysSomethingReasonRenote: '{name} поширив запис з {reason}' +notRecommended: Не рекомендується +botProtection: Захист від ботів +instanceBlocking: Керування Федерацією +privateMode: Приватний режим +allowedInstances: Сервери у білому списку +previewNoteText: Показати прев'ю +antennaInstancesDescription: Введіть по одному хосту сервера на рядок +breakFollowConfirm: Ви дійсно бажаєте видалити підписника? +ads: Реклама +cw: Попередження про вміст +hiddenTags: Приховані хештеги +noInstances: Немає серверів +misskeyUpdated: Calckey оновлено! +received: Отримане +xl: Надвеликий +searchResult: Результати пошуку +useBlurEffect: Використовувати ефекти розмиття в інтерфейсі +learnMore: Дізнатися більше +usernameInfo: Ім'я, яке ідентифікує ваш обліковий запис серед інших на цьому сервері. Ви + можете використовувати алфавіт (a~z, A~Z), цифри (0~9) або знаки підкреслення (_). + Ім'я користувача не може бути змінено пізніше. +noThankYou: Ні, дякую +keepCw: Зберігати попередження про вміст From 7a7de755d132c4835adf9fa177080d5978682fc3 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 18:38:53 -0700 Subject: [PATCH 131/162] remove trailing slash --- .../backend/src/server/api/endpoints/admin/update-meta.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index ce2c5c802..d11e6b964 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -224,10 +224,9 @@ export default define(meta, paramDef, async (ps, me) => { if (set.recommendedInstances?.length > 0) { set.recommendedInstances.forEach((instance, index) => { if (/^https?:\/\//i.test(instance)) { - set.recommendedInstances![index] = instance.replace( - /^https?:\/\//i, - "", - ); + set.recommendedInstances![index] = instance + .replace(/^https?:\/\//i, "") + .replace(/\/$/, ""); } }); } From 4435c460e66d75160b71de83ab75f1c07b16e9df Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 18:39:51 -0700 Subject: [PATCH 132/162] chore: :busts_in_silhouette: patrons --- patrons.json | 1 + 1 file changed, 1 insertion(+) diff --git a/patrons.json b/patrons.json index cf56fa839..6cb14afa6 100644 --- a/patrons.json +++ b/patrons.json @@ -93,6 +93,7 @@ "@dracoling@firetribe.org", "@Space6host@calckey.social", "@zakalwe@plasmatrap.com", + "@seasicksailor@calckey.social", "\nInterkosmos Link" ] } From 59fdc77cae0df18e5481d9310480aef3d4f9affa Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 20:26:07 -0700 Subject: [PATCH 133/162] chore: :busts_in_silhouette: patrons --- patrons.json | 1 + 1 file changed, 1 insertion(+) diff --git a/patrons.json b/patrons.json index 6cb14afa6..28a3b5870 100644 --- a/patrons.json +++ b/patrons.json @@ -94,6 +94,7 @@ "@Space6host@calckey.social", "@zakalwe@plasmatrap.com", "@seasicksailor@calckey.social", + "@Hunkabilly@calckey.world", "\nInterkosmos Link" ] } From 3255066fe4d01d2a2acb248a657e555c00ab5b47 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 23:03:07 -0700 Subject: [PATCH 134/162] feat: :sparkles: seperate sponsors and patrons --- locales/en-US.yml | 1 + .../src/server/api/endpoints/patrons.ts | 8 +++-- packages/client/src/pages/about-calckey.vue | 35 ++++++++++++++----- packages/client/src/pages/user/home.vue | 7 ++-- patrons.json | 9 ++++- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 8e1d0ba3c..76bc5c24a 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1228,6 +1228,7 @@ _aboutMisskey: donateHost: "Donate to {host}" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" + sponsors: "Calckey sponsors" patrons: "Calckey patrons" patronsList: "Listed chronologically, not by donation size. Donate with the link above to get your name on here!" _nsfw: diff --git a/packages/backend/src/server/api/endpoints/patrons.ts b/packages/backend/src/server/api/endpoints/patrons.ts index 696d0e338..8ca1f8902 100644 --- a/packages/backend/src/server/api/endpoints/patrons.ts +++ b/packages/backend/src/server/api/endpoints/patrons.ts @@ -9,7 +9,7 @@ const _dirname = dirname(_filename); export const meta = { tags: ["meta"], - description: "Get list of Calckey patrons from Codeberg", + description: "Get Calckey patrons", requireCredential: false, requireCredentialPrivateMode: false, @@ -51,6 +51,8 @@ export default define(meta, paramDef, async (ps) => { }); await redisClient.set("patrons", JSON.stringify(patrons), "EX", 3600); } - - return patrons["patrons"]; + return { + patrons: patrons["patrons"], + sponsors: patrons["sponsors"], + }; }); diff --git a/packages/client/src/pages/about-calckey.vue b/packages/client/src/pages/about-calckey.vue index fb508239b..eb06a6104 100644 --- a/packages/client/src/pages/about-calckey.vue +++ b/packages/client/src/pages/about-calckey.vue @@ -127,6 +127,25 @@ ></template > </FormSection> + <FormSection> + <template #label + ><Mfm :text="`$[x2 $[jelly ❤] ${i18n.ts._aboutMisskey.sponsors}]`" /> + </template + > + <MkSparkle> + <span + v-for="sponsor in sponsors" + :key="sponsor" + style=" + margin-bottom: 0.5rem; + margin-right: 0.5rem; + font-size: 1.7rem; + " + > + <Mfm :text="`${sponsor}`" /> + </span> + </MkSparkle> + </FormSection> <FormSection> <template #label ><Mfm text="$[jelly ❤]" /> @@ -147,9 +166,7 @@ <Mfm :text="`${patron}`" /> </span> </MkSparkle> - <template #caption>{{ - i18n.ts._aboutMisskey.morePatrons - }}</template> + <p>{{ i18n.ts._aboutMisskey.morePatrons }}</p> </FormSection> </div> </MkSpacer> @@ -172,11 +189,13 @@ import * as os from "@/os"; import { definePageMetadata } from "@/scripts/page-metadata"; let patrons = []; -try { - patrons = await os.api("patrons", { forceUpdate: true }); -} catch { - console.error("Codeberg's down."); -} +let sponsors = []; +const patronsResp = await os.api("patrons", { forceUpdate: true }); +patrons = patronsResp.patrons; +sponsors = patronsResp.sponsors; + + +patrons = patrons.filter((patron) => !sponsors.includes(patron)); let easterEggReady = false; let easterEggEmojis = $ref([]); diff --git a/packages/client/src/pages/user/home.vue b/packages/client/src/pages/user/home.vue index e87052ea2..9d643c0b6 100644 --- a/packages/client/src/pages/user/home.vue +++ b/packages/client/src/pages/user/home.vue @@ -461,11 +461,8 @@ const timeForThem = $computed(() => { }); let patrons = []; -try { - patrons = await os.api("patrons"); -} catch { - console.error("Codeberg's down."); -} +const patronsResp = await os.api("patrons"); +patrons = patronsResp.patrons; function parallaxLoop() { parallaxAnimationId = window.requestAnimationFrame(parallaxLoop); diff --git a/patrons.json b/patrons.json index 28a3b5870..f2339e3b8 100644 --- a/patrons.json +++ b/patrons.json @@ -94,7 +94,14 @@ "@Space6host@calckey.social", "@zakalwe@plasmatrap.com", "@seasicksailor@calckey.social", - "@Hunkabilly@calckey.world", + "@geerue@calckey.social", + "@WXFanatic@m.ai6yr.org", + "@Hunkabilly@calckey.world" + ], + "sponsors": [ + "@atomicpoet@calckey.social", + "@unattributed@calckey.social", + "@jtbennett@noc.social", "\nInterkosmos Link" ] } From 10e9c2bfd3d24ede316a520092622f43176bca3a Mon Sep 17 00:00:00 2001 From: Rauf <raufsen11@gmail.com> Date: Sat, 15 Jul 2023 06:00:35 +0000 Subject: [PATCH 135/162] chore: Translated using Weblate (Turkish) Currently translated at 56.5% (1035 of 1830 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/tr/ --- locales/tr-TR.yml | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index d6fecb6e8..82da6f649 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -1111,3 +1111,62 @@ customSplashIcons: Özel açılış ekranı simgeleri (url'ler) recommendedInstancesDescription: Önerilen zaman çizelgesinde görünmesi için satır sonlarıyla ayrılmış önerilen sunucular. `https://` EKLEMEYİN, YALNIZCA etki alanı. recommendedInstances: Önerilen sunucular +enableServerMachineStats: Sunucu donanımı istatistiklerini etkinleştir +_sensitiveMediaDetection: + sensitivityDescription: Hassasiyetin düşürülmesi daha az yanlış tespite yol açarken, + hassasiyeti artırmak daha az tespitin gözden kaçmasına yol açacaktır. + setSensitiveFlagAutomaticallyDescription: Bu seçenek kapatılsa bile dahili algılamanın + sonuçları korunacaktır. + description: Makine Öğrenimi yoluyla NSFW ortamını otomatik olarak tanıyarak sunucu + denetleme çabasını azaltır. Bu, sunucudaki yükü biraz artıracaktır. + sensitivity: Algılama hassasiyeti + analyzeVideos: Videoların analizini etkinleştir + setSensitiveFlagAutomatically: NSFW olarak işaretle + analyzeVideosDescription: Görüntülere ek olarak videoları da analiz eder. Bu, sunucudaki + yükü biraz artıracaktır. +enableIdenticonGeneration: Kimlik oluşturmayı etkinleştir +reactionPickerSkinTone: Tercih edilen emoji cilt tonu +noteId: Gönderi ID +preventAiLearning: AI bot öğrenmesini önleyin +preventAiLearningDescription: Gönderiler ve resimler gibi yüklediğiniz içeriği incelememek + için üçüncü taraf yapay zeka dil modellerini isteyin. +isAdmin: Yönetici +_emailUnavailable: + disposable: Tek kullanımlık mail adresleri kullanılamaz + smtp: Bu mail sunucusu cevap vermiyor + mx: Bu mail sunucusu hatalı + used: Bu mail zaten kullanılıyor + format: Bu mail adresi yanlış +apps: Uygulamalar +findOtherInstance: Başka bir sunucu bul +showWithSparkles: Parıltılarla göster +showPopup: Kullanıcıları pop-up ile bilgilendirin +silencedWarning: Bu sayfa, bu kullanıcılar yöneticinizin susturduğu sunuculardan olduğu + için gösteriliyor, bu nedenle potansiyel olarak spam olabilirler. +isPatron: Calckey Patronu +youHaveUnreadAnnouncements: Okunmamış duyurularınız var +donationLink: Bağış sayfası linki +neverShow: Birdaha gösterme +remindMeLater: Belki sonra +removeQuote: Alıntıyı sil +removeRecipient: Alıcıyı sil +removeMember: Kullanıcıyı sil +customKaTeXMacroDescription: 'Kolayca matematiksel ifadeler yazmak için makrolar kurun! + Gösterim, LaTeX komut tanımlarına uygundur ve \newcommand{\ name}{content} veya + \newcommand{\name}[argüman sayısı]{content} şeklinde yazılır. Örneğin, \newcommand{\add}[2]{#1 + + #2}, \add{3}{foo} öğesini 3 + foo olarak genişletir. Makro adını çevreleyen süslü + parantezler, yuvarlak veya köşeli parantezler olarak değiştirilebilir. Bu, bağımsız + değişkenler için kullanılan parantezleri etkiler. Satır başına bir (ve yalnızca + bir) makro tanımlanabilir ve satırı tanımın ortasından ayıramazsınız. Geçersiz satırlar + basitçe yoksayılır. Yalnızca basit dizi değiştirme işlevleri desteklenir; koşullu + dallanma gibi gelişmiş söz dizimi burada kullanılamaz.' +enableCustomKaTeXMacro: Özel KaTeX makrolarını aktif et +isLocked: Bu hesabın takip onayları var +isModerator: Moderatör +signupsDisabled: Bu sunucudaki kayıtlar şu anda devre dışı, ancak istediğiniz zaman + başka bir sunucuya kaydolabilirsiniz! Bu sunucu için bir davet kodunuz varsa, lütfen + aşağıya girin. +sendModMail: Moderasyon Bildirimi Gönder +noGraze: Calckey ile çakıştığı için lütfen "Graze for Mastodon" tarayıcı uzantısını + devre dışı bırakın. +isBot: Bu hesap bir bottur From f4776712a3ae894767c19cb1b19e282a31ec6848 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 23:13:32 -0700 Subject: [PATCH 136/162] refactor: :recycle: correct params for notes/children+conversion --- packages/backend/src/server/api/endpoints/notes/children.ts | 4 ++-- .../backend/src/server/api/endpoints/notes/conversation.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 9047fcce1..dc536df62 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -1,4 +1,3 @@ -import { Brackets } from "typeorm"; import { Notes } from "@/models/index.js"; import define from "../../define.js"; import { makePaginationQuery } from "../../common/make-pagination-query.js"; @@ -23,13 +22,14 @@ export const meta = { ref: "Note", }, }, -}; +} as const; export const paramDef = { type: "object", properties: { noteId: { type: "string", format: "misskey:id" }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, + depth: { type: "integer", minimum: 1, maximum: 100, default: 12}, sinceId: { type: "string", format: "misskey:id" }, untilId: { type: "string", format: "misskey:id" }, }, diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 2e8f5ef73..47c672736 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -51,7 +51,7 @@ export default define(meta, paramDef, async (ps, user) => { const conversation: Note[] = []; let i = 0; - async function get(id: any) { + async function get(id: string) { i++; const p = await getNote(id, user).catch((e) => { if (e.id === "9725d0ce-ba28-4dde-95a7-2cbb2c15de24") return null; @@ -60,7 +60,7 @@ export default define(meta, paramDef, async (ps, user) => { if (p == null) return; - if (i > ps.offset!) { + if (i > ps.offset) { conversation.push(p); } From 49f543cebcdd2f023378802e1bd11e07ab8e931d Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Fri, 14 Jul 2023 23:16:50 -0700 Subject: [PATCH 137/162] docs: :memo: descriptions for notes/children+conversation endpoints --- packages/backend/src/server/api/endpoints/notes/children.ts | 1 + .../backend/src/server/api/endpoints/notes/conversation.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index dc536df62..3615df024 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -10,6 +10,7 @@ export const meta = { requireCredential: false, requireCredentialPrivateMode: true, + description: "Get threaded/chained replies to a note", res: { type: "array", diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 47c672736..67927794d 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -9,6 +9,7 @@ export const meta = { requireCredential: false, requireCredentialPrivateMode: true, + description: "Get conversation of a note thread/chain by a reply", res: { type: "array", @@ -34,7 +35,7 @@ export const meta = { export const paramDef = { type: "object", properties: { - noteId: { type: "string", format: "misskey:id" }, + noteId: { type: "string", format: "misskey:id", description: "Should be a reply" }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, offset: { type: "integer", default: 0 }, }, From 4be5f3b58ca3b8085a8952a8408e8899a6fd0033 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 00:06:42 -0700 Subject: [PATCH 138/162] refactor: :wastebasket: deprecate DB_MAX_NOTE_TEXT_LENGTH --- .config/example.yml | 2 +- packages/backend/src/const.ts | 3 +-- packages/backend/src/misc/hard-limits.ts | 3 ++- packages/backend/src/server/api/endpoints/admin/update-meta.ts | 1 - packages/megalodon/src/misskey/entities/meta.ts | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.config/example.yml b/.config/example.yml index ba74df8a5..9716915b6 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -121,7 +121,7 @@ redis: # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── -# Maximum length of a post (default 3000, max 8192) +# Maximum length of a post (default 3000, max 250000000) #maxNoteLength: 3000 # Maximum length of an image caption (default 1500, max 8192) diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 7e8f96444..1f1e63292 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,8 +1,7 @@ import config from "@/config/index.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; -export const MAX_NOTE_TEXT_LENGTH = - config.maxNoteLength != null ? config.maxNoteLength : 3000; // <- should we increase this? +export const MAX_NOTE_TEXT_LENGTH = config.maxNoteLength ?? 3000; export const MAX_CAPTION_TEXT_LENGTH = Math.min( config.maxCaptionLength ?? 1500, DB_MAX_IMAGE_COMMENT_LENGTH, diff --git a/packages/backend/src/misc/hard-limits.ts b/packages/backend/src/misc/hard-limits.ts index 51d2c0f5d..f1a58a425 100644 --- a/packages/backend/src/misc/hard-limits.ts +++ b/packages/backend/src/misc/hard-limits.ts @@ -3,8 +3,9 @@ /** * Maximum note text length that can be stored in DB. * Surrogate pairs count as one + * DEPRECARTED: use const/MAX_NOTE_TEXT_LENGTH instead */ -export const DB_MAX_NOTE_TEXT_LENGTH = 8192; +// export const DB_MAX_NOTE_TEXT_LENGTH = 8192; /** * Maximum image description length that can be stored in DB. diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index d11e6b964..2142c7df7 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -1,6 +1,5 @@ import { Meta } from "@/models/entities/meta.js"; import { insertModerationLog } from "@/services/insert-moderation-log.js"; -import { DB_MAX_NOTE_TEXT_LENGTH } from "@/misc/hard-limits.js"; import { db } from "@/db/postgre.js"; import define from "../../define.js"; diff --git a/packages/megalodon/src/misskey/entities/meta.ts b/packages/megalodon/src/misskey/entities/meta.ts index 2e99266ab..7dd5f6400 100644 --- a/packages/megalodon/src/misskey/entities/meta.ts +++ b/packages/megalodon/src/misskey/entities/meta.ts @@ -12,7 +12,7 @@ namespace MisskeyEntity { disableRegistration: boolean disableLocalTimeline: boolean bannerUrl: string - maxNoteTextLength: 300 + maxNoteTextLength: 3000 emojis: Array<Emoji> } } From d33f74adda20cd7a8b7e2bc33fafb6fb20c51c3b Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 00:06:53 -0700 Subject: [PATCH 139/162] chore: :art: format --- .../backend/src/server/api/endpoints/notes/children.ts | 2 +- .../src/server/api/endpoints/notes/conversation.ts | 6 +++++- packages/client/src/components/MkPostForm.vue | 2 +- packages/client/src/pages/about-calckey.vue | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 3615df024..a35b17a02 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -30,7 +30,7 @@ export const paramDef = { properties: { noteId: { type: "string", format: "misskey:id" }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, - depth: { type: "integer", minimum: 1, maximum: 100, default: 12}, + depth: { type: "integer", minimum: 1, maximum: 100, default: 12 }, sinceId: { type: "string", format: "misskey:id" }, untilId: { type: "string", format: "misskey:id" }, }, diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 67927794d..c74da2ec7 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -35,7 +35,11 @@ export const meta = { export const paramDef = { type: "object", properties: { - noteId: { type: "string", format: "misskey:id", description: "Should be a reply" }, + noteId: { + type: "string", + format: "misskey:id", + description: "Should be a reply", + }, limit: { type: "integer", minimum: 1, maximum: 100, default: 10 }, offset: { type: "integer", default: 0 }, }, diff --git a/packages/client/src/components/MkPostForm.vue b/packages/client/src/components/MkPostForm.vue index b1812c2f1..c49001f2a 100644 --- a/packages/client/src/components/MkPostForm.vue +++ b/packages/client/src/components/MkPostForm.vue @@ -400,7 +400,7 @@ const textLength = $computed((): number => { }); const maxTextLength = $computed((): number => { - return instance ? instance.maxNoteTextLength : 1000; + return instance ? instance.maxNoteTextLength : 3000; }); const canPost = $computed((): boolean => { diff --git a/packages/client/src/pages/about-calckey.vue b/packages/client/src/pages/about-calckey.vue index eb06a6104..af06ea65a 100644 --- a/packages/client/src/pages/about-calckey.vue +++ b/packages/client/src/pages/about-calckey.vue @@ -129,9 +129,10 @@ </FormSection> <FormSection> <template #label - ><Mfm :text="`$[x2 $[jelly ❤] ${i18n.ts._aboutMisskey.sponsors}]`" /> - </template - > + ><Mfm + :text="`$[x2 $[jelly ❤] ${i18n.ts._aboutMisskey.sponsors}]`" + /> + </template> <MkSparkle> <span v-for="sponsor in sponsors" @@ -194,7 +195,6 @@ const patronsResp = await os.api("patrons", { forceUpdate: true }); patrons = patronsResp.patrons; sponsors = patronsResp.sponsors; - patrons = patrons.filter((patron) => !sponsors.includes(patron)); let easterEggReady = false; From 63d28adeff9ed2b5e5d84c58e88a443c2637dc83 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 00:19:09 -0700 Subject: [PATCH 140/162] =?UTF-8?q?fix:=20=F0=9F=90=9B=20allow=20up=20to?= =?UTF-8?q?=201024=20chars=20for=20SMTP=20login?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #10472 --- .../migration/1678426061773-tweak-varchar-length.js | 10 ++++++++++ packages/backend/src/models/entities/meta.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 packages/backend/migration/1678426061773-tweak-varchar-length.js diff --git a/packages/backend/migration/1678426061773-tweak-varchar-length.js b/packages/backend/migration/1678426061773-tweak-varchar-length.js new file mode 100644 index 000000000..883374599 --- /dev/null +++ b/packages/backend/migration/1678426061773-tweak-varchar-length.js @@ -0,0 +1,10 @@ +export class tweakVarcharLength1678426061773 { + name = 'tweakVarcharLength1678426061773' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "smtpUser" TYPE character varying(1024)`, undefined); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "smtpPass" TYPE character varying(1024)`, undefined); + } + + async down(queryRunner) {} +} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index d3de7ba53..e90a5269a 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -326,13 +326,13 @@ export class Meta { public smtpPort: number | null; @Column("varchar", { - length: 128, + length: 1024, nullable: true, }) public smtpUser: string | null; @Column("varchar", { - length: 128, + length: 1024, nullable: true, }) public smtpPass: string | null; From 85167cf15d5c70b5348f9105306af8d033542be3 Mon Sep 17 00:00:00 2001 From: jolupa <jolupameister@gmail.com> Date: Sat, 15 Jul 2023 07:36:02 +0000 Subject: [PATCH 141/162] chore: Translated using Weblate (Catalan) Currently translated at 100.0% (1831 of 1831 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/ca/ --- locales/ca-ES.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 4d265d7ee..8fb57e879 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1609,6 +1609,7 @@ _aboutMisskey: pleaseDonateToHost: Penseu també en fer una donació a la vostre instància, {host}, per ajudar-lo a suportar els costos de funcionament. donateHost: Fes una donació a {host} + sponsors: Patrocinadors de Calckey unknown: Desconegut pageLikesCount: Nombre de pàgines amb M'agrada youAreRunningUpToDateClient: Estás fent servir la versió del client més nova. From c8d3f5571afbec1b5e76819553cd1683ffd4b934 Mon Sep 17 00:00:00 2001 From: Rauf <raufsen11@gmail.com> Date: Sat, 15 Jul 2023 06:54:30 +0000 Subject: [PATCH 142/162] chore: Translated using Weblate (Turkish) Currently translated at 100.0% (1831 of 1831 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/tr/ --- locales/tr-TR.yml | 986 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 970 insertions(+), 16 deletions(-) diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index 82da6f649..8c3c15f33 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -1,9 +1,6 @@ _lang_: "Türkçe" -introMisskey: "Açık kaynaklı bir dağıtılmış mikroblog hizmeti olan Calckey'e hoş geldiniz.\n - Misskey, neler olup bittiğini paylaşmak ve herkese sizden bahsetmek için \"notlar\"\ - \ oluşturmanıza olanak tanıyan, açık kaynaklı, dağıtılmış bir mikroblog hizmetidir.\n - Herkesin notlarına kendi tepkilerinizi hızlıca eklemek için \"Tepkiler\" özelliğini - de kullanabilirsiniz👍.\nYeni bir dünyayı keşfedin🚀." +introMisskey: "Hoş geldin! Calckey, sonsuza kadar ücretsiz olan, açık kaynaklı, merkezi + olmayan bir sosyal medya platformudur! 🚀" monthAndDay: "{month}Ay {day}Gün" search: "Arama" notifications: "Bildirimler" @@ -11,10 +8,10 @@ username: "Kullanıcı Adı" password: "Şifre" forgotPassword: "şifremi unuttum" ok: "TAMAM" -gotIt: "Anladım" +gotIt: "Anladım!" cancel: "İptal" enterUsername: "Kullanıcı adınızı giriniz" -noNotes: "Gönderiler mevcut değil." +noNotes: "Gönderiler mevcut değil" noNotifications: "Bildirim bulunmuyor" settings: "Ayarlar" basicSettings: "Temel Ayarlar" @@ -22,11 +19,11 @@ otherSettings: "Diğer Ayarlar" openInWindow: "Bir pencere ile aç" profile: "Profil" timeline: "Zaman çizelgesi" -noAccountDescription: "Bu kullanıcı henüz biyografisini yazmadı" -login: "Giriş Yap " +noAccountDescription: "Bu kullanıcı henüz hakkındasını yazmadı." +login: "Giriş Yap" logout: "Çıkış Yap" signup: "Kayıt Ol" -uploading: "Yükleniyor" +uploading: "Yükleniyor..." users: "Kullanıcı" addUser: "Kullanıcı Ekle" favorite: "Favoriler" @@ -54,17 +51,175 @@ user: "Kullanıcı" searchByGoogle: "Arama" _mfm: search: "Arama" + play: MFM'i çal + stop: MFM'i durdur + cheatSheet: MFM Kopya Kağıdı + intro: MFM, Misskey, Calckey, Akkoma ve daha pek çok yerde kullanılabilen bir biçimlendirme + dilidir. Burada mevcut tüm MFM sözdiziminin bir listesini görüntüleyebilirsiniz. + link: Link + boldDescription: Harfleri kalınlaştırarak vurgular. + small: Küçük + smallDescription: İçeriği küçük ve ince görüntüler. + warn: MFM, hızla hareket eden veya gösterişli animasyonlar içerebilir + alwaysPlay: Her zaman tüm animasyonlu MFM'yi otomatik oynat + x4Description: İçeriği büyükten de büyükten daha büyük görüntüler. + rainbowDescription: İçeriğin gökkuşağı renklerinde görünmesini sağlar. + bounceDescription: İçeriğe sıçarayan bir animasyon verir. + sparkle: Işıltı + sparkleDescription: İçeriğe ışıltılı bir parçacık efekti verir. + rotateDescription: İçeriği belirli bir açıyla döndürür. + fadeDescription: İçeriği içeri ve dışarı karartır. + fade: Karart + position: Pozisyon + blockCode: Kod (Blok) + crop: Kırp + positionDescription: İçeriği belirli bir miktarda taşıyın. + scale: Ölçek + scaleDescription: İçeriği belirtilen bir miktara göre ölçeklendirin. + foreground: Ön plan rengi + mention: Bahset + mentionDescription: Bir et-sembolü (@) ve bir kullanıcı adı kullanarak bir kullanıcı + belirleyebilirsiniz. + hashtag: Etiket + dummy: Calckey, Fediverse dünyasını genişletiyor + hashtagDescription: Sayı işareti ve metin kullanarak bir etiket belirtebilirsiniz. + url: URL + urlDescription: URL'ler görüntülenebilir. + inlineMath: Matematik (Satır İçi) + blockCodeDescription: Bir blokta çok satırlı (program) kod için sözdizimi vurgulamasını + görüntüler. + inlineMathDescription: Matematik formüllerini (KaTeX) satır içinde görüntüleyin + quote: Alıntı + quoteDescription: İçeriği alıntı olarak görüntüler. + twitch: Animasyon (Seğir) + emoji: Özel Emoji + jelly: Animasyon (Jöle) + blur: Bulanık + blurDescription: İçeriği bulanıklaştırır. Fareyle üzerine gelindiğinde net bir şekilde + görüntülenecektir. + spinDescription: İçeriğe dönen bir animasyon verir. + plainDescription: Bu MFM efektinde bulunan tüm MFM'lerin etkilerini devre dışı bırakır. + background: Arka plan rengi + backgroundDescription: Metnin arka plan rengini değiştirin. + jump: Animasyon (Zıpla) + cropDescription: İçeriği kırpar. + advancedDescription: Devre dışı bırakılırsa, animasyonlu MFM oynatılmadığı sürece + yalnızca temel işaretlemeye izin verir + bold: Kalın + inlineCodeDescription: (Program) kodu için satır içi sözdizimi vurgulamasını görüntüler. + flip: Tersine Çevir + flipDescription: İçeriği yatay veya dikey olarak çevirir. + font: Yazı Tipi + twitchDescription: İçeriğe güçlü bir şekilde seğiren bir animasyon verir. + spin: Animasyon (Dön) + x2Description: İçeriği büyük gösterir. + rotate: Döndür + plain: Düz + linkDescription: Metnin belirli bölümleri bir URL olarak görüntülenebilir. + searchDescription: Önceden girilmiş metin içeren bir arama kutusu görüntüler. + blockMathDescription: Matematik formüllerini (KaTeX) bir blokta görüntüleyin + jumpDescription: İçeriğe zıplama animasyonu verir. + rainbow: Gökkuşağı + x4: İnanılmaz derecede büyük + tadaDescription: İçeriğe "Tada!" benzeri bir animasyon verir. + shake: Animasyon (Salla) + x3: Büyük göster + blockMath: Matematik (Blok) + x2: Büyük + fontDescription: İçeriğin görüntüleneceği yazı tipini ayarlar. + foregroundDescription: Metnin ön plan rengini değiştirin. + centerDescription: İçeriği ortada görüntüler. + inlineCode: Kod (Satır İçi) + advanced: Gelişmiş MFM + center: Ortala + x3Description: İçeriği daha büyük gösterir. + tada: Animasyon (Tada) + emojiDescription: Özel bir emoji adını iki nokta ile çevreleyerek, özel emoji görüntülenebilir. + jellyDescription: İçeriğe jöle benzeri bir animasyon verir. + shakeDescription: İçeriğe sallanan bir animasyon verir. + bounce: Animasyon (Sıçra) _sfx: notification: "Bildirim" + noteMy: Kendi Gönderim + note: Yeni gönderi + antenna: Anten + chat: Sohbet + channel: Kanal bildirimleri + chatBg: Sohbet (Arkaplan) _widgets: notifications: "Bildirim" timeline: "Zaman çizelgesi" + photos: Fotoğraflar + userList: Kullanıcı Listesi + _userList: + chooseList: Liste seç + onlineUsers: Aktif Kullanıcılar + aiscript: AiScript Konsolu + activity: Aktivite + digitalClock: Dijital Saat + unixClock: UNIX Saati + meiliIndexCount: Indexlenmiş gönderiler + calendar: Takvim + trends: Popüler + memo: Yapışkan Notlar + rssTicker: RSS Ticker + federation: Federasyon + instanceCloud: Sunucu Bulutu + postForm: Gönderi Formu + meiliSize: Index boyutu + slideshow: Slayt Gösterisi + button: Düğme + clock: Saat + rss: RSS Okuyucu + serverInfo: Sunucu Bilgisi + meiliStatus: Sunucu Durumu + jobQueue: İş Sırası + serverMetric: Sunucu Bilgileri _profile: username: "Kullanıcı Adı" + changeBanner: Afişini değiştir + locationDescription: Önce şehrinizi girerseniz, yerel saatinizi diğer kullanıcılara + gösterecektir. + youCanIncludeHashtags: Hakkımdan'da etiket kullanabilirsin. + description: Hakkımda + metadataDescription: Bunları kullanarak profilinizde ek bilgi alanları görüntüleyebilirsiniz. + metadata: Ek Bilgi + metadataContent: İçerik + metadataLabel: Etiket + changeAvatar: Avatarını değiştir + name: İsim + metadataEdit: Ek Bilgini Düzenle _deck: _columns: notifications: "Bildirim" tl: "Zaman çizelgesi" + antenna: Anten + list: Liste + widgets: Araçlar + channel: Kanal + direct: Direkt mesajlar + main: Ana + mentions: Bahsetmeler + swapLeft: Sol sütunla değiştir + addColumn: Sütun ekle + configureColumn: Sütun ayarları + swapRight: Sağ sütunla değiştir + swapUp: Üstteki sütunla değiştir + stackLeft: Sol sütunla birleştir + swapDown: Alttaki sütunla değiştir + popRight: Sağdaki sütunu aç + introduction2: İstediğiniz zaman yeni sütunlar eklemek için ekranın sağındaki + + işaretini tıklayın. + alwaysShowMainColumn: Her zaman ana sütunu göster + columnAlign: Sütunları hizala + profile: Çalışma alanı + newProfile: Yeni çalışma alanı + renameProfile: Çalışma alanını yeniden adlandır + deleteProfile: Çalışma alanını sil + nameAlreadyExists: Bu çalışma alanı zaten mevcut. + introduction: Sütunları özgürce düzenleyerek sizin için mükemmel arayüzü oluşturun! + widgetsIntroduction: Lütfen sütun menüsünde "Araç'ları düzenle"yi seçin ve bir widget + ekleyin. searchPlaceholder: Calckey'de Ara reply: Yanıtla jumpToPrevious: Öncekini görüntüle @@ -80,7 +235,7 @@ headlineMisskey: Sonsuza kadar ücretsiz, açık kaynak kodlu, merkeziyetsiz sos platformu! 🚀 loadMore: Daha fazla yükle instance: Sunucu -fetchingAsApObject: Fedevren'den çekiliyor +fetchingAsApObject: Fediverse'den çekiliyor removeReaction: Tepkini sil rememberNoteVisibility: Gönderi görünürlüğü ayarlarını hatırla attachCancel: Eklentiyi kaldır @@ -279,7 +434,7 @@ lockedAccountInfo: Gönderi görünürlüğünüzü "Yalnızca takipçiler" olar görülebilir. unlikeConfirm: Beğeniyi kaldırmak istiyor musunuz? notSpecifiedMentionWarning: Bu gönderi, alıcı olarak dahil edilmeyen kullanıcılardan - bahsetmektedir. + bahsetmektedir hideOnlineStatus: Çevrimiçi bilgisini gizle hideOnlineStatusDescription: Çevrimiçi durumunuzu gizlemek, arama gibi bazı özelliklerin rahatlığını azaltır. @@ -517,7 +672,7 @@ objectStorageRegionDesc: "'xx-east-1' gibi bir bölge belirtin. Hizmetiniz bölg arasında ayrım yapmıyorsa, bunu boş bırakın veya 'us-east-1' girin." objectStorageUseSSL: SSL Kullan popout: Açılır Pencere -volume: Ses +volume: Ses Kuvveti showInPage: Sayfada göster masterVolume: Ana ses undeck: Desteden çık @@ -565,7 +720,7 @@ moveAccountDescription: Bu süreç geri döndürülemez. Taşımadan önce yeni bu hesap için bir takma ad ayarladığınızdan emin olun. Lütfen @person@server.com şeklinde biçimlendirilmiş hesabın etiketini girin emojis: Emoji -flagAsCat: Kedi misin? +flagAsCat: Kedi misin? 😺 selectChannel: Kanal seç emojiName: Emoji adı showOnRemote: Uzak sunucuda görüntüle @@ -922,7 +1077,7 @@ manageAccounts: Hesapları Düzenle makeReactionsPublicDescription: Bu, tüm geçmiş tepkilerinizin listesini herkesin görebileceği bir hale getirecektir. unmuteThread: İleti dizisinin sesini aç -ffVisibility: Takipçiler/Takipçiler Görünürlüğü +ffVisibility: Takipler/Takipçiler Görünürlüğü reflectMayTakeTime: Bunun yansıması biraz zaman alabilir. cropImageAsk: Bu resmi kırpmak istediğinize emin misiniz? check: Kontrol Et @@ -1109,7 +1264,7 @@ adminCustomCssWarn: Bu ayar yalnızca ne işe yaradığını biliyorsanız kulla emin olun. customSplashIcons: Özel açılış ekranı simgeleri (url'ler) recommendedInstancesDescription: Önerilen zaman çizelgesinde görünmesi için satır - sonlarıyla ayrılmış önerilen sunucular. `https://` EKLEMEYİN, YALNIZCA etki alanı. + sonlarıyla ayrılmış önerilen sunucular. recommendedInstances: Önerilen sunucular enableServerMachineStats: Sunucu donanımı istatistiklerini etkinleştir _sensitiveMediaDetection: @@ -1170,3 +1325,802 @@ sendModMail: Moderasyon Bildirimi Gönder noGraze: Calckey ile çakıştığı için lütfen "Graze for Mastodon" tarayıcı uzantısını devre dışı bırakın. isBot: Bu hesap bir bottur +_2fa: + renewTOTPOk: Yeniden Yapılandır + registerTOTP: Doğrulayıcı uygulamasını kaydedin + renewTOTPCancel: İptal Et + renewTOTPConfirm: Bu, önceki uygulamanızdaki doğrulama kodlarının çalışmamasına + neden olur + alreadyRegistered: Zaten bir 2 faktörlü kimlik doğrulama cihazını kaydettiniz. + chromePasskeyNotSupported: Chrome geçiş anahtarları şu anda desteklenmemektedir. + registerSecurityKey: Bir güvenlik veya geçiş anahtarı kaydedin + securityKeyName: Bir anahtar adı girin + removeKey: Güvenlik anahtarını kaldır + removeKeyConfirm: '{name} anahtarı gerçekten silinsin mi?' + renewTOTP: Kimlik doğrulayıcı uygulamasını yeniden yapılandırın + token: 2FA Tokeni + step1: Öncelikle, cihazınıza bir kimlik doğrulama uygulaması ({a} veya {b} gibi) + yükleyin. + step2Click: Bu QR koduna tıklamak, 2FA'yı güvenlik anahtarınıza veya telefon kimlik + doğrulayıcı uygulamanıza kaydetmenize olanak tanır. + step3Title: Bir kimlik doğrulama kodu girin + securityKeyNotSupported: Tarayıcınız güvenlik anahtarlarını desteklemiyor. + step2: Ardından, bu ekranda görüntülenen QR kodunu tarayın. + step2Url: "Bir masaüstü programı kullanıyorsanız bu URL'yi de girebilirsiniz:" + step3: Kurulumu tamamlamak için uygulamanız tarafından sağlanan tokeni girin. + step4: Şu andan itibaren, gelecekteki herhangi bir oturum açma denemesi böyle bir + oturum açma tokeni isteyecektir. + securityKeyInfo: Parmak izi veya PIN kimlik doğrulamasının yanı sıra, hesabınızın + güvenliğini daha da artırmak için FIDO2'yi destekleyen donanım güvenlik anahtarları + aracılığıyla kimlik doğrulama ayarlayabilirsiniz. + tapSecurityKey: Güvenlik veya geçiş anahtarını kaydetmek için lütfen tarayıcınızı + takip edin + registerTOTPBeforeKey: Bir güvenlik veya geçiş anahtarı kaydetmek için lütfen bir + kimlik doğrulama uygulaması kurun. + whyTOTPOnlyRenew: Kimlik doğrulayıcı uygulaması, bir güvenlik anahtarı kaydedildiği + sürece kaldırılamaz. +_poll: + voted: Oylandı + deadlineTime: Zaman + remainingDays: '{d} gün {h} saat kaldı' + remainingHours: '{h} saat {m} dakika kaldı' + remainingSeconds: '{s} saniye kaldı' + remainingMinutes: '{m} dakika {s} saniye kaldı' + noOnlyOneChoice: En az 2 seçenek gerekiyor + noMore: Daha fazla seçenek ekleyemezsin + at: Bitiş... + deadlineDate: Bitiş tarihi + duration: Süre + votesCount: '{n} oy' + expiration: Anketi bitir + totalVotes: toplam {n} oy + closed: Bitti + infinite: Asla + vote: Oyla + showResult: Sonuçları görüntüle + after: "'den sonra bitiş..." + choiceN: Seçenek {n} + canMultipleVote: Birden fazla seçime izin ver +_theme: + code: Tema kodu + description: Açıklama + builtinThemes: Yerleşik temalar + color: Renk + keys: + fgHighlighted: Vurgulanan Metin + infoWarnFg: Uyarı metni + mention: Bahsetme + mentionMe: Bahsetme (Kendim) + buttonBg: Düğme arka planı + buttonHoverBg: Düğme arka planı (Üstüne Gelince) + shadow: Gölge + navBg: Kenar çubuğu arka planı + accent: Vurgu + fg: Yazı + dateLabelFg: Tarih etiketi metni + navActive: Kenar çubuğu metni (Etkin) + wallpaperOverlay: Arkaplan arayüzü + messageBg: Sohbet arkaplanı + focus: Fokus + accentLighten: Vurgu (Aydınlık) + bg: Arkaplan + indicator: Gösterge + hashtag: Etiket + renote: Yükseltme + modalBg: Modal arka plan + divider: Bölücü + scrollbarHandle: Kaydırma çubuğu kolu + scrollbarHandleHover: Kaydırma çubuğu tutacağı (Üzerine Gelince) + infoBg: Bilgi geçmişi + accentDarken: Vurgu (Karanlık) + header: Başlık + navFg: Kenar çubuğu metni + navIndicator: Kenar çubuğu göstergesi + link: Link + infoFg: Bilgi metni + infoWarnBg: Uyarı arka planı + badge: Rozen + panel: Panel + navHoverFg: Kenar çubuğu metni (Üzerine Gelince) + cwBg: CW düğmesi arka planı + cwFg: CW düğmesi meni + cwHoverBg: CW düğmesi arka planı (Üzerine Gelince) + toastFg: Bildirim metni + inputBorder: Giriş alanı sınırı + listItemHoverBg: Liste öğesi arka planı (Üstüne Gelince) + toastBg: Bildirim arka planı + driveFolderBg: Drive klasörü arkaplanı + funcKind: Fonksiyon tipi + argument: Argüman + lighten: Aydınlat + inputConstantName: Bu sabit için bir ad girin + deleteConstantConfirm: '{const} sabitini gerçekten silmek istiyor musunuz?' + explore: Temaları Keşfet + darken: Karart + base: Temel + manage: Temaları düzenle + installedThemes: Yüklenen temalar + invalid: Bu temanın biçimi geçersiz + make: Tema oluştur + key: Anahtar + alpha: Opaklık + install: Tema yükle + installed: '{name} başarıyla yüklendi' + alreadyInstalled: Bu tema zaten yüklendi + importInfo: Buraya tema kodunu girerseniz, onu tema düzenleyiciye aktarabilirsiniz + func: Fonksiyonlar + basedProp: Referenslanan özellik + constant: Sabit + defaultValue: Varsayılan değer + refConst: Bir sabiti referansla + refProp: Bir mülkü referansla + addConstant: Sabit ekle +_menuDisplay: + sideIcon: Yan (Simgeler) + sideFull: Yan + hide: Gizle + top: Üst +_filters: + fromUser: Kullanıcıdan + withFile: Dosya ile + notesBefore: Gönderiden önce + notesAfter: Gönderiden sonra + followingOnly: Sadece takip ettiklerim + fromDomain: Alan adı ile + followersOnly: Sadece takipçiler +_permissions: + "write:blocks": Engelli kullanıcıları düzenle + "read:drive": Drive dosya ve klasörlerine eriş + "read:favorites": Yer imlerini görüntüle + "write:mutes": Susturulmuş kullanıcıları düzenle + "read:notifications": Bildirimleri görüntüle + "write:notifications": Bildirimleri düzenle + "write:page-likes": Sayfalardaki beğenilerini düzenle + "read:user-groups": Kullanıcı gruplarını göster + "write:reactions": Tepkilerini düzenle + "read:pages": Sayfalarını göster + "write:channels": Kanallarını düzenle + "read:gallery": Galerini göster + "read:gallery-likes": Beğenilen galeri gönderilerini göster + "write:gallery-likes": Galeri gönderilerini düzenle + "write:messaging": Sohbet mesajı oluştur veya sil + "write:user-groups": Kullanıcı gruplarını düzenle veya sil + "read:messaging": Sohbetlerini görüntüle + "read:mutes": Susturulmuş kullanıcıları göster + "write:votes": Bir ankete oy ver + "read:page-likes": Beğenilen sayfalarını göster + "read:reactions": Tepkilerini göster + "read:channels": Kanallarını göster + "write:notes": Gönderi oluştur veya sil + "write:drive": Drive dosya ve klasörlerini düzenle + "write:favorites": Yer imlerini düzenle + "read:following": Kimleri takip ettiğini göster + "write:account": Hesap bilgisini düzenle + "read:account": Hesap bilgisini görüntüle + "read:blocks": Engelli kullanıcıları gör + "write:following": Hesapları takip et veya takipten çıkar + "write:pages": Sayfalarını düzenle veya sil + "write:gallery": Galerini düzenle +_auth: + pleaseGoBack: Lütfen uygulamaya geri dönün + callback: Uygulamaya geri dönülüyor + shareAccess: '"{name}" adlı kişinin bu hesaba erişmesine izin vermek ister misiniz?' + permissionAsk: 'Bu uygulama aşağıdaki izinleri ister:' + allPermissions: Tam hesap erişimi + denied: Erişim reddedildi + copyAsk: 'Lütfen aşağıdaki yetkilendirme kodunu uygulamaya yapıştırın:' + shareAccessAsk: Bu uygulamanın hesabınıza erişmesine izin vermek istediğinizden + emin misiniz? +_antennaSources: + users: Belirli kullanıcılardan gönderiler + homeTimeline: Takip edilen kullanıcılardan gönderiler + all: Tüm gönderiler + instances: Bir sunucudaki tüm kullanıcılardan gelen gönderiler + userList: Belirli bir kullanıcı listesinden gönderiler + userGroup: Belirli bir gruptaki kullanıcıların gönderileri +_charts: + usersIncDec: Kullanıcı sayısı farkı + usersTotal: Toplam kullanıcı sayısı + remoteNotesIncDec: Uzak gönderilerin sayısındaki fark + notesTotal: Toplam gönderi sayısı + filesTotal: Toplam dosya sayısı + apRequest: İstekler + storageUsageIncDec: Depolama kullanımındaki fark + localNotesIncDec: Yerel gönderilerin sayısındaki fark + storageUsageTotal: Toplam depolama kullanımı + federation: Federasyon + notesIncDec: Gönderi sayısındaki fark + activeUsers: Aktif kullanıcılar + filesIncDec: Dosya sayısındaki fark +_pages: + fontSerif: Serif + fontSansSerif: Sans Serif + chooseBlock: Bloğu sil + blocks: + _canvas: + id: Tuval ID + height: Yükseklik + width: Genişlik + _button: + _action: + resetRandom: Rastgele çekirdeği sıfırla + _pushEvent: + no-variable: Hiçbiri + event: Etkinlik ismi + message: Aktif olduğunda gösterilecek mesaj + variable: Gönderilecek değişken + callAiScript: AiScript'i çağırın + _callAiScript: + functionName: Fonksiyon ismi + dialog: Dialog göster + _dialog: + content: İçerik + pushEvent: Etkinlik gönder + text: Başlık + action: Düğmeye basıldığında olacaklar + colored: Renkli + text: Yazı + if: Eğer + _if: + variable: Değişken + canvas: Tuval + note: Gömülü yazı + _note: + id: Gönderi ID + idDescription: Alternatif olarak gönderi URL'sini buraya yapıştırabilirsiniz. + detailed: Detaylı görüntüleme + _counter: + text: Başlık + inc: Adım + name: Değer ismi + radioButton: Seçenek + _radioButton: + name: Değişken ismi + values: Seçenekleri satırlarla ayırın + title: Başlık + default: Varsayılan değer + _post: + text: İçerik + attachCanvasImage: Tuval resmi ekle + canvasId: Tuval ID + _textInput: + text: Başlık + name: Değişken ismi + default: Varsayılan değer + _numberInput: + name: Değiken ismi + text: Başlık + default: Varsayılan değer + _textareaInput: + text: Başlık + name: Değişken ismi + default: Varsayılan değer + textarea: Yazı alanı + _switch: + name: Değişken ismi + default: Varsayılan değer + text: Başlık + counter: Sayaç + switch: Değiştir + post: Gönderi formu + image: Resimler + section: Bölüm + textareaInput: Çok satırlı yazı girişi + button: Düğme + textInput: Yazı girişi + numberInput: Sayısal giriş + script: + categories: + text: Yazı işlemleri + flow: Akış kontrolü + random: Rastgele + fn: Fonksiyonlar + convert: Dönüşümler + list: Listeler + logical: Mantıksal işlem + operation: Hesaplama + comparison: Karşılaştırma + value: Değerler + blocks: + and: A ve B + _or: + arg2: B + arg1: A + _lt: + arg1: A + arg2: B + _ltEq: + arg1: A + arg2: B + textList: Yazı listesi + strReverse: Yazıyı çevir + multiply: Çarp + subtract: Çıkar + _mod: + arg1: A + arg2: B + _divide: + arg2: B + arg1: A + round: Ondalık yuvarlama + _round: + arg1: Sayı + _eq: + arg1: A + arg2: B + notEq: A ve B farklıysa + _notEq: + arg1: A + arg2: B + or: A veya B + gt: "> A, B'den çoksa" + ltEq: <= A, B'den az veya eşitse + gtEq: ">= A, B'den çok veya eşitse" + _gtEq: + arg1: A + arg2: B + _not: + arg1: OLUMSUZ + random: Rastgele + randomPick: Listeden rastgele seç + seedRandom: Random (çekirdek ile) + _for: + arg1: Tekrarlama sayısı + arg2: Eylem + _seedRannum: + arg3: Maksimum değer + arg2: Minimum değer + arg1: Çekirdek + _strReplace: + arg3: ile değiştir + arg2: Değiştirilecek yazı + arg1: Yazı + _subtract: + arg2: B + arg1: A + mod: Kalan + _and: + arg1: A + arg2: B + _DRPWPM: + arg1: Yazı listesi + _fn: + slots-info: Her yuvayı bir satır sonu ile ayırın + arg1: Çıkış + slots: Yuvalar + for: dögü + dailyRandomPick: Listeden rastgele seçim yapın (Her kullanıcı için günde bir + kez değişir) + _dailyRannum: + arg1: Minimum değer + arg2: Maksimum değer + _seedRandomPick: + arg2: Liste + arg1: Çekirdek + _pick: + arg2: Pozisyon + arg1: Liste + number: Sayı + _if: + arg3: Yoksa + arg1: Eğer + arg2: Sonra + _rannum: + arg1: Minimum değer + arg2: Maksimum değer + eq: A ve B eşitse + _gt: + arg1: A + arg2: B + rannum: Rastgele sayı + _randomPick: + arg1: Liste + pick: Listeden seç + _listLen: + arg1: Liste + _multiply: + arg2: B + arg1: A + divide: Böl + strPick: Dize ayıklayın + _strPick: + arg1: Yazı + arg2: Dize konunumu + dailyRandom: Rastgele (Her kullanıcı için günde bir kez değişir) + _dailyRandom: + arg1: Olasılık + dailyRannum: Rastgele sayı (Her kullanıcı için günde bir kez değişir) + _stringToNumber: + arg1: Yazı + if: Şube + strReplace: Yedek dize + text: Yazı + _splitStrByLine: + arg1: Yazı + not: OLUMSUZ + _seedRandom: + arg1: Çekirdek + arg2: Olasılık + seedRandomPick: Listeden rastgele seçim yapın (çekirdek ile) + fn: Fonksiyon + multiLineText: Yazı (çok satırlı) + _textList: + info: Her girişi satırlar ile ayırın + _strReverse: + arg1: Yazı + join: Yazıyı birleştirme + _join: + arg1: Listeler + arg2: Ayraç + add: Ekle + _add: + arg1: A + arg2: B + _strLen: + arg1: Yazu + aiScriptVar: AiScript Değişkeni + ref: Değişken + splitStrByLine: Yazıyı satır sonlarına göre bölme + strLen: Yazı uzunluğu + lt: < A, B'den azsa + _random: + arg1: Olasılık + DRPWPM: Ağırlıklı listeden rastgele seçim yapın (Her kullanıcı için günde bir + kez değişir) + listLen: Listenin uzunluğunu al + numberToString: Sayıdan yazıya + _dailyRandomPick: + arg1: Liste + stringToNumber: Yazıdan Sayıya + seedRannum: Rastgele sayı (çekirdek ile) + _numberToString: + arg1: Sayı + types: + number: Sayı + boolean: Etiket + array: Liste + stringArray: Yazı listesi + string: Yazı + emptySlot: Boş yuva + enviromentVariables: Ortam değikenleri + argVariables: Giriş yuvaları + thereIsEmptySlot: Yuva {slot} boş! + typeError: Yuva {slot}, "{expect}" türündeki değerleri kabul eder, ancak sağlanan + değer "{actual}" türündedir! + pageVariables: Sayfa değişkenleri + readPage: Bu sayfanın kaynağını görüntüle + created: Sayfa başarıyla oluşturuldu + eyeCatchingImageRemove: Afişi sil + selectType: Tip seç + pageSetting: Sayfa ayarları + viewSource: Kaynağı görüntüle + variables: Değişkenler + url: Sayfa URL'si + unlike: Beğeniyi kaldır + my: Sayfalarım + content: Sayfa bloğu + deleted: Sayfa başarıyla silindi + newPage: Yeni sayfa oluştur + editPage: Bu sayfayı düzenle + viewPage: Sayfalarını görüntüle + like: Beğen + nameAlreadyExists: Belirtilen Sayfa URL'si zaten var + invalidNameTitle: Belirtilen Sayfa URL'si geçersiz + invalidNameText: Sayfa başlığının boş olmadığından emin olun + editThisPage: Sayfayı düzenle + featured: Popüler + inspector: Denetçi + contents: İçerik + title: Başlık + liked: Beğenilen Sayfalar + font: Yazı Tipi + alignCenter: İçerikleri ortala + eyeCatchingImageSet: Afiş ayarla + enterVariableName: Değişken ismi ekle + hideTitleWhenPinned: Profile sabitlendiğinde Sayfa başlığını gizle + variableNameIsAlreadyUsed: Bu değişken adı zaten kullanımda + contentBlocks: İçerik + inputBlocks: Giriş + specialBlocks: Özel + updated: Sayfa başarıyla düzenlendi + summary: Sayfa özeti +_notification: + _types: + follow: Yeni takipçiler + mention: Bahsetmeler + app: Bağlı uygulamalardan bildirimler + pollEnded: Biten anket + receiveFollowRequest: Takip istekleri alındı + reaction: Tepkiler + all: Hepsi + followRequestAccepted: Takip istekleri kabul edildi + pollVote: Anket oylamaları + renote: Yükseltmeler + reply: Yanıtlar + groupInvited: Grup davetleri + quote: Alıntılar + pollEnded: Anket sonuçları açıklandı + fileUploaded: Dosya başarıyla yüklendi + youRenoted: '{name} tarafından yükseltildin' + _actions: + followBack: Seni geri takip etti + reply: Yanıtla + renote: Yükseltmeler + youGotMention: '{name} senden bahsetti' + youWereFollowed: seni takip etti + youGotMessagingMessageFromGroup: '{name} grubuna bir sohbet mesajı gönderildi' + renoted: gönderini yükseltti + youGotQuote: '{name} seni alıntıladı' + youGotReply: '{name} seni yanıtladı' + reacted: gönderine tepki ekledi + yourFollowRequestAccepted: Takip isteğin kabul edildi + emptyPushNotificationMessage: Push bildirimleri güncellendi + youWereInvitedToGroup: '{userName} seni gruba davet etti' + voted: anketine oy verdi + youReceivedFollowRequest: Bir takip isteği geldi + youGotPoll: '{name} anketinde oylama yaptı' + youGotMessagingMessageFromUser: '{name} sana bir sohbet mesajı gönderdi' +_experiments: + title: Deneyler + postImportsCaption: Kullanıcıların geçmiş Calckey, Misskey, Mastodon, Akkoma ve + Pleroma hesaplarından gönderilerini içe aktarmalarına izin verir. Kuyruğunuz tıkanırsa + yükleme sırasında yavaşlamalara neden olabilir. + enablePostImports: Gönderi içeri aktarmasını aktif et +_dialog: + charactersExceeded: 'Maksimum karakter aşıldı! Geçerli: {current}/Sınır: {max}' + charactersBelow: 'Yeterli karakter yok! Geçerli: {current}/Sınır: {min}' +_signup: + emailSent: Mail adresinize ({email}) bir onay maili gönderildi. Hesap oluşturmayı + tamamlamak için lütfen verilen bağlantıya tıklayın. + almostThere: Neredeyse vardık + emailAddressInfo: Lütfen mail adresinizi giriniz. Herkese açık gözükmeyecektir. +_ad: + back: Geri + reduceFrequencyOfThisAd: Daha az reklam göster +_accountDelete: + accountDelete: Hesabı sil + mayTakeTime: Hesap silme, kaynak yoğun bir işlem olduğundan, ne kadar içerik oluşturduğunuza + ve ne kadar dosya yüklediğinize bağlı olarak tamamlanması biraz zaman alabilir. + sendEmail: Hesap silme işlemi tamamlandıktan sonra, bu hesapta kayıtlı olan mail + adresine bir mail gönderilecektir. + started: Silme işlemi başlatıldı. + requestAccountDelete: Hesap silme talebinde bulun + inProgress: Silme işlemi şu anda devam ediyor +_forgotPassword: + enterEmail: Kaydolmak için kullandığınız mail adresini girin. Parolanızı sıfırlayabileceğiniz + bir bağlantı daha sonra ona gönderilecektir. + contactAdmin: Bu sunucu, mail adreslerinin kullanılmasını desteklemiyor, bunun yerine + şifrenizi sıfırlamak için lütfen sunucu yöneticisiyle iletişime geçin. + ifNoEmail: Kayıt sırasında bir mail kullanmadıysanız, sunucu yöneticisiyle iletişime + geçin. +_gallery: + my: Galerim + liked: Beğenilen Gönderiler + like: Beğen + unlike: Beğeniyi kaldır +_registry: + key: Anahtar + scope: Kapsam + keys: Anahtarlar + createKey: Anahtar oluştur + domain: Alan adı +_email: + _follow: + title: Yeni bir takipçin var + _receiveFollowRequest: + title: Yeni bir takip isteğin var +_preferencesBackups: + apply: Bu cihaza uygula + invalidFile: Geçersiz dosya formatı + applyConfirm: '"{name}" yedeğini bu cihaza gerçekten uygulamak istiyor musunuz? + Bu cihazın mevcut ayarlarının üzerine yazılacak.' + inputName: Lütfen bu yedekleme için bir ad girin + cannotSave: Kaydedilemedi + saveConfirm: Yedekleme {name} olarak kaydedilsin mi? + renameConfirm: '"{old}" olan bu yedeğin adı "{new}" olarak değiştirilsin mi?' + createdAt: 'Oluşturma tarihi: {date} {time}' + save: Değişiklikleri Kaydet + nameAlreadyExists: '"{name}" adlı bir yedek zaten var. Lütfen farklı bir ad girin.' + deleteConfirm: '{name} yedeği silinsin mi?' + noBackups: Yedekleme yok. "Yeni yedekleme oluştur" seçeneğini kullanarak bu sunucudaki + istemci ayarlarınızı yedekleyebilirsiniz. + list: Oluşturulan yedekler + saveNew: Yeni bir yedek oluştur + loadFile: Dosyadan yükle + updatedAt: 'Güncelleme tarihi: {date} {time}' + cannotLoad: Yüklenemedi +_aboutMisskey: + patronsList: Bağış büyüklüğüne göre değil, kronolojik olarak listelenmiştir. Adınızı + buraya almak için yukarıdaki bağlantıyla bağış yapın! + about: Calckey, 2022'den beri geliştirilmekte olan ThatOneCalculator tarafından + yapılan bir Misskey çatalıdır. + allContributors: Tüm katkıda bulunanlar + patrons: Calckey patronları + morePatrons: Burada listelenmeyen diğer birçok yardımcının desteğini de takdir ediyoruz. + Teşekkür ederim! 🥰 + donate: Calckey'e bağışta bulunun + contributors: Ana katkıda bulunanlar + source: Kaynak Kodu + translation: Calckey'i tercüme et + donateTitle: Calckey'den hoşlanıyor musunuz? + pleaseDonateToCalckey: Lütfen gelişimini desteklemek için Calckey'e bağış yapmayı + düşünün. + pleaseDonateToHost: İşletme maliyetlerini desteklemek için lütfen ev sunucunuz {host}'a + bağış yapmayı da düşünün. + donateHost: '{ev sahibi} için bağış yapın' + sponsors: Calckey sponsorları +_weekday: + saturday: Cumartesi + sunday: Pazar + wednesday: Çarşamba + friday: Cuma + thursday: Perşembe + monday: Pazartesi + tuesday: Salı +_serverDisconnectedBehavior: + reload: Otomatik olarak yenile + quiet: Göze çarpmayan uyarı göster + nothing: Hiçbir şey yapma + dialog: Uyarı mesajını göster +_channel: + removeBanner: Afişi sil + owned: Sahip Olunan + nameOnly: Sadece isim + featured: Popüler + setBanner: Afiş ayarla + usersCount: '{n} Katılımcı' + create: Kanal oluştur + following: Takip + notesCount: '{n} Gönderi' + nameAndDescription: İsim ve açıklama + edit: Kanalı düzenle +_messaging: + groups: Gruplar + dms: Özel +_tutorial: + step5_5: Sosyal {icon} zaman çizelgesi, Ev ve Yerel zaman çizelgelerinin bir kombinasyonudur. + step5_6: Önerilen {icon} zaman çizelgesi, yöneticilerin önerdiği sunuculardan gelen + gönderileri görebileceğiniz yerdir. + step6_1: Peki burası neresi? + title: Calckey nasıl kullanılır + step3_2: "Ev ve sosyal zaman çizelgeleriniz, kimi takip ettiğinize bağlıdır, bu + nedenle başlamak için birkaç hesabı takip etmeyi deneyin.\nTakip etmek için bir + profilin sağ üstündeki artı dairesine tıklayın." + step5_3: Ana Sayfa {icon} zaman çizelgesi, takip ettiğiniz hesaplardan gelen gönderileri + görebileceğiniz yerdir. + step5_4: Yerel {icon} zaman çizelgesi, bu sunucudaki diğer herkesin gönderilerini + görebileceğiniz yerdir. + step6_2: Calckey'e öylece katılmadın. Binlerce sunucudan oluşan birbirine bağlı + bir ağ olan Fediverse'e giden bir portala katıldınız. + step6_4: Şimdi gidin, keşfedin ve eğlenin! + step5_7: Global {icon} zaman çizelgesi, bağlı diğer tüm sunuculardan gelen gönderileri + görebileceğiniz yerdir. + step2_1: Öncelikle lütfen profilinizi doldurunuz. + step2_2: Kim olduğunuz hakkında biraz bilgi vermeniz, başkalarının gönderilerinizi + görmek mi yoksa sizi takip etmek mi istediklerini anlamalarını kolaylaştıracaktır. + step3_1: Şimdi birkaç kullanıcı takip etme zamanı! + step1_1: Hoşgeldin! + step1_2: Hadi seni hazırlayalım. Kısa sürede kullanmaya başlayacaksınız! + step5_1: Zaman çizelgeleri, her yerde zaman çizelgeleri! + step6_3: Her sunucu farklı şekillerde çalışır ve tüm sunucular Calckey'i çalıştırmaz. + Ama bu sunucu kullanıyor! Biraz karışık ama kısa sürede anlayacaksın. + step4_1: Seni oradan çıkaralım. + step5_2: Sunucunuzda etkinleştirilmiş {timelines} farklı zaman çizelgesi var. + step4_2: İlk gönderiniz için, bazı insanlar bir {introduction} gönderisi veya basit + bir "Merhaba dünya!" gönderir +_visibility: + public: Herkese açık + publicDescription: Gönderiniz herkese açık tüm zaman çizelgelerinde görünür olacak + specified: Direkt + followersDescription: Yalnızca takipçilerinize ve adı geçen kullanıcılara görünür + kılın + localOnlyDescription: Uzak kullanıcılara gözükmez + home: Listelenmemiş + homeDescription: Yalnızca ev zaman çizelgesine yayınla + followers: Takipçiler + specifiedDescription: Belirli kullanıcılara özel yapın + localOnly: Sadece yerel +_postForm: + quotePlaceholder: Bu gönderiyi alıntıla... + _placeholders: + a: Ne ile meşgulsün? + b: Etrafında neler oluyor? + f: Yazman bekleniyor... + c: Aklınızdan ne geçiyor? + d: Ne demek istiyorsun? + e: Yazmaya başka... + replyPlaceholder: Bu gönderiyi yanıtla... + channelPlaceholder: Bir kanala gönder... +_exportOrImport: + allNotes: Tüm gönderiler + followingList: Takip edilen kullanıcılar + muteList: Susturulmuş kullanıcılar + excludeMutingUsers: Susturulmuş kullanıcıları hariç tut + excludeInactiveUsers: Aktif olmayan kullanıcıları hariç tut + userLists: Kullanıcı listeleri + blockingList: Engellenimş kullanıcılar +_instanceCharts: + notes: Gönderi sayısındaki fark + notesTotal: Toplu gönderi sayısı + files: Dosya sayısındaki fark + filesTotal: Toplu dosya sayısı + requests: İstekler + usersTotal: Toplu kullanıcı sayısı + users: Kullanıcı sayısı farkı + cacheSize: Önbellek boyutundaki fark + ff: 'Takip edilen / Takipçi sayısındaki fark ' + cacheSizeTotal: Toplam önbellek boyutu + ffTotal: Toplu Takip edilen / Takipçi sayısı +_wordMute: + soft: Yumuşak + muteWords: Susturulmuş kelimeler + muteWordsDescription: AND koşulu için boşluklarla veya OR koşulu için satır sonlarıyla + ayırın. + softDescription: Belirlenen koşulları karşılayan gönderileri zaman çizelgesinden + gizleyin. + hardDescription: Belirlenen koşulları sağlayan gönderilerin zaman çizelgesineeklenmesini + engeller. Ayrıca bu gönderiler, koşullar değişse dahi zaman tüneline eklenmeyecektir. + mutedNotes: Susturulmuş gönderiler + hard: Sert + muteWordsDescription2: Normal ifadeleri kullanmak için anahtar kelimeleri eğik çizgilerle + çevreleyin. +_ago: + weeksAgo: '{n}hafta önce' + minutesAgo: '{n}dakika önce' + daysAgo: '{n}gün önce' + future: Gelecek + justNow: Şimdi + secondsAgo: '{n}saniye önce' + hoursAgo: '{n}saat önce' + monthsAgo: '{n}ay önce' + yearsAgo: '{n}yıl önce' +_timelines: + home: Ev + local: Yerel + social: Sosyal + global: Global + recommended: Tavsiye Edilen +_nsfw: + respect: NSFW medyasını gizle + force: Tüm medyayı gizle + ignore: NSFW medyasını gizleme +_cw: + files: '{count} dosya(lar)' + chars: '{count} harf' + hide: Gizle + show: İçeriği göster +_relayStatus: + rejected: Reddedildi + accepted: Kabul edildi + requesting: Bekleniyor +_time: + day: Gün(ler) + hour: Saat(ler) + second: Saniye(ler) + minute: Dakika(lar) +_skinTones: + light: Aydınlık + medium: Orta + mediumLight: Orta Aydınlık + dark: Karanlık + yellow: Sarı + mediumDark: Orta Karanlık +_plugin: + install: Eklenti indir + installWarn: Lütfen güvenli olmayan eklentiler kurmayınız. + manage: Eklentileri yönet +_instanceTicker: + remote: Uzak kullanıcılar için göster + always: Her zaman göster + none: Asla gösterme +_instanceMute: + heading: Sessize alınacak sunucuların listesi + instanceMuteDescription2: Yeni satırlarla ayırın + title: Listelenen sunuculardan gönderileri gizler. + instanceMuteDescription: Bu, sessize alınmış bir sunucudan bir kullanıcıya yanıt + veren kullanıcılarınkiler de dahil olmak üzere, listelenen sunuculardan gelen + tüm gönderileri/yükseltmeleri sessize alacaktır. +_ffVisibility: + followers: Takipçilere açık + private: Gizli + public: Herkese açık From 911745583270043d3f47ce86e231443e15956394 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sat, 15 Jul 2023 15:21:33 -0400 Subject: [PATCH 143/162] fix: note detailed tabs using wrong styling --- packages/client/src/components/MkNoteDetailed.vue | 1 - packages/client/src/components/MkTab.vue | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue index 3dfac1f0c..71c11350d 100644 --- a/packages/client/src/components/MkNoteDetailed.vue +++ b/packages/client/src/components/MkNoteDetailed.vue @@ -35,7 +35,6 @@ <MkTab v-model="tab" - style="white-space: nowrap" :style="'underline'" @update:modelValue="loadTab" > diff --git a/packages/client/src/components/MkTab.vue b/packages/client/src/components/MkTab.vue index a5bc28260..b5d6e8056 100644 --- a/packages/client/src/components/MkTab.vue +++ b/packages/client/src/components/MkTab.vue @@ -58,6 +58,7 @@ export default defineComponent({ font-size: 90%; border-radius: var(--radius); padding: 10px 8px; + white-space: nowrap; > button { flex: 1; From d64a72c806c8a118ecd08286e9a97b0ef0a7dc3a Mon Sep 17 00:00:00 2001 From: Cold Ravioli <diegoxe7117@gmail.com> Date: Sat, 15 Jul 2023 14:23:49 +0000 Subject: [PATCH 144/162] chore: Translated using Weblate (Spanish) Currently translated at 86.9% (1592 of 1831 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/es/ --- locales/es-ES.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 0bd874f33..faf9ba282 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -642,7 +642,7 @@ wordMute: "Silenciar palabras" regexpError: "Error de la expresión regular" regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}" -instanceMute: "Instancias silenciadas" +instanceMute: "Servidores silenciados" userSaysSomething: "{name} dijo algo" makeActive: "Activar" display: "Apariencia" @@ -671,14 +671,14 @@ sample: "Muestra" abuseReports: "Reportes" reportAbuse: "Reportar" reportAbuseOf: "Reportar a {name}" -fillAbuseReportDescription: "Ingrese los detalles del reporte. Si hay una nota en - particular, ingrese la URL de esta." +fillAbuseReportDescription: "Ingrese los detalles del reporte. Si hay una publicación + en particular, ingrese la URL de esta." abuseReported: "Se ha enviado el reporte. Muchas gracias." reporter: "Reportador" reporteeOrigin: "Reportar a" reporterOrigin: "Origen del reporte" -forwardReport: "Transferir un informe a una instancia remota" -forwardReportIsAnonymous: "No puede ver su información de la instancia remota y aparecerá +forwardReport: "Transferir reporte a un servidor remoto" +forwardReportIsAnonymous: "No puede ver su información del servidor remoto y aparecerá como una cuenta anónima del sistema" send: "Enviar" abuseMarkAsResolved: "Marcar reporte como resuelto" @@ -686,7 +686,7 @@ openInNewTab: "Abrir en una Nueva Pestaña" openInSideView: "Abrir en una vista al costado" defaultNavigationBehaviour: "Navegación por defecto" editTheseSettingsMayBreakAccount: "Editar estas configuraciones puede dañar su cuenta." -instanceTicker: "Información de notas de la instancia" +instanceTicker: "Información de publicaciones de el servidor" waitingFor: "Esperando a {x}" random: "Aleatorio" system: "Sistema" @@ -697,14 +697,14 @@ createNew: "Crear" optional: "Opcional" createNewClip: "Crear clip nuevo" unclip: "Quitar clip" -confirmToUnclipAlreadyClippedNote: "Esta nota ya está incluida en el clip \"{name}\"\ - . ¿Quiere quitar la nota del clip?" +confirmToUnclipAlreadyClippedNote: "Esta publicación ya está incluida en el clip \"\ + {name}\". ¿Quiere quitar la nota del clip?" public: "Público" i18nInfo: "Calckey está siendo traducido a varios idiomas gracias a voluntarios. Se puede colaborar traduciendo en {link}" manageAccessTokens: "Administrar tokens de acceso" accountInfo: "Información de la Cuenta" -notesCount: "Cantidad de notas" +notesCount: "Cantidad de publicaciones" repliesCount: "Cantidad de respuestas hechas" renotesCount: "Cantidad de renotas hechas" repliedCount: "Cantidad de respuestas recibidas" @@ -720,7 +720,7 @@ no: "No" driveFilesCount: "Cantidad de archivos en el drive" driveUsage: "Uso del drive" noCrawle: "Rechazar indexación del crawler" -noCrawleDescription: "Pedir a los motores de búsqueda que no indexen tu perfil, notas, +noCrawleDescription: "Pedir a los motores de búsqueda que no indexen tu perfil, publicaciones, páginas, etc." lockedAccountInfo: "A menos que configures la visibilidad de tus notas como \"Sólo seguidores\", tus notas serán visibles para cualquiera, incluso si requieres que @@ -734,7 +734,7 @@ verificationEmailSent: "Se le ha enviado un correo electrónico de confirmación configuración." notSet: "Sin especificar" emailVerified: "Su dirección de correo electrónico ha sido verificada." -noteFavoritesCount: "Número de notas favoritas" +noteFavoritesCount: "Número de publicaciones favoritas" pageLikesCount: "Número de favoritos en la página" pageLikedCount: "Número de favoritos de su página" contact: "Contacto" @@ -975,7 +975,7 @@ shuffle: "Aleatorio" account: "Cuentas" move: "Mover" _sensitiveMediaDetection: - description: "Reduce el esfuerzo de la moderación el el servidor a través del reconocimiento + description: "Reduce el esfuerzo de la moderación de el servidor a través del reconocimiento automático de contenido NSFW usando 'Machine Learning'. Esto puede incrementar ligeramente la carga en el servidor." sensitivity: "Sensibilidad de detección" @@ -1295,7 +1295,7 @@ _time: _tutorial: title: "Cómo usar Calckey" step1_1: "¡Bienvenido!" - step1_2: "Vamos a configurarte. Estarás listo y funcionando en poco tiempo" + step1_2: "Vamos a configurarte. ¡Estarás listo y funcionando en poco tiempo!" step2_1: "En primer lugar, rellena tu perfil" step2_2: "Proporcionar algo de información sobre quién eres hará que sea más fácil para los demás saber si quieren ver tus notas o seguirte." @@ -1789,7 +1789,7 @@ _pages: splitStrByLine: "Separar texto en lineas" _splitStrByLine: arg1: "Texto" - ref: "Variables" + ref: "Variable" aiScriptVar: "Variable de AiScript" fn: "funciones" _fn: @@ -1800,8 +1800,8 @@ _pages: _for: arg1: "Cantidad de repeticiones" arg2: "Acción" - typeError: "El slot {slot} acepta el tipo {expect} pero fue ingresado el tipo - {actual}" + typeError: "El slot {slot} acepta el tipo \"{expect}\" pero fue ingresado el tipo + \"{actual}\"" thereIsEmptySlot: "El slot {slot} está vacío" types: string: "Texto" From 0978a210cb90cfe01e92afdf1fcb8fe2ec905ebc Mon Sep 17 00:00:00 2001 From: Rauf <raufsen11@gmail.com> Date: Sat, 15 Jul 2023 08:10:17 +0000 Subject: [PATCH 145/162] chore: Translated using Weblate (Turkish) Currently translated at 100.0% (1831 of 1831 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/tr/ --- locales/tr-TR.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index 8c3c15f33..a3021221d 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -660,7 +660,7 @@ driveCapacityPerLocalAccount: Kullanıcı başı Driver kapasitesi driveCapacityPerRemoteAccount: Uzak kullanıcı başı Driver kapasitesi inMb: Megabayt cinsinden pinnedClipId: Sabitlenecek atacın ID'si -withFiles: Dosyaları içer +withFiles: Dosya içeren recentlyRegisteredUsers: Yeni katılmış kullanıcılar recentlyDiscoveredUsers: Yeni keşfedilmiş kullanıcılar nUsersMentioned: '{n} kullanıcı tarafından bahsedildi' @@ -1237,7 +1237,7 @@ objectStorageRegion: Region invisibleNote: Gizli Gönderi deletedNote: Silinmiş Gönderi visibility: Görünürlük -poll: Oylama +poll: Anket themeEditor: Tema düzenleyicisi enterFileDescription: Başlık gir description: Açıklama From 21e8f5bf234b6394ce19514c1f0c86f8e80a0040 Mon Sep 17 00:00:00 2001 From: Xalis Ratt <xalisratt@linux.pl> Date: Sat, 15 Jul 2023 17:32:11 +0000 Subject: [PATCH 146/162] chore: Translated using Weblate (Ukrainian) Currently translated at 100.0% (1831 of 1831 strings) Translation: Calckey/locales Translate-URL: https://hosted.weblate.org/projects/calckey/locales/uk/ --- locales/uk-UA.yml | 688 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 598 insertions(+), 90 deletions(-) diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 4df6dd212..78aaf2bbd 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -153,10 +153,11 @@ flagAsBotDescription: "Ввімкніть якщо цей обліковий з Ця опція позначить обліковий запис як бота. Це потрібно щоб виключити безкінечну інтеракцію між ботами а також відповідного підлаштування Calckey." flagAsCat: "Акаунт кота" -flagAsCatDescription: "Ввімкніть, щоб позначити, що обліковий запис є котиком." +flagAsCatDescription: "Ввімкніть, щоб позначити, що обліковий запис є котиком, та + отримати котячі вуха!" flagShowTimelineReplies: "Показувати відповіді на нотатки на часовій шкалі" -flagShowTimelineRepliesDescription: "Показує відповіді користувачів на нотатки інших - користувачів на часовій шкалі." +flagShowTimelineRepliesDescription: "Показує відповіді користувачів на записи інших + користувачів у стрічці." autoAcceptFollowed: "Автоматично приймати запити на підписку від користувачів, на яких ви підписані" addAccount: "Додати акаунт" @@ -169,7 +170,7 @@ removeWallpaper: "Прибрати шпалери" searchWith: "Пошук: {q}" youHaveNoLists: "У вас немає списків" followConfirm: "Підписатися на {name}?" -proxyAccount: "Проксі-акаунт" +proxyAccount: "Обліковий запис проксі" proxyAccountDescription: "Обліковий запис проксі – це обліковий запис, який діє як віддалений підписник для користувачів за певних умов. Наприклад, коли користувач додає віддаленого користувача до списку, активність віддаленого користувача не буде @@ -217,7 +218,7 @@ blockedUsers: "Заблоковані користувачі" noUsers: "Немає користувачів" editProfile: "Редагувати обліковий запис" noteDeleteConfirm: "Ви дійсно хочете видалити цей запис?" -pinLimitExceeded: "Більше записів не можна закріпити" +pinLimitExceeded: "Ви не можете закріпити більше записів" intro: "Встановлення Calckey завершено! Будь ласка, створіть обліковий запис адміністратора." done: "Готово" processing: "Обробка" @@ -232,7 +233,7 @@ all: "Всі" subscribing: "Підписка" publishing: "Публікація" notResponding: "Не відповідає" -instanceFollowing: "Підписка на інстанс" +instanceFollowing: "Підписка на сервер" instanceFollowers: "Підписники серверу" instanceUsers: "Користувачі цього серверу" changePassword: "Змінити пароль" @@ -359,7 +360,7 @@ pinnedUsersDescription: "Впишіть в список користувачів \"Знайти\", ім'я в стовпчик." pinnedPages: "Закріплені сторінки" pinnedPagesDescription: "Введіть шляхи сторінок, які ви бажаєте закріпити на головній - сторінці цього інстанса, розділені новими рядками." + сторінці цього сервера, розділені новими рядками." pinnedClipId: "Ідентифікатор закріпленої замітки" pinnedNotes: "Закріплений запис" hcaptcha: "hCaptcha" @@ -506,12 +507,14 @@ promote: "Виділити" numberOfDays: "Кількість днів" hideThisNote: "Сховати цей запис" showFeaturedNotesInTimeline: "Показувати популярні записи у стрічці" -objectStorage: "Object Storage" +objectStorage: "Сховище" useObjectStorage: "Використовувати object storage" -objectStorageBaseUrl: "Base URL" -objectStorageBaseUrlDesc: "Це початкова частина адреси, що використовується CDN або - проксі, наприклад для S3: https://<bucket>.s3.amazonaws.com, або GCS: 'https://storage.googleapis.com/<bucket>'" -objectStorageBucket: "Bucket" +objectStorageBaseUrl: "Базовий URL" +objectStorageBaseUrlDesc: "URL-адреса, що використовується як джерело. Вкажіть URL-адресу + вашого CDN або проксі-сервера, якщо ви їх використовуєте.\nДля S3 використовуйте + 'https://<bucket>.s3.amazonaws.com', а для GCS або подібних сервісів - 'https://storage.googleapis.com/<bucket>', + тощо." +objectStorageBucket: "Сховище (Bucket)" objectStorageBucketDesc: "Будь ласка вкажіть назву відра в налаштованому сервісі." objectStoragePrefix: "Prefix" objectStoragePrefixDesc: "Файли будуть зберігатись у розташуванні з цим префіксом." @@ -665,11 +668,11 @@ reportAbuse: "Поскаржитись" reportAbuseOf: "Поскаржитись на {name}" fillAbuseReportDescription: "Будь ласка вкажіть подробиці скарги. Якщо скарга стосується запису, вкажіть посилання на нього." -abuseReported: "Дякуємо, вашу скаргу було відправлено. " +abuseReported: "Дякуємо. Ваш звіт було відправлено." reporter: "Репортер" reporteeOrigin: "Про кого повідомлено" reporterOrigin: "Хто повідомив" -forwardReport: "Переслати звіт на віддалений інстанс" +forwardReport: "Переслати звіт на віддалений сервер" forwardReportIsAnonymous: "Замість вашого облікового запису, анонімний системний обліковий запис буде відображатися як доповідач на віддаленому сервері." send: "Відправити" @@ -679,16 +682,16 @@ openInSideView: "Відкрити збоку" defaultNavigationBehaviour: "Поведінка навігації за замовчуванням" editTheseSettingsMayBreakAccount: "Зміна цих параметрів може призвести до пошкодження вашого акаунта." -instanceTicker: "Мітка з назвою інстанса в нотатках" +instanceTicker: "Інформація про записи на сервері" waitingFor: "Чекаємо на {x}" random: "Випадковий" system: "Система" switchUi: "Інтерфейс" desktop: "Десктоп" -clip: "Добірка" +clip: "Підбірка" createNew: "Створити новий" optional: "Необов'язково" -createNewClip: "Створити нотатку" +createNewClip: "Створити підбірку" public: "Публічний" i18nInfo: "Calckey перекладається на різні мови волонтерами. Ви можете допомогти за посиланням: {link}." @@ -793,24 +796,33 @@ hide: "Сховати" searchByGoogle: "Пошук" indefinitely: "Ніколи" file: "Файли" -reverse: "Перевернути" +reverse: "Переворот" colored: "Кольоровий" label: "Назва" localOnly: "Локально" _ffVisibility: public: "Опублікувати" + private: Приватні + followers: Доступно тільки для підписників _ad: back: "Назад" + reduceFrequencyOfThisAd: Менше показувати цю рекламу _gallery: unlike: "Не вподобати" + liked: Вподобані записи + like: Подобається + my: Моя галерея _email: _follow: title: "Новий підписник" + _receiveFollowRequest: + title: Ви отримали запит на підписку _registry: key: "Ключ" keys: "Ключі" domain: "Домен" createKey: "Створити ключ" + scope: Область _aboutMisskey: about: "Misskey - це програмне забезпечення з відкритим кодом, яке розробляє syuilo з 2014 року." @@ -822,12 +834,20 @@ _aboutMisskey: morePatrons: "Ми дуже цінуємо підтримку багатьох інших помічників, не перелічених тут. Дякуємо! 🥰" patrons: "Підтримали" + patronsList: Перераховані в хронологічному порядку, а не за розміром пожертви. Зробіть + внесок за посиланням вище, щоб ваше ім'я було тут! + donateTitle: Сподобався Calckey? + pleaseDonateToCalckey: Будь ласка, підтримайте розробку Calckey. + pleaseDonateToHost: Також не забудьте підтримати ваш домашній сервер {host}, щоб + допомогти з його операційними витратами. + donateHost: Зробити внесок на рахунок {host} + sponsors: Спонсори Calckey _nsfw: respect: "Приховувати NSFW медіа" ignore: "Не приховувати NSFW медіа" force: "Приховувати всі медіа файли" _mfm: - cheatSheet: " Довідка MFM" + cheatSheet: "Довідка MFM" intro: "MFM це ексклюзивна мова розмітки тексту в Calckey, яку можна використовувати в багатьох місцях. Тут ви можете переглянути приклади її синтаксису." dummy: "Calckey розширює світ Федіверсу" @@ -839,35 +859,36 @@ _mfm: url: "URL" urlDescription: "Відображаються URL-адреси." link: "Посилання" - linkDescription: "Окремі частини тексту можуть містити посилання" + linkDescription: "Окремі частини тексту можуть містити посилання." bold: "Жирний шрифт" - boldDescription: "Виділяє літери, роблячи їх товще" + boldDescription: "Виділяє літери, роблячи їх товщими." small: "Дрібний шрифт" - smallDescription: "Робить текст маленьким і тонким" + smallDescription: "Робить текст маленьким і тонким." center: "По центру" - centerDescription: "Показує вміст у центрі" + centerDescription: "Показує вміст у центрі." inlineCode: "Код (у рядку)" - inlineCodeDescription: "Показує фрагмент тексту у рядку як програмний код" + inlineCodeDescription: "Відображає підсвічування синтаксису для коду (програми)." blockCode: "Код (блок)" - blockCodeDescription: "Показує кілька рядків тексту як блок програмного кода" + blockCodeDescription: "Відображає підсвічування синтаксису для багаторядкового (програмного) + коду в блоці." inlineMath: "Формула (у рядку)" inlineMathDescription: "Відображення математичних формул (KaTeX) у рядку" blockMath: "Формули (блок)" - blockMathDescription: "Відображати багаторядкові формули (KaTeX) блоками" + blockMathDescription: "Відображати математичні формули (KaTeX) блоками" quote: "Цитата" quoteDescription: "Відображає зміст як цитату." emoji: "Кастомні емоджі" emojiDescription: "Щоб показати нетиповий емоджі, потрібно ввести його назву в двокрапках." search: "Пошук" - searchDescription: "Відображає вікно пошуку з попередньо введеним текстом" + searchDescription: "Відображає вікно пошуку з попередньо введеним текстом." flip: "Перевернути" - flipDescription: "Віддзеркалює вміст по горизонталі або вертикалі" + flipDescription: "Віддзеркалює вміст по горизонталі або вертикалі." jelly: "Анімація (желе)" - jellyDescription: "Створює желеподібну анімацію" + jellyDescription: "Створює желеподібну анімацію." tada: "Анімація (Тада!)" - tadaDescription: "Створює анімацію з відчуттям \"Тада!\"" + tadaDescription: "Створює анімацію з відчуттям \"Тада!\"." jump: "Анімація (стрибки)" - jumpDescription: "Показує стрибаючу анімацію" + jumpDescription: "Надає вмісту стрибучу анімацію." bounce: "Анімація (пружина)" shake: "Анімація (Shake)" twitch: "Анімація (Twitch)" @@ -884,6 +905,36 @@ _mfm: font: "Шрифт" fontDescription: "Встановлює шрифт для контенту." rotate: "Обертати" + play: Відтворити MFM + alwaysPlay: Завжди автозапускати всі анімовані MFM + twitchDescription: Надає контенту анімацію, що сильно сіпається. + spinDescription: Надає контенту анімацію обертання. + sparkle: Блиск + sparkleDescription: Надає вмісту ефект мерехтливого блиску. + fade: Згасання + fadeDescription: Зменшує та збільшує видимість контенту. + crop: Обрізати + cropDescription: Обрізати вміст. + scale: Масштабувати + positionDescription: Перемістити вміст на вказане значення. + scaleDescription: Масштабувати вміст на вказану величину. + background: Фоновий колір + foreground: Колір переднього плану + foregroundDescription: Змінити колір тексту на передньому плані. + bounceDescription: Надає контенту пружної анімації. + shakeDescription: Надає контенту тремтливої анімації. + rainbowDescription: Робить вміст веселковим. + rotateDescription: Повертає вміст на вказаний кут. + advancedDescription: Якщо вимкнено, дозволяє лише базову розмітку, якщо не відтворюється + анімований MFM + plainDescription: Вимикає ефекти всіх MFM, що містяться в цьому MFM-ефекті. + stop: Зупинити MFM + plain: Звичайний текст + advanced: Розширені MFM + warn: MFM може містити швидко-рухому або яскраву анімацію + position: Розташування + rainbow: Веселка + backgroundDescription: Змінити колір фону тексту. _instanceTicker: none: "Не відображати" remote: "Відображати для віддалених користувачів" @@ -892,6 +943,7 @@ _serverDisconnectedBehavior: reload: "Автоматично перезавантажити" dialog: "Показати діалогове вікно" quiet: "Показати ненав’язливе попередження" + nothing: Нічого не робити _channel: create: "Створити канал" edit: "Редагувати канал" @@ -900,22 +952,27 @@ _channel: featured: "Тренди" following: "Підписки" usersCount: "{n} учасників" - notesCount: "{n} дописів" + notesCount: "{n} записів" + nameOnly: Тільки назва + nameAndDescription: Назва та опис + owned: Власні _menuDisplay: hide: "Сховати" + sideFull: Збоку + sideIcon: Збоку (тільки іконки) + top: Верх _wordMute: muteWords: "Заглушені слова" - muteWordsDescription: "Розділення ключових слів пробілами для \"І\" або з нової - лінійки для \"АБО\"" + muteWordsDescription: "Відокремліть ключові слова пробілами для умови \"І\" або + з нового рядку для умови \"АБО\"." muteWordsDescription2: "Для використання RegEx, ключові слова потрібно вписати поміж слешів \"/\"." - softDescription: "Приховати записи які відповідають критеріям зі стрічки подій." + softDescription: "Приховати записи які відповідають критеріям зі стрічки." hardDescription: "Приховати записи які відповідають критеріям зі стрічки подій. - Також приховані записи не будуть додані до стрічки подій навіть якщо критерії - буде змінено." + Також приховані записи не будуть додані до стрічки навіть якщо критерії буде змінено." soft: "М'яко" hard: "Жорстко" - mutedNotes: "Заблоковані нотатки" + mutedNotes: "Ігноровані записи" _theme: explore: "Оглянути теми" install: "Встановити тему" @@ -979,9 +1036,20 @@ _theme: accentDarken: "Акцент (Затемлений)" accentLighten: "Акцент (Освітлений)" fgHighlighted: "Виділений текст" + color: Колір + refProp: Посилання на властивість + alpha: Прозорість + constant: Стала + refConst: Посилання на сталу + key: Ключ + funcKind: Тип функції + darken: Затемнення + argument: Аргумент + basedProp: Початкова властивість + addConstant: Додати сталу _sfx: - note: "Нотатки" - noteMy: "Мої нотатки" + note: "Новий запис" + noteMy: "Мої записи" notification: "Сповіщення" chat: "Чати" chatBg: "Чати (фон)" @@ -991,7 +1059,7 @@ _ago: future: "Майбутнє" justNow: "Щойно" secondsAgo: "{n}с тому" - minutesAgo: "{n}х тому" + minutesAgo: "{n}хв тому" hoursAgo: "{n}г тому" daysAgo: "{n}д тому" weeksAgo: "{n} тиж. тому" @@ -1006,36 +1074,66 @@ _tutorial: title: "Як використовувати Calckey" step1_1: "Ласкаво просимо!" step1_2: "Давайте налаштуємо вас. Ви будете працювати в найкоротші терміни!" - step2_1: "Спочатку, будь ласка, заповніть свій профіль" - step2_2: "Надавши деяку інформацію про себе, іншим людям буде легше зрозуміти, чи + step2_1: "Спочатку, будь ласка, заповніть свій профіль." + step2_2: "Після надання інформації про себе, іншим людям буде легше зрозуміти, чи хочуть вони бачити ваші записи або стежити за вами." - step3_1: "Тепер настав час стежити за деякими людьми!" + step3_1: "Тепер настав час на когось підписатися!" step3_2: "Ваша домашня і соціальна стрічки ґрунтуються на тому, за ким ви стежите, тому для початку спробуйте стежити за кількома акаунтами.\nНатисніть на гурток із плюсом у правому верхньому кутку профілю, щоб стежити за ним." - step4_1: "Давайте вийдемо на вас" + step4_1: "Давайте вийдемо на вас." step4_2: "Для свого першого повідомлення деякі люди люблять робити {introduction} повідомлення або просте \"Hello world!\"" - step5_1: "Тимчасові рамки, скрізь тимчасові рамки!" - step5_2: "У вашому екземплярі включені {timelines} різних часових ліній." - step5_3: "Головна {icon} часова шкала - це шкала, де ви можете бачити повідомлення - ваших підписників." - step5_4: "Місцева {icon} тимчасова шкала - це шкала, де ви можете бачити повідомлення - всіх інших користувачів даного екземпляра" - step5_5: "Тимчасова шкала Рекомендовані {icon} - це шкала, де ви можете бачити повідомлення - від інстанцій, рекомендованих адміністраторами." - step5_6: "На часовій шкалі Social {icon} відображаються повідомлення від друзів - ваших підписників" - step5_7: "Глобальна {icon} часова шкала - це місце, де ви можете бачити повідомлення - від усіх інших підключених екземплярів" + step5_1: "Стрічки, скрізь одні стрічки!" + step5_2: "У вашому сервері включені {timelines} різні стрічки." + step5_3: "Головна {icon} стрічка - це стрічка, де ви можете бачити записи тих, на + кого ви підписалися." + step5_4: "Місцева {icon} стрічка - це стрічка, де ви можете бачити записи всіх інших + користувачів даного серверу." + step5_5: "Стрічка рекомендованих {icon} - це комбінація домашньої та місцевої стрічок." + step5_6: "На стрічці Рекомендованих {icon} ви можете бачити записи з серверів, які + рекомендують адміністратори." + step5_7: "Глобальна {icon} стрічка - це місце, де ви можете бачити записи від усіх + інших приєднаних серверів." step6_1: "Отже, що це за місце?" - step6_2: "Ну, ви не просто приєдналися до Кальки. Ви приєдналися до порталу в Fediverse, - взаємопов'язаної мережі з тисяч серверів, званих \"інстансами\"." + step6_2: "Ну, ви не просто приєдналися до Calckey. Ви увійшли в Fediverse, взаємопов'язану + мережу з тисяч серверів." step6_3: "Кожен сервер працює по-своєму, і не на всіх серверах працює Calckey. Але - цей працює! Це трохи складно, але ви швидко розберетеся" + цей працює! Це трохи складно, але ви швидко розберетеся." step6_4: "Тепер ідіть, вивчайте і розважайтеся!" _2fa: registerSecurityKey: "Зареєструвати новий ключ безпеки" + registerTOTP: Зареєструйте новий пристрій + tapSecurityKey: Будь ласка, дотримуйтесь інструкцій вашого браузера, щоб зареєструвати + апаратний ключ безпеки або ключ-пароль + securityKeyName: Введіть назву ключа + chromePasskeyNotSupported: Паролі Chrome наразі не підтримуються. + renewTOTPOk: Переналаштувати + removeKey: Видалити ключ безпеки + alreadyRegistered: 2FA вже налаштовано. + step2Click: Натиснувши на цей QR-код, ви зможете зареєструвати 2FA у вашому ключі + безпеки або додатку-автентифікаторі для телефону. + step3Title: Введіть код автентифікації + step1: По-перше, встановіть програму 2FA (наприклад, {a} або {b}) на свій пристрій. + securityKeyNotSupported: Ваш браузер не підтримує ключі безпеки. + step4: Відтепер при наступних спробах входу в систему буде запитуватися такий токен. + securityKeyInfo: Окрім автентифікації за відбитком пальця або PIN-кодом, ви також + можете налаштувати автентифікацію за допомогою апаратних ключів безпеки, які підтримують + FIDO2, щоб додатково захистити свій обліковий запис. + removeKeyConfirm: Дійсно видалити ключ {name}? + whyTOTPOnlyRenew: Додаток автентифікатора не можна видалити, доки зареєстровано + ключ безпеки. + renewTOTP: Переналаштувати додаток-автентифікатор + renewTOTPCancel: Скасувати + renewTOTPConfirm: Це призведе до того, що коди підтвердження з попереднього додатку + перестануть працювати + token: 2FA Токен + registerTOTPBeforeKey: Будь ласка, налаштуйте додаток-автентифікатор, щоб зареєструвати + ключ безпеки або пароль. + step2Url: 'Також, ви можете ввести цю URL-адресу, якщо використовуєте десктопну + програму:' + step3: Введіть токен, наданий вашим додатком, щоб завершити налаштування. + step2: Потім відскануйте QR-код, що відображається на цьому екрані. _permissions: "read:account": "Переглядати дані профілю" "write:account": "Змінити дані акаунту" @@ -1051,7 +1149,7 @@ _permissions: "write:messaging": "Створювати та видаляти повідомлення" "read:mutes": "Переглядати список ігнорованих" "write:mutes": "Змінювати список ігнорованих" - "write:notes": "Писати і видаляти нотатки" + "write:notes": "Створення та видалення записів" "read:notifications": "Переглядати сповіщення" "read:reactions": "Переглядати реакції" "write:reactions": "Змінювати реакції" @@ -1064,13 +1162,27 @@ _permissions: "write:user-groups": "Змінювати групи користувача" "read:channels": "Переглядати канали" "write:channels": "Змінювати канали" + "read:gallery": Переглянути галерею + "write:gallery": Редагування галереї + "read:gallery-likes": Переглянути список вподобаних записів галереї + "write:notifications": Керування сповіщеннями + "write:gallery-likes": Редагувати список вподобаних записів галереї _auth: shareAccess: "Ви хочете надати \"{name}\" доступ до цього акаунту?" shareAccessAsk: "Ви впевнені, що хочете надати цій програмі доступ до вашого акаунту?" denied: "У доступі відмовлено" + allPermissions: Повний доступ до облікового запису + permissionAsk: 'Цей додаток запитує наступні дозволи:' + copyAsk: 'Будь ласка, вставте наступний код авторизації в додаток:' + pleaseGoBack: Будь ласка, поверніться до додатку + callback: Повернення до додатку _antennaSources: - all: "Всі нотатки" - homeTimeline: "Нотатки тих, на кого ви підписані" + all: "Усі записи" + homeTimeline: "Записи тих, на кого ви підписані" + instances: Записи від усіх користувачів на сервері + userGroup: Записи від користувачів у вказаній групі + users: Записи обраних користувачів + userList: Дописи користувачів із вказаного списку _weekday: sunday: "Неділя" monday: "Понеділок" @@ -1091,20 +1203,30 @@ _widgets: photos: "Фото" digitalClock: "Цифровий годинник" federation: "Федіверс" - postForm: "Створення нотатки" + postForm: "Створення запису" slideshow: "Слайд-шоу" button: "Кнопка" onlineUsers: "Користувачі онлайн" jobQueue: "Черга завдань" - serverMetric: "Показники сервера " + serverMetric: "Показники сервера" aiscript: "Консоль AiScript" + _userList: + chooseList: Оберіть список + meiliStatus: Стан сервера + meiliSize: Розмір індексу + rssTicker: RSS-тікер + instanceCloud: Хмара серверів + unixClock: Годинник UNIX + userList: Список користувачів + serverInfo: Інформація про сервер + meiliIndexCount: Індексовані записи _cw: hide: "Сховати" show: "Показати більше" chars: "{count} символів" files: "{count} файлів" _poll: - noOnlyOneChoice: "Потрібні принаймні два варіанти." + noOnlyOneChoice: "Потрібні принаймні два варіанти" choiceN: "Варіант {n}" noMore: "Більше варіантів додати не можна" canMultipleVote: "Можна вибрати кілька варіантів" @@ -1127,19 +1249,19 @@ _poll: remainingSeconds: "Залишилось {s} секунд" _visibility: public: "Публічний" - publicDescription: "Для всіх користувачів" - home: "Домівка" + publicDescription: "Ваш запис буде видно в усіх публічних стрічках" + home: "Скритий" homeDescription: "Лише на домашній стрічці" followers: "Підписники" - followersDescription: "Тільки для підписників" + followersDescription: "Зробити видимим тільки для ваших підписників і згаданих користувачів" specified: "Особисто" specifiedDescription: "Лише для певних користувачів" localOnly: "Локально" localOnlyDescription: "Приховано для віддалених користувачів" _postForm: - replyPlaceholder: "Відповідь на цю нотатку..." - quotePlaceholder: "Прокоментуйте цю нотатку..." - channelPlaceholder: "Опублікувати в каналі" + replyPlaceholder: "Відповідь на цей запис..." + quotePlaceholder: "Прокоментуйте цей запис..." + channelPlaceholder: "Опублікувати в каналі..." _placeholders: a: "Чим займаєтесь?" b: "Що відбувається навколо вас?" @@ -1160,46 +1282,59 @@ _profile: metadataContent: "Вміст" changeAvatar: "Змінити аватар" changeBanner: "Змінити банер" + locationDescription: Якщо ви спочатку введете своє місто, іншим користувачам буде + показано ваш місцевий час. _exportOrImport: - allNotes: "Всі нотатки" + allNotes: "Всі записи" followingList: "Підписки" muteList: "Ігнорувати" blockingList: "Заблокувати" userLists: "Списки" + excludeInactiveUsers: Вилучити неактивних користувачів + excludeMutingUsers: Вилучити заглушених користувачів _charts: federation: "Федіверс" apRequest: "Запити" usersTotal: "Загальна кількість користувачів" activeUsers: "Активні користувачі" - notesTotal: "Загальна кількість нотаток" + notesTotal: "Загальна кількість записів" filesIncDec: "Зміни кількості файлів" filesTotal: "Загальна кількість файлів" + storageUsageIncDec: Різниця в використанні ємності диску + remoteNotesIncDec: Різниця в кількості віддалених записів + notesIncDec: Різниця в кількості записів + localNotesIncDec: Різниця в кількості локальних записів + storageUsageTotal: Загальне використання пам'яті + usersIncDec: Різниця в кількості користувачів _instanceCharts: requests: "Запити" usersTotal: "Сумарна кількість користувачів" - notes: "Різниця кількості зроблених записів" - notesTotal: "Сумарна кількість нотаток" - ff: "Різниця кількості підписників" + notes: "Різниця в кількості зроблених записів" + notesTotal: "Сумарна кількість записів" + ff: "Різниця кількості підписників " ffTotal: "Кількість підписників" cacheSizeTotal: "Сумарний розмір кешу" files: "Різниця в кількості файлів" filesTotal: "Сумарна кількість файлів" + users: Різниця в кількості користувачів + cacheSize: Різниця в розмірі кешу _timelines: home: "Домівка" local: "Локальна" social: "Соціальна" global: "Глобальна" + recommended: Рекомендована _pages: newPage: "Створити сторінку" editPage: "Редагувати сторінку" readPage: "Перегляд вихідного коду" - created: "Сторінка успішно створена." - updated: "Сторінка успішно оновлена." + created: "Сторінка успішно створена" + updated: "Сторінка успішно оновлена" deleted: "Сторінку видалено" pageSetting: "Налаштування сторінки" - nameAlreadyExists: "Вказана адреса сторінки вже існує." - invalidNameTitle: "Вказана адреса сторінки неприпустима." - invalidNameText: "Переконайтеся, що не залишили порожнім." + nameAlreadyExists: "Вказана адреса сторінки вже існує" + invalidNameTitle: "Вказана адреса сторінки неприпустима" + invalidNameText: "Переконайтеся, що поле заголовка сторінки не порожнє" editThisPage: "Редагувати цю сторінку" viewSource: "Переглянути вихідний код" viewPage: "Переглянути свої сторінки" @@ -1242,6 +1377,7 @@ _pages: _post: text: "Вміст" canvasId: "Ідентифікатор полотна" + attachCanvasImage: Прикріпити зображення полотна textInput: "Введення тексту" _textInput: name: "Ім'я змінної" @@ -1262,10 +1398,10 @@ _pages: id: "Ідентифікатор полотна" width: "Ширина" height: "Висота" - note: "Вбудована нотатка" + note: "Вбудований запис" _note: - id: "Ідентифікатор нотатки" - idDescription: "Також можна вказати посилання на нотатку" + id: "Ідентифікатор запису" + idDescription: "Також можна вказати посилання на запис." detailed: "Детальний вигляд" switch: "Перемикач" _switch: @@ -1456,7 +1592,7 @@ _pages: arg1: "Текст" ref: "Змінні" aiScriptVar: "Змінна AiScript" - fn: "Функції" + fn: "Функція" _fn: slots: "Паз" slots-info: "Використовувати нову лінію як роздільник пазів" @@ -1508,9 +1644,16 @@ _notification: followRequestAccepted: "Прийняті підписки" groupInvited: "Запрошення до груп" app: "Сповіщення від додатків" + pollEnded: Опитування закінчено _actions: reply: "Відповісти" - renote: "Поширити" + renote: "Поширення" + followBack: також підписався на вас + emptyPushNotificationMessage: Push-сповіщення були оновлені + voted: проголосував на вашому опитуванні + renoted: поширив ваш запис + reacted: відреагував на ваш запис + pollEnded: Стали доступні результати опитування _deck: alwaysShowMainColumn: "Завжди показувати головну колонку" columnAlign: "Вирівняти стовпці" @@ -1521,16 +1664,27 @@ _deck: swapDown: "Пересунути вниз" stackLeft: "У стовпчик вліво" popRight: "Витягнути вправо" - profile: "Обліковий запис" + profile: "Простір" _columns: main: "Головна" widgets: "Віджети" notifications: "Сповіщення" tl: "Стрічка" - antenna: "Антени" + antenna: "Антена" list: "Списки" mentions: "Згадки" - direct: "Особисте" + direct: "Особисті повідомлення" + channel: Канал + newProfile: Новий простір + introduction2: Натисніть на + у правій частині екрана, щоб додавати нові стовпці + по бажанню. + configureColumn: Налаштування стовпців + introduction: Створіть ідеальний інтерфейс для себе, вільно розташовуючи стовпці! + widgetsIntroduction: Будь ласка, виберіть "Редагувати віджети" в меню колонки і + додайте віджет. + renameProfile: Перейменувати простір + deleteProfile: Видалити простір + nameAlreadyExists: Простір із такою назвою вже існує. removeReaction: Видалити вашу реакцію renoteMute: Ігнорувати поширення renoteUnmute: Показувати поширення @@ -1623,3 +1777,357 @@ usernameInfo: Ім'я, яке ідентифікує ваш обліковий Ім'я користувача не може бути змінено пізніше. noThankYou: Ні, дякую keepCw: Зберігати попередження про вміст +showEmojisInReactionNotifications: Показувати емодзі у сповіщеннях про реакції +accountMoved: 'Користувач переїхав до нового облікового запису:' +expandOnNoteClickDesc: Якщо цю опцію вимкнено, ви все одно зможете відкривати дописи + в меню, клацнувши правою кнопкою миші або натиснувши на мітку часу. +deleteAccountConfirm: Це призведе до незворотного видалення вашого облікового запису. + Приступити? +unread: Непрочитане +filter: Фільтри +useDrawerReactionPickerForMobile: Відображати вибирач реакцій як шухляду на мобільному + телефоні +leaveGroupConfirm: Ви впевнені, що хочете залишити "{name}"? +clickToFinishEmailVerification: Будь ласка, натисніть [{ok}], щоб завершити перевірку + електронної пошти. +welcomeBackWithName: Ласкаво просимо назад, {name} +overridedDeviceKind: Тип пристрою +themeColor: Колір теми серверу +oneDay: Один день +instanceDefaultLightTheme: Світла тема за замовчуванням для сервера +oneWeek: Одна неділя +instanceDefaultDarkTheme: Темна тема за замовчуванням для сервера +video: Відео +audio: Аудіо +rateLimitExceeded: Перевищено ліміт +numberOfPageCacheDescription: Збільшення цієї величини покращить зручність для користувачів, + але призведе до збільшення навантаження на сервер та використання більшої кількості + пам'яті. +lastActiveDate: Останній раз використовувався у +statusbar: Панель статусу +speed: Швидкість +sensitiveMediaDetection: Виявлення NSFW медіа +cannotUploadBecauseNoFreeSpace: Завантаження не вдалося через брак місця на Диску. +cannotUploadBecauseExceedsFileSizeLimit: Цей файл не може бути завантажений, оскільки + він перевищує максимально дозволений розмір. +account: Обліковий запис +move: Перемістити +pushNotification: Push-сповіщення +subscribePushNotification: Увімкнути push-сповіщення +unsubscribePushNotification: Вимкнути push-сповіщення +pushNotificationAlreadySubscribed: Push-сповіщення вже увімкнено +enterSendsMessage: Натисніть Enter у повідомленнях, щоб надіслати повідомлення (якщо + вимкнено, то Ctrl + Enter) +showAds: Показувати рекламу +customMOTD: Користувацькі MOTD (повідомлення на заставці) +customSplashIcons: Користувацькі іконки заставки (URL) +splash: Заставка +adminCustomCssWarn: Цей параметр слід використовувати, тільки якщо ви знаєте, що він + робить. Введення неправильних значень може призвести до того, що ВСІ клієнти перестануть + нормально працювати. Будь ласка, переконайтеся, що ваш CSS працює належним чином, + протестувавши його в налаштуваннях користувача. +_filters: + followersOnly: Тільки підписники + fromUser: Від користувача + notesBefore: Записи до + withFile: З файлом + fromDomain: З домену + notesAfter: Записи після + followingOnly: Тільки підписки +sendModMail: Надіслати повідомлення про модерацію +enableServerMachineStats: Увімкнути статистику серверного обладнання +enableIdenticonGeneration: Увімкнути генерацію Identicon +_sensitiveMediaDetection: + analyzeVideosDescription: Аналізує відео так само як і зображення. Це трохи збільшить + навантаження на сервер. + description: Зменшує навантаження на серверну модерацію завдяки автоматичному розпізнаванню + NSFW медіа за допомогою машинного навчання. Це трохи збільшить навантаження на + сервер. + sensitivity: Чутливість виявлення + sensitivityDescription: Зменшення чутливості призведе до зменшення кількості хибних + спрацьовувань, тоді як збільшення чутливості призведе до зменшення кількості пропущених + спрацьовувань. + setSensitiveFlagAutomatically: Позначити як NSFW + setSensitiveFlagAutomaticallyDescription: Результати внутрішнього виявлення будуть + збережені, навіть якщо цю опцію вимкнено. + analyzeVideos: Ввімкнути аналіз відео +_emailUnavailable: + used: Ця електронна пошта вже використовується + format: Формат цієї адреси електронної пошти є неправильним + mx: Цей сервер електронної пошти є недійсним + disposable: Використовувати одноразові адреси електронної пошти заборонено + smtp: Цей поштовий сервер не відповідає +_messaging: + dms: Приватні + groups: Групи +_instanceMute: + instanceMuteDescription: Це приховає всі записи/поширення із вказаних серверів, + включно з відповідями користувачам заглушеного серверу. + title: Приховує записи з перелічених серверів. + instanceMuteDescription2: Розділити новими рядками + heading: Список серверів для заглушення +_experiments: + enablePostImports: Ввімкнути імпорт записів + title: Експерименти + postImportsCaption: Дозволяє користувачам імпортувати свої публікації з минулих + облікових записів Calckey, Misskey, Mastodon, Akkoma і Pleroma. Це може спричинити + зниження швидкості під час завантаження, якщо ваша черга перевантажена. +_dialog: + charactersExceeded: 'Перевищено максимальну кількість символів! Обмеження: {current}/{max}' + charactersBelow: 'Недостатньо символів! Обмеження: {current}/{min}' +jumpToSpecifiedDate: Перейти до конкретної дати +quitFullView: Закрити повний вигляд +ffVisibility: Видимість підписок/підписників +numberOfColumn: Кількість стовпців +failedToFetchAccountInformation: Не вдалося отримати інформацію про обліковий запис +reflectMayTakeTime: Може пройти деякий час, перш ніж зміни набудуть чинності. +recentNHours: Останні {n} годин +logoutConfirm: Ви впевнені, що хочете вийти? +enableRecommendedTimeline: Увімкнути рекомендовану стрічку +_accountDelete: + requestAccountDelete: Запросити видалення облікового запису + accountDelete: Видалити обліковий запис + mayTakeTime: Оскільки видалення облікового запису є ресурсоємним процесом, він може + зайняти деякий час, залежно від того, скільки контенту ви створили та скільки + файлів завантажили. + sendEmail: Коли ваш обліковий запис буде видалено, ми повідомимо на вказану вами + електронну пошту. + started: Процес видалення розпочався. + inProgress: Наразі триває видалення +_preferencesBackups: + deleteConfirm: Видалити резервну копію {name}? + applyConfirm: Ви дійсно хочете застосувати резервну копію "{name}" до цього пристрою? + Існуючі налаштування цього пристрою буде замінено. + saveConfirm: Зберегти резервну копію як {name}? + saveNew: Зберегти нову резервну копію + save: Зберегти зміни + inputName: Будь ласка, введіть назву для цієї резервної копії + loadFile: Завантажити з файлу + updatedAt: 'Оновлено: {date} {time}' + invalidFile: Неправильний формат файлу + apply: Застосувати до цього пристрою + list: Створені резервні копії + cannotSave: Збереження невдале + nameAlreadyExists: Резервна копія з назвою "{name}" вже існує. Будь ласка, введіть + іншу назву. + renameConfirm: Перейменувати цю резервну копію з "{old}" на "{new}"? + noBackups: Резервних копій немає. Ви можете створити резервну копію налаштувань + клієнта на цьому сервері за допомогою "Створити нову резервну копію". + createdAt: 'Створено: {date} {time}' + cannotLoad: Не вдалося завантажити +beta: Бета +customMOTDDescription: Користувацькі повідомлення для MOTD (заставки), розділені новими + рядками, які будуть показуватися випадковим чином щоразу, коли користувач завантажує/перезавантажує + сторінку. +replayTutorial: Перезапустити туторіал +_forgotPassword: + ifNoEmail: Якщо ви не використовували електронну пошту під час реєстрації, зверніться + до адміністратора серверу. + enterEmail: Введіть адресу електронної пошти, яку ви використовували для реєстрації. + На неї буде надіслано посилання, за яким ви зможете скинути пароль. + contactAdmin: Цей сервер не підтримує використання адрес електронної пошти, будь + ласка, зверніться до адміністратора сервера, щоб скинути пароль. +reactionPickerSkinTone: Бажаний колір шкіри емодзі +addInstance: Додати сервер +jumpToPrevious: Перейти до попереднього +listsDesc: Списки дозволяють створювати стрічки із вказаними користувачами. Доступ + до них можна отримати на сторінці стрічок. +channelFederationWarn: Канали наразі федеруються з іншими серверами +lastCommunication: Останнє повідомлення +edited: Відредаговано {date} о {time} +confirmToUnclipAlreadyClippedNote: Цей запис уже в підбірці "{name}". Чи бажаєте ви + натомість видалити пост із підбірки? +quickAction: Швидкі дії +remoteOnly: Тільки віддалені +failedToUpload: Помилка завантаження +moveFrom: Мігрувати на цей обліковий запис зі старого облікового запису +preventAiLearning: Захист від скрепінгу ШІ-ботів +moveAccountDescription: Цей процес є незворотнім. Переконайтеся, що ви створили псевдонім + для цього акаунта в новому акаунті перед переїздом. Будь ласка, введіть тег акаунта + у форматі @person@server.com +_signup: + almostThere: Майже готово + emailAddressInfo: Будь ласка, введіть свою адресу електронної пошти. Вона не буде + опублікована. + emailSent: На вашу електронну адресу ({email}) було надіслано лист із підтвердженням. + Будь ласка, перейдіть за посиланням, щоб завершити створення облікового запису. +defaultValueIs: 'За замовчуванням: {value}' +shareWithNote: Поділитися з записом +classic: Відцентрований +size: Розмір +slow: Повільно +alt: ALT +auto: Автоматично +oneHour: Одна година +instanceDefaultThemeDescription: Введіть код теми в об'єктному форматі. +cropImageAsk: Чи бажаєте ви обрізати це зображення? +noEmailServerWarning: Поштовий сервер не налаштовано. +thereIsUnresolvedAbuseReportWarning: Є не розглянуті звіти. +image: Зображення +check: Перевірити +isSystemAccount: Цей акаунт створений і автоматично управляється системою. Будь ласка, + не модеруйте, не редагуйте, не видаляйте та не втручайтеся в цей акаунт будь-яким + іншим чином, інакше це може призвести до поломки вашого серверу. +document: Документація +driveCapOverrideCaption: Ви можете скинути ємність до значення за замовчуванням, ввівши + значення 0 або менше. +numberOfPageCache: Кількість кешованих сторінок +pleaseSelect: Оберіть варіант +refreshInterval: 'Інтервал оновлення ' +enableAutoSensitive: Автоматичне маркування NSFW +cannotUploadBecauseInappropriate: Цей файл не може бути завантажений тому що його + частини були виявлені як потенційне NSFW. +sendPushNotificationReadMessageCaption: На короткий час буде показано сповіщення з + текстом "{emptyPushNotificationMessage}". Це може призвести до збільшення споживання + заряду акумулятора вашого пристрою, якщо це можливо. +pushNotificationNotSupported: Ваш браузер або сервер не підтримує push-сповіщення +showUpdates: Показувати спливаюче вікно при оновленні Calckey +updateAvailable: Можливо, є доступне оновлення! +recommendedInstancesDescription: Рекомендовані сервери відокремлюються переведенням + рядка, щоб з'явитися на стрічці рекомендацій. +caption: Автоматичний підпис +showAdminUpdates: Вказати, що доступна нова версія Calckey (тільки для адміністратора) +defaultReaction: Емодзі реакція за замовчуванням для вихідних і вхідних записів +license: Ліцензія +indexPosts: Індексувати пости +indexFrom: Індексувати записи з ID +indexFromDescription: Залиште порожнім, щоб індексувати кожен запис +indexNotice: Зараз відбувається індексація. Це, ймовірно, займе деякий час, будь ласка, + не перезавантажуйте сервер принаймні годину. +signupsDisabled: Реєстрація на цьому сервері наразі відключена, але ви завжди можете + зареєструватися на іншому сервері! Якщо у вас є код запрошення на цей сервер, будь + ласка, введіть його нижче. +findOtherInstance: Знайти інший сервер +customKaTeXMacro: Користувацькі макроси KaTeX +enableCustomKaTeXMacro: Увімкнути користувацькі макроси KaTeX +apps: Додатки +isModerator: Модератор +isAdmin: Адміністратор +isPatron: Патрон Calckey +swipeOnMobile: Дозволити гортання між сторінками +migration: Міграція +swipeOnDesktop: Дозволити свайп у мобільному стилі на десктопі +logoImageUrl: URL-адреса зображення логотипу +moveTo: Перенести поточний обліковий запис на новий +moveFromDescription: Це встановить псевдонім вашого старого облікового запису, щоб + ви могли перейти зі старого облікового запису до цього поточного. Зробіть це ДО + переходу зі старого акаунта. Будь ласка, введіть тег акаунта у форматі @person@server.com +moveToLabel: 'Обліковий запис, на який ви мігруєте:' +moveAccount: Перемістити обліковий запис! +moveFromLabel: 'Обліковий запис, з якого ви мігруєте:' +_plugin: + install: Встановлення плагінів + manage: Керування плагінами + installWarn: Будь ласка, не встановлюйте ненадійні плагіни. +_skinTones: + yellow: Жовтий + mediumLight: Помірно-світлий + medium: Помірний + mediumDark: Помірно-темний + dark: Темний + light: Світлий +tenMinutes: 10 хвилин +expandOnNoteClick: Відкрити запис кліком +preferencesBackups: Резервне копіювання +unlikeConfirm: Дійсно видалити вподобайку? +fullView: Повний вигляд +postToGallery: Опублікувати в галереї +memo: Нотатки +allowedInstancesDescription: Хости серверів, які будуть допущені до федерації, кожен + з яких відокремлюється новим рядком (стосується лише приватного режиму). +squareAvatars: Квадратні аватарки +aiChanMode: Режим ШІ +controlPanel: Панель керування +manageAccounts: Керування обліковими записами +incorrectPassword: Неправильний пароль. +voteConfirm: Підтвердити свій голос за "{choice}"? +leaveGroup: Залишити групу +smartphone: Смартфон +mutePeriod: Тривалість глушіння +requireAdminForView: Ви маєте увійти з облікового запису адміністратора, щоб переглянути + це. +fast: Швидко +isBot: Цей обліковий запис є ботом +isLocked: Цей обліковий запис має схвалення запитів на підписку +silenceThisInstance: Ігнорувати цей сервер +hideOnlineStatusDescription: Приховування вашого онлайн-статусу знижує зручність деяких + функцій, таких як пошук. +accountDeletionInProgress: Наразі триває видалення облікового запису +makeReactionsPublic: Зробити історію реакцій публічною +continueThread: Показати наступні відповіді +unmuteThread: Скасувати глушіння гілки +ffVisibilityDescription: Дозволяє налаштувати, хто може бачити, на кого ви підписані + і хто підписаний на вас. +tablet: Планшет +cropImage: Обрізати зображення +recentNDays: Останні {n} днів +navbar: Панель навігації +noGraze: Будь ласка, вимкніть розширення браузера "Graze для Mastodon", оскільки воно + заважає роботі Calckey. +preventAiLearningDescription: Попросити сторонні мовні моделі ШІ не вивчати вміст, + який ви завантажуєте, наприклад, записи та зображення. +userSaysSomethingReasonReply: '{name} відповів на пост з {reason}' +secureMode: Безпечний режим (Authorized Fetch) +seperateRenoteQuote: Розділити кнопки поширення та цитати +makeReactionsPublicDescription: Це зробить список усіх ваших минулих реакцій публічно + видимим. +muteThread: Заглушити гілку +sendPushNotificationReadMessage: Видаляти push-сповіщення після того, як відповідні + сповіщення або повідомлення будуть прочитані +unclip: Видалити з підбірки +silencedInstances: Ігноровані сервери +typeToConfirm: Введіть {x} щоб підтвердити +silencedWarning: Ця сторінка відображається тому, що ці користувачі з серверів, які + ваш адміністратор заглушив, тому вони потенційно можуть бути спамом. +shuffle: Перетасувати +ratio: Співвідношення +secureModeInfo: У разі запитів з інших серверів не надсилати непідтверджену відповідь. +pubSub: Облікові записи Pub/Sub +driveCapOverrideLabel: Змінити ємність диску для цього користувача +deleteAccount: Видалити обліковий запис +type: Тип +enableAutoSensitiveDescription: Дозволяє автоматично виявляти та позначати медіафайли + NSFW за допомогою машинного навчання, де це можливо. Навіть якщо цю опцію вимкнено, + вона може бути увімкнена на всьому сервері. +recommendedInstances: Рекомендовані сервери +noteId: Ідентифікатор запису +showPopup: Сповіщати користувачів спливаючим вікном +showWithSparkles: Показати з блиском +youHaveUnreadAnnouncements: У вас є непрочитані оголошення +donationLink: Посилання на сторінку для внесків +neverShow: Не показувати знову +remindMeLater: Можливо пізніше +removeQuote: Видалити цитату +removeRecipient: Видалити одержувача +removeMember: Видалити члена +silencedInstancesDescription: Вкажіть імена хостів серверів, які ви хочете ігнорувати. + Облікові записи на перелічених серверах вважаються "Ігнорованими", можуть робити + лише запити на підписку і не можуть згадувати локальні облікові записи, якщо на + них не підписалися. Це не вплине на заблоковані сервери. +hiddenTagsDescription: 'Перелічіть хештеги (без #), які ви хочете приховати з трендів + і дослідження. Приховані хештеги все одно можна знайти іншими способами.' +antennasDesc: "Антени показують нові дописи, що відповідають встановленим вами критеріям!\n + Доступ до них можна отримати зі сторінки стрічок." +clipsDesc: Підбірки схожі на категоризовані закладки, до яких можна надавати спільний + доступ. Ви можете створювати підбірки з меню окремих записів. +migrationConfirm: "Ви точно впевнені, що хочете перенести свій обліковий запис на + {account}? Якщо ви це зробите, ви не зможете скасувати цю операцію і не зможете + користуватися своїм обліковим записом як раніше.\nТакож, будь ласка, переконайтеся, + що ви вибрали цей поточний обліковий запис як обліковий запис, з якого ви переходите." +customKaTeXMacroDescription: 'Налаштуйте макроси, щоб легко писати математичні вирази! + Позначення відповідає визначенню команд LaTeX і записується у вигляді \newcommand{\ + name}{content} або \newcommand{\name}[number of arguments]{content}. Наприклад, + \newcommand{\add}[2]{#1 + #2} розширить \add{3}{foo} to 3 + foo. Фігурні дужки навколо + назви макросу можна змінити на круглі або квадратні. Це вплине на дужки, що використовуються + для аргументів. В одному рядку можна визначити один (і тільки один) макрос, і жоден + рядок не можна розривати посередині визначення. Неправильні рядки просто ігноруються. + Підтримуються лише прості функції заміни рядків; розширений синтаксис, такий як + умовне розгалуження, не може бути використаний тут.' +activeEmailValidationDescription: Вмикає більш сувору перевірку адрес електронної + пошти, яка включає перевірку на наявність одноразових адрес і перевірку того, чи + дійсно з нею можна зв'язатися. Якщо цей прапорець знято, перевіряється лише формат + електронної пошти. +customSplashIconsDescription: URL-адреси іконок для заставки, розділені новими рядками, + які будуть показуватися випадковим чином щоразу, коли користувач завантажує/перезавантажує + сторінку. Будь ласка, переконайтеся, що зображення знаходяться на статичній URL-адресі, + бажано, щоб вони були змінені до розміру 192x192. From d0cc2d8af5bec631d13b81e905da8119eb885c7a Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sat, 15 Jul 2023 15:26:15 -0400 Subject: [PATCH 147/162] fix: move nowrap to proper place --- packages/client/src/components/MkTab.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/MkTab.vue b/packages/client/src/components/MkTab.vue index b5d6e8056..bc5f20d4c 100644 --- a/packages/client/src/components/MkTab.vue +++ b/packages/client/src/components/MkTab.vue @@ -58,7 +58,6 @@ export default defineComponent({ font-size: 90%; border-radius: var(--radius); padding: 10px 8px; - white-space: nowrap; > button { flex: 1; @@ -106,6 +105,8 @@ export default defineComponent({ transparent ); padding-right: 90px !important; + white-space: nowrap; + &::-webkit-scrollbar { display: none; } From b8fcd0dc331ce73994f85ce078c03509bb8cc5ea Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 14:13:21 -0700 Subject: [PATCH 148/162] fix: :lock: prevent potential SSRF through media proxy --- packages/backend/src/misc/download-url.ts | 3 +- .../backend/src/server/proxy/proxy-media.ts | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index 7fafb635b..b96871e72 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -21,9 +21,10 @@ export async function downloadUrl(url: string, path: string): Promise<void> { const maxSize = config.maxFileSize || 262144000; const req = got - .stream(url, { + .stream(url, { headers: { "User-Agent": config.userAgent, + "Host": new URL(url).hostname, }, timeout: { lookup: timeout, diff --git a/packages/backend/src/server/proxy/proxy-media.ts b/packages/backend/src/server/proxy/proxy-media.ts index a9c257bfe..b3bb03124 100644 --- a/packages/backend/src/server/proxy/proxy-media.ts +++ b/packages/backend/src/server/proxy/proxy-media.ts @@ -1,4 +1,6 @@ import * as fs from "node:fs"; +import net from "node:net"; +import { promises } from "node:dns"; import type Koa from "koa"; import sharp from "sharp"; import type { IImage } from "@/services/drive/image-processor.js"; @@ -19,6 +21,40 @@ export async function proxyMedia(ctx: Koa.Context) { return; } + const { hostname } = new URL(url); + let resolvedIps; + try { + resolvedIps = await promises.resolve(hostname); + } catch (error) { + ctx.status = 400; + ctx.body = { message: "Invalid URL" }; + return; + } + + const isSSRF = resolvedIps.some((ip) => { + if (net.isIPv4(ip)) { + const parts = ip.split(".").map(Number); + return ( + parts[0] === 10 || + (parts[0] === 172 && parts[1] >= 16 && parts[1] < 32) || + (parts[0] === 192 && parts[1] === 168) || + parts[0] === 127 || + parts[0] === 0 + ); + } else if (net.isIPv6(ip)) { + return ( + ip.startsWith("::") || ip.startsWith("fc00:") || ip.startsWith("fe80:") + ); + } + return false; + }); + + if (isSSRF) { + ctx.status = 400; + ctx.body = { message: "Access to this URL is not allowed" }; + return; + } + // Create temp file const [path, cleanup] = await createTemp(); From 7308d9f90f5dd2735bfee48db173cc7dee987b29 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 14:28:44 -0700 Subject: [PATCH 149/162] dev78 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b38da39fa..a30d85b3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev77", + "version": "14.0.0-dev78", "codename": "aqua", "repository": { "type": "git", From 5324d1298fc2157adb9777e631a66814d6cc42c6 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 14:50:23 -0700 Subject: [PATCH 150/162] fix: :wrench: max post length 100000 Pleroma doesn't accept >100K (ref: https://blob.cat/objects/82f33d96-534f-45ee-902a-f77c2723db8b) --- .config/example.yml | 2 +- packages/backend/src/const.ts | 7 +++++-- packages/backend/src/misc/hard-limits.ts | 3 +-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.config/example.yml b/.config/example.yml index 9716915b6..f73f4f1d7 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -121,7 +121,7 @@ redis: # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── -# Maximum length of a post (default 3000, max 250000000) +# Maximum length of a post (default 3000, max 100000) #maxNoteLength: 3000 # Maximum length of an image caption (default 1500, max 8192) diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 1f1e63292..49f012c5e 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,7 +1,10 @@ import config from "@/config/index.js"; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; +import { DB_MAX_NOTE_TEXT_LENGTH, DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; -export const MAX_NOTE_TEXT_LENGTH = config.maxNoteLength ?? 3000; +export const MAX_NOTE_TEXT_LENGTH = Math.min( + config.maxNoteLength ?? 3000, + DB_MAX_NOTE_TEXT_LENGTH, +); export const MAX_CAPTION_TEXT_LENGTH = Math.min( config.maxCaptionLength ?? 1500, DB_MAX_IMAGE_COMMENT_LENGTH, diff --git a/packages/backend/src/misc/hard-limits.ts b/packages/backend/src/misc/hard-limits.ts index f1a58a425..62671a706 100644 --- a/packages/backend/src/misc/hard-limits.ts +++ b/packages/backend/src/misc/hard-limits.ts @@ -3,9 +3,8 @@ /** * Maximum note text length that can be stored in DB. * Surrogate pairs count as one - * DEPRECARTED: use const/MAX_NOTE_TEXT_LENGTH instead */ -// export const DB_MAX_NOTE_TEXT_LENGTH = 8192; +export const DB_MAX_NOTE_TEXT_LENGTH = 100000; /** * Maximum image description length that can be stored in DB. From 3ee2dc787b814517642e46d6c8b96aa9542ea42f Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sat, 15 Jul 2023 15:32:39 -0700 Subject: [PATCH 151/162] docs: :bulb: going past DB_MAX_NOTE_TEXT_LENGTH --- packages/backend/src/misc/hard-limits.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/backend/src/misc/hard-limits.ts b/packages/backend/src/misc/hard-limits.ts index 62671a706..5ce3e0ac9 100644 --- a/packages/backend/src/misc/hard-limits.ts +++ b/packages/backend/src/misc/hard-limits.ts @@ -3,6 +3,11 @@ /** * Maximum note text length that can be stored in DB. * Surrogate pairs count as one + * + * NOTE: this can hypothetically be pushed further + * (up to 250000000), but will likely cause truncations + * and incompatibilities with other servers, + * as well as potential performance issues. */ export const DB_MAX_NOTE_TEXT_LENGTH = 100000; From 17124f38344a484d92f3ee06dc4e320398476afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=B3=E3=83=AB=E3=82=BB=E3=83=83=E3=83=88=E5=A7=AB=40?= =?UTF-8?q?=E3=81=8C=E3=82=93=E3=81=B0=E3=82=89=E3=81=AA=E3=81=84?= <cgsama@noreply.codeberg.org> Date: Sat, 15 Jul 2023 22:56:09 +0000 Subject: [PATCH 152/162] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20media=20to=20?= =?UTF-8?q?Mastodon=20and=20Calckey=20post=20imports=20(#10496)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What does this PR do? Adding files fields in the export notes option, and corresponding import notes Current the mastodon import does not import any attachments, this pr will use the "upload from url" feature to include medias if its a valid URL. There are many way to convert the outbox.json file, can be simple as upload media_attachments to any web hosting and do string replace on the json file. I also create a tool that upload the tar.gz file with auto convert and host the media as simplify the process at https://tempfile.moegirl.live Detail example can be found at https://fedi.moegirl.live/notes/9h76gtqnp2gwl5dz https://r2temp.moegirl.live/2023/7/15/15356683-050f-423a-b331-c9a05561f52a/shana-settings-_-meng-zhai-le-yuan-xyou-yu-ou-xiang-de-luo-ke-ke-wu-yan-moe-otaku-elysian-x-gloomily-idol-s-rococo-luncheon----mozilla-firefox-private-browsing-2023-07-15-18-36-37.mp4 Co-authored-by: CGsama <CGsama@outlook.com> Reviewed-on: https://codeberg.org/calckey/calckey/pulls/10496 Co-authored-by: コルセット姫@がんばらない <cgsama@noreply.codeberg.org> Co-committed-by: コルセット姫@がんばらない <cgsama@noreply.codeberg.org> --- .../src/queue/processors/db/export-notes.ts | 9 +++++---- .../processors/db/import-calckey-post.ts | 19 +++++++++++++++++- .../queue/processors/db/import-masto-post.ts | 20 ++++++++++++++++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/queue/processors/db/export-notes.ts b/packages/backend/src/queue/processors/db/export-notes.ts index de8fac05b..bf53f8360 100644 --- a/packages/backend/src/queue/processors/db/export-notes.ts +++ b/packages/backend/src/queue/processors/db/export-notes.ts @@ -4,7 +4,7 @@ import * as fs from "node:fs"; import { queueLogger } from "../../logger.js"; import { addFile } from "@/services/drive/add-file.js"; import { format as dateFormat } from "date-fns"; -import { Users, Notes, Polls } from "@/models/index.js"; +import { Users, Notes, Polls, DriveFiles } from "@/models/index.js"; import { MoreThan } from "typeorm"; import type { Note } from "@/models/entities/note.js"; import type { Poll } from "@/models/entities/poll.js"; @@ -75,7 +75,7 @@ export async function exportNotes( if (note.hasPoll) { poll = await Polls.findOneByOrFail({ noteId: note.id }); } - const content = JSON.stringify(serialize(note, poll)); + const content = JSON.stringify(await serialize(note, poll)); const isFirst = exportedNotesCount === 0; await write(isFirst ? content : ",\n" + content); exportedNotesCount++; @@ -112,15 +112,16 @@ export async function exportNotes( done(); } -function serialize( +async function serialize( note: Note, poll: Poll | null = null, -): Record<string, unknown> { +): Promise<Record<string, unknown>> { return { id: note.id, text: note.text, createdAt: note.createdAt, fileIds: note.fileIds, + files: await DriveFiles.packMany(note.fileIds), replyId: note.replyId, renoteId: note.renoteId, poll: poll, diff --git a/packages/backend/src/queue/processors/db/import-calckey-post.ts b/packages/backend/src/queue/processors/db/import-calckey-post.ts index 28e794aa0..945c50d63 100644 --- a/packages/backend/src/queue/processors/db/import-calckey-post.ts +++ b/packages/backend/src/queue/processors/db/import-calckey-post.ts @@ -3,6 +3,8 @@ import create from "@/services/note/create.js"; import { Users } from "@/models/index.js"; import type { DbUserImportMastoPostJobData } from "@/queue/types.js"; import { queueLogger } from "../../logger.js"; +import { uploadFromUrl } from "@/services/drive/upload-from-url.js"; +import type { DriveFile } from "@/models/entities/drive-file.js"; import type Bull from "bull"; const logger = queueLogger.createSubLogger("import-calckey-post"); @@ -29,10 +31,25 @@ export async function importCkPost( done(); return; } + const urls = (post.files || []) + .map((x: any) => x.url) + .filter((x: String) => x.startsWith("http")); + const files: DriveFile[] = []; + for (const url of urls) { + try { + const file = await uploadFromUrl({ + url: url, + user: user, + }); + files.push(file); + } catch (e) { + logger.error(`Skipped adding file to drive: ${url}`); + } + } const { text, cw, localOnly, createdAt } = Post.parse(post); const note = await create(user, { createdAt: createdAt, - files: undefined, + files: files.length == 0 ? undefined : files, poll: undefined, text: text || undefined, reply: null, diff --git a/packages/backend/src/queue/processors/db/import-masto-post.ts b/packages/backend/src/queue/processors/db/import-masto-post.ts index efa4adf3f..05166b085 100644 --- a/packages/backend/src/queue/processors/db/import-masto-post.ts +++ b/packages/backend/src/queue/processors/db/import-masto-post.ts @@ -6,6 +6,8 @@ import type Bull from "bull"; import { htmlToMfm } from "@/remote/activitypub/misc/html-to-mfm.js"; import { resolveNote } from "@/remote/activitypub/models/note.js"; import { Note } from "@/models/entities/note.js"; +import { uploadFromUrl } from "@/services/drive/upload-from-url.js"; +import type { DriveFile } from "@/models/entities/drive-file.js"; const logger = queueLogger.createSubLogger("import-masto-post"); @@ -43,9 +45,25 @@ export async function importMastoPost( throw e; } job.progress(80); + const urls = post.object.attachment + .map((x: any) => x.url) + .filter((x: String) => x.startsWith("http")); + const files: DriveFile[] = []; + for (const url of urls) { + try { + const file = await uploadFromUrl({ + url: url, + user: user, + }); + files.push(file); + } catch (e) { + logger.error(`Skipped adding file to drive: ${url}`); + } + } + const note = await create(user, { createdAt: new Date(post.object.published), - files: undefined, + files: files.length == 0 ? undefined : files, poll: undefined, text: text || undefined, reply, From 9fbcdb529ed01a3391f4fbf56630fa4c79116c9f Mon Sep 17 00:00:00 2001 From: Mizunashi Mana <contact@mizunashi.work> Date: Sun, 16 Jul 2023 18:57:38 +0900 Subject: [PATCH 153/162] feat: Move json5 to prod dependencies --- packages/backend/package.json | 2 +- pnpm-lock.yaml | 94 ++++++----------------------------- 2 files changed, 17 insertions(+), 79 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index fe8c078a0..8564ca832 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -71,6 +71,7 @@ "is-svg": "4.3.2", "js-yaml": "4.1.0", "jsdom": "20.0.3", + "json5": "2.2.3", "jsonld": "8.2.0", "jsrsasign": "10.8.6", "koa": "2.14.2", @@ -185,7 +186,6 @@ "cross-env": "7.0.3", "eslint": "^8.44.0", "execa": "6.1.0", - "json5": "2.2.3", "json5-loader": "4.0.1", "mocha": "10.2.0", "pug": "3.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adead9c6f..540d94109 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -219,6 +219,9 @@ importers: jsdom: specifier: 20.0.3 version: 20.0.3 + json5: + specifier: 2.2.3 + version: 2.2.3 jsonld: specifier: 8.2.0 version: 8.2.0 @@ -563,9 +566,6 @@ importers: execa: specifier: 6.1.0 version: 6.1.0 - json5: - specifier: 2.2.3 - version: 2.2.3 json5-loader: specifier: 4.0.1 version: 4.0.1(webpack@5.88.1) @@ -595,7 +595,7 @@ importers: version: 5.1.6 webpack: specifier: ^5.88.1 - version: 5.88.1(@swc/core@1.3.68) + version: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) ws: specifier: 8.13.0 version: 8.13.0 @@ -780,7 +780,7 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b + version: github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -5138,7 +5138,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) transitivePeerDependencies: - debug dev: false @@ -5164,7 +5164,7 @@ packages: /axios@1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -6843,17 +6843,6 @@ packages: dependencies: ms: 2.0.0 - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: false - /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -6864,7 +6853,6 @@ packages: dependencies: ms: 2.1.3 supports-color: 8.1.1 - dev: true /debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} @@ -8377,16 +8365,6 @@ packages: tabbable: 6.2.0 dev: true - /follow-redirects@1.15.2: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -9355,7 +9333,7 @@ packages: engines: {node: '>= 4.5.0'} dependencies: agent-base: 4.3.0 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -11280,7 +11258,7 @@ packages: json5: 2.2.3 loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /json5@1.0.2: @@ -11535,7 +11513,7 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) koa-send: 5.0.1 transitivePeerDependencies: - supports-color @@ -12579,7 +12557,7 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) iconv-lite: 0.4.24 sax: 1.2.4 transitivePeerDependencies: @@ -15558,7 +15536,7 @@ packages: webpack: '>=2' dependencies: '@swc/core': 1.3.68 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /swiper@10.0.4: @@ -15677,7 +15655,7 @@ packages: schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.0 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /terser@5.19.0: @@ -16016,7 +15994,7 @@ packages: micromatch: 4.0.5 semver: 7.5.4 typescript: 5.1.6 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /ts-node@10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3): @@ -16933,46 +16911,6 @@ packages: engines: {node: '>=10.13.0'} dev: true - /webpack@5.88.1(@swc/core@1.3.68): - 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.9 - 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.68)(webpack@5.88.1) - watchpack: 2.4.0 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - /webpack@5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3): resolution: {integrity: sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==} engines: {node: '>=10.13.0'} @@ -17486,8 +17424,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b} + github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/d3c8c6a77d4362b3b3180099f1d2eac344ce245c} name: emojilib version: 3.0.10 dev: true From 9c245e603123c88683da0eb1bbbefbe5ce637acc Mon Sep 17 00:00:00 2001 From: DVD <zjdavid.2003@gmail.com> Date: Sun, 16 Jul 2023 21:54:42 +0800 Subject: [PATCH 154/162] Fix: Quicktime Video Play on Chrome --- packages/client/src/components/MkMedia.vue | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/MkMedia.vue b/packages/client/src/components/MkMedia.vue index 4c023f131..2cbb881f3 100644 --- a/packages/client/src/components/MkMedia.vue +++ b/packages/client/src/components/MkMedia.vue @@ -54,7 +54,7 @@ controls @contextmenu.stop > - <source :src="media.url" :type="media.type" /> + <source :src="media.url" :type="mediaType" /> </video> </VuePlyr> </template> @@ -80,7 +80,7 @@ </template> <script lang="ts" setup> -import { watch, ref } from "vue"; +import { watch, ref, computed } from "vue"; import VuePlyr from "vue-plyr"; import "vue-plyr/dist/vue-plyr.css"; import type * as misskey from "calckey-js"; @@ -107,6 +107,10 @@ const url = ? getStaticImageUrl(props.media.thumbnailUrl) : props.media.thumbnailUrl; +const mediaType = computed(() => { + return props.media.type === 'video/quicktime' ? 'video/mp4' : props.media.type; +}); + function captionPopup() { os.alert({ type: "info", From 90738efa67b79914bc970f6b178fc82bab893348 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sun, 16 Jul 2023 13:41:55 -0400 Subject: [PATCH 155/162] fix: more reliable not closing emoji picker on shift key --- .../client/src/components/MkEmojiPicker.vue | 4 +-- .../src/components/MkEmojiPickerDialog.vue | 31 +++---------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/packages/client/src/components/MkEmojiPicker.vue b/packages/client/src/components/MkEmojiPicker.vue index 09d61518d..2a797f56a 100644 --- a/packages/client/src/components/MkEmojiPicker.vue +++ b/packages/client/src/components/MkEmojiPicker.vue @@ -195,7 +195,7 @@ const props = withDefaults( ); const emit = defineEmits<{ - (ev: "chosen", v: string): void; + (ev: "chosen", v: string, ev: MouseEvent): void; }>(); const search = ref<HTMLInputElement>(); @@ -436,7 +436,7 @@ function chosen(emoji: any, ev?: MouseEvent) { } const key = getKey(emoji); - emit("chosen", key); + emit("chosen", key, ev); // 最近使った絵文字更新 if (!pinned.value.includes(key)) { diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index 28cc1d215..99afe9b6a 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -58,29 +58,16 @@ const emit = defineEmits<{ const modal = ref<InstanceType<typeof MkModal>>(); const picker = ref<InstanceType<typeof MkEmojiPicker>>(); -const isShiftKeyPressed = ref(false); -const keydownHandler = (e) => { - if (e.key === "Shift") { - isShiftKeyPressed.value = true; - } -}; - -const keyupHandler = (e) => { - if (e.key === "Shift") { - isShiftKeyPressed.value = false; - } -}; function checkForShift(ev?: MouseEvent) { - if (!isShiftKeyPressed.value) { - modal.value?.close(ev); - } + if (ev?.shiftKey) return; + modal.value?.close(ev); } -function chosen(emoji: any) { +function chosen(emoji: any, ev: MouseEvent) { emit("done", emoji); - checkForShift(); + checkForShift(ev); } function opening() { @@ -91,16 +78,6 @@ function opening() { } picker.value?.focus(); } - -onMounted(() => { - window.addEventListener("keydown", keydownHandler); - window.addEventListener("keyup", keyupHandler); -}); - -onBeforeUnmount(() => { - window.removeEventListener("keydown", keydownHandler); - window.removeEventListener("keyup", keyupHandler); -}); </script> <style lang="scss" scoped> From 2ac7a750ec44c5a42583c21892b04a3e816dfbd0 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 16 Jul 2023 13:57:38 -0700 Subject: [PATCH 156/162] dev79 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a30d85b3d..818b50ab3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "calckey", - "version": "14.0.0-dev78", + "version": "14.0.0-dev79", "codename": "aqua", "repository": { "type": "git", From 311b9beaa1ec814819e4ee40c452577edf216611 Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sun, 16 Jul 2023 17:24:34 -0400 Subject: [PATCH 157/162] fix: unable to scroll through reactions on mobile --- packages/client/src/components/MkNote.vue | 12 ++++----- packages/client/src/components/MkNoteSub.vue | 12 ++++----- .../client/src/components/MkQuoteButton.vue | 2 +- .../components/MkReactionsViewer.reaction.vue | 26 ++++++++++++------- .../src/components/MkReactionsViewer.vue | 7 ++++- .../client/src/components/MkRenoteButton.vue | 2 +- .../client/src/components/MkStarButton.vue | 2 +- .../src/components/MkStarButtonNoEmoji.vue | 2 +- 8 files changed, 36 insertions(+), 29 deletions(-) diff --git a/packages/client/src/components/MkNote.vue b/packages/client/src/components/MkNote.vue index 2f524c64a..4c71b2703 100644 --- a/packages/client/src/components/MkNote.vue +++ b/packages/client/src/components/MkNote.vue @@ -148,7 +148,7 @@ {{ appearNote.channel.name }}</MkA > </div> - <footer ref="footerEl" class="footer" @click.stop tabindex="-1"> + <footer ref="footerEl" class="footer" tabindex="-1"> <XReactionsViewer v-if="enableEmojiReactions" ref="reactionsViewer" @@ -157,7 +157,7 @@ <button v-tooltip.noDelay.bottom="i18n.ts.reply" class="button _button" - @click="reply()" + @click.stop="reply()" > <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> <template @@ -202,7 +202,7 @@ ref="reactButton" v-tooltip.noDelay.bottom="i18n.ts.reaction" class="button _button" - @click="react()" + @click.stop="react()" > <i class="ph-smiley ph-bold ph-lg"></i> </button> @@ -213,7 +213,7 @@ " ref="reactButton" class="button _button reacted" - @click="undoReact(appearNote)" + @click.stop="undoReact(appearNote)" v-tooltip.noDelay.bottom="i18n.ts.removeReaction" > <i class="ph-minus ph-bold ph-lg"></i> @@ -223,7 +223,7 @@ ref="menuButton" v-tooltip.noDelay.bottom="i18n.ts.more" class="button _button" - @click="menu()" + @click.stop="menu()" > <i class="ph-dots-three-outline ph-bold ph-lg"></i> </button> @@ -862,7 +862,6 @@ defineExpose({ z-index: 2; display: flex; flex-wrap: wrap; - pointer-events: none; // Allow clicking anything w/out pointer-events: all; to open post margin-top: 0.4em; > :deep(.button) { position: relative; @@ -876,7 +875,6 @@ defineExpose({ max-width: 3.5em; width: max-content; min-width: max-content; - pointer-events: all; height: auto; transition: opacity 0.2s; &::before { diff --git a/packages/client/src/components/MkNoteSub.vue b/packages/client/src/components/MkNoteSub.vue index 9b7f1f5f5..380fd67a7 100644 --- a/packages/client/src/components/MkNoteSub.vue +++ b/packages/client/src/components/MkNoteSub.vue @@ -56,7 +56,7 @@ </div> </div> </div> - <footer ref="footerEl" class="footer" @click.stop tabindex="-1"> + <footer ref="footerEl" class="footer" tabindex="-1"> <XReactionsViewer v-if="enableEmojiReactions" ref="reactionsViewer" @@ -65,7 +65,7 @@ <button v-tooltip.noDelay.bottom="i18n.ts.reply" class="button _button" - @click="reply()" + @click.stop="reply()" > <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> <template v-if="appearNote.repliesCount > 0"> @@ -107,7 +107,7 @@ ref="reactButton" v-tooltip.noDelay.bottom="i18n.ts.reaction" class="button _button" - @click="react()" + @click.stop="react()" > <i class="ph-smiley ph-bold ph-lg"></i> </button> @@ -118,7 +118,7 @@ " ref="reactButton" class="button _button reacted" - @click="undoReact(appearNote)" + @click.stop="undoReact(appearNote)" v-tooltip.noDelay.bottom="i18n.ts.removeReaction" > <i class="ph-minus ph-bold ph-lg"></i> @@ -128,7 +128,7 @@ ref="menuButton" v-tooltip.noDelay.bottom="i18n.ts.more" class="button _button" - @click="menu()" + @click.stop="menu()" > <i class="ph-dots-three-outline ph-bold ph-lg"></i> </button> @@ -470,7 +470,6 @@ function noteClick(e) { z-index: 2; display: flex; flex-wrap: wrap; - pointer-events: none; // Allow clicking anything w/out pointer-events: all; to open post > :deep(.button) { position: relative; @@ -484,7 +483,6 @@ function noteClick(e) { max-width: 3.5em; width: max-content; min-width: max-content; - pointer-events: all; height: auto; transition: opacity 0.2s; &::before { diff --git a/packages/client/src/components/MkQuoteButton.vue b/packages/client/src/components/MkQuoteButton.vue index 44e423ed5..95689df07 100644 --- a/packages/client/src/components/MkQuoteButton.vue +++ b/packages/client/src/components/MkQuoteButton.vue @@ -3,7 +3,7 @@ v-if="canRenote && $store.state.seperateRenoteQuote" v-tooltip.noDelay.bottom="i18n.ts.quote" class="eddddedb _button" - @click="quote()" + @click.stop="quote()" > <i class="ph-quotes ph-bold ph-lg"></i> </button> diff --git a/packages/client/src/components/MkReactionsViewer.reaction.vue b/packages/client/src/components/MkReactionsViewer.reaction.vue index b44afcca1..73a887826 100644 --- a/packages/client/src/components/MkReactionsViewer.reaction.vue +++ b/packages/client/src/components/MkReactionsViewer.reaction.vue @@ -9,7 +9,7 @@ canToggle, newlyAdded: !isInitial, }" - @click="toggleReaction()" + @click.stop="toggleReaction()" > <XReactionIcon class="icon" @@ -100,13 +100,20 @@ useTooltip( <style lang="scss" scoped> .hkzvhatu { + position: relative; display: inline-block; height: 32px; - margin: 2px; - padding: 0 6px; - border-radius: 4px; + margin-block: 2px; + padding: 0 8px; pointer-events: all; min-width: max-content; + &::before { + content: ""; + position: absolute; + inset: 0 2px; + border-radius: 4px; + z-index: -1; + } &.newlyAdded { animation: scaleInSmall 0.3s cubic-bezier(0, 0, 0, 1.2); :deep(.mk-emoji) { @@ -126,9 +133,10 @@ useTooltip( } } &.canToggle { - background: rgba(0, 0, 0, 0.05); - - &:hover { + &::before { + background: rgba(0, 0, 0, 0.05); + } + &:hover:not(.reacted)::before { background: rgba(0, 0, 0, 0.1); } } @@ -139,9 +147,7 @@ useTooltip( &.reacted { order: -1; - background: var(--accent); - - &:hover { + &::before { background: var(--accent); } diff --git a/packages/client/src/components/MkReactionsViewer.vue b/packages/client/src/components/MkReactionsViewer.vue index b60c53df6..2381b0a02 100644 --- a/packages/client/src/components/MkReactionsViewer.vue +++ b/packages/client/src/components/MkReactionsViewer.vue @@ -1,5 +1,5 @@ <template> - <div ref="reactionsEl" class="reactions-list tdflqwzn" :class="{ isMe }"> + <div ref="reactionsEl" class="reactions-list swiper-no-swiping tdflqwzn" :class="{ isMe }"> <XReaction v-for="(count, reaction) in note.reactions" :key="reaction" @@ -50,6 +50,11 @@ const isMe = computed(() => $i && $i.id === props.note.userId); transparent ); scrollbar-width: none; + pointer-events: none; + :deep(*) { + pointer-events: all; + } + &::-webkit-scrollbar { display: none; } diff --git a/packages/client/src/components/MkRenoteButton.vue b/packages/client/src/components/MkRenoteButton.vue index 16a8b9536..09138d7d6 100644 --- a/packages/client/src/components/MkRenoteButton.vue +++ b/packages/client/src/components/MkRenoteButton.vue @@ -5,7 +5,7 @@ v-tooltip.noDelay.bottom="i18n.ts.renote" class="button _button canRenote" :class="{ renoted: hasRenotedBefore }" - @click="renote(false, $event)" + @click.stop="renote(false, $event)" > <i class="ph-repeat ph-bold ph-lg"></i> <p v-if="count > 0 && !detailedView" class="count">{{ count }}</p> diff --git a/packages/client/src/components/MkStarButton.vue b/packages/client/src/components/MkStarButton.vue index ecfbf2e73..7af0c5aee 100644 --- a/packages/client/src/components/MkStarButton.vue +++ b/packages/client/src/components/MkStarButton.vue @@ -2,7 +2,7 @@ <button v-tooltip.noDelay.bottom="i18n.ts._gallery.like" class="button _button" - @click="star($event)" + @click.stop="star($event)" > <svg v-if="defaultStore.state.woozyMode === true" diff --git a/packages/client/src/components/MkStarButtonNoEmoji.vue b/packages/client/src/components/MkStarButtonNoEmoji.vue index 8123270c8..22326c483 100644 --- a/packages/client/src/components/MkStarButtonNoEmoji.vue +++ b/packages/client/src/components/MkStarButtonNoEmoji.vue @@ -4,7 +4,7 @@ class="button _button" :class="$style.root" ref="buttonRef" - @click="toggleStar($event)" + @click.stop="toggleStar($event)" > <span v-if="!reacted"> <i From 6ddb96a392cb5f4dc990ca064d8d81408a434f1c Mon Sep 17 00:00:00 2001 From: freeplay <freeplay@duck.com> Date: Sun, 16 Jul 2023 17:46:30 -0400 Subject: [PATCH 158/162] feat: add view on remote server to user profile dropdowns --- packages/client/src/scripts/get-user-menu.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index 48b97fed6..2750df65b 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -260,6 +260,15 @@ export function getUserMenu(user, router: Router = mainRouter) { to: `/my/messaging/${Acct.toString(user)}`, } : undefined, + user.host != null && user.url + ? { + type: "a", + icon: "ph-arrow-square-out ph-bold ph-lg", + text: i18n.ts.showOnRemote, + href: user.url, + target: "_blank", + + } : undefined, null, { icon: "ph-list-bullets ph-bold ph-lg", From d425c29347b63440ee554c4d9d2490fc53729bb6 Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 16 Jul 2023 15:32:32 -0700 Subject: [PATCH 159/162] refactor: :rotating_light: linting fix --- package.json | 2 +- .../1678426061773-tweak-varchar-length.js | 18 +- packages/backend/native-utils/package.json | 1 + .../src/model/repository/antenna.rs | 2 +- .../native-utils/src/model/schema/antenna.rs | 2 +- .../native-utils/src/model/schema/app.rs | 2 +- packages/backend/native-utils/tests/common.rs | 4 +- .../tests/model/repository/antenna.rs | 10 +- packages/backend/src/const.ts | 5 +- packages/backend/src/misc/download-url.ts | 4 +- packages/client/.eslintrc.json | 7 + packages/client/package.json | 10 +- .../client/src/components/MkAbuseReport.vue | 4 +- .../src/components/MkAbuseReportWindow.vue | 2 +- .../client/src/components/MkAnalogClock.vue | 40 +- .../client/src/components/MkAutocomplete.vue | 18 +- packages/client/src/components/MkButton.vue | 4 +- packages/client/src/components/MkCaptcha.vue | 8 +- .../client/src/components/MkChannelList.vue | 3 +- packages/client/src/components/MkChart.vue | 59 +- .../client/src/components/MkChatPreview.vue | 2 +- .../client/src/components/MkContextMenu.vue | 12 +- .../client/src/components/MkCropperDialog.vue | 10 +- packages/client/src/components/MkCwButton.vue | 2 +- .../src/components/MkDateSeparatedList.vue | 5 +- packages/client/src/components/MkDialog.vue | 16 +- packages/client/src/components/MkDonation.vue | 6 +- .../src/components/MkEmojiPickerDialog.vue | 1 - packages/client/src/components/MkMedia.vue | 4 +- .../client/src/components/MkNoteDetailed.vue | 6 +- packages/client/src/components/MkTab.vue | 2 +- packages/client/src/components/form/input.vue | 6 +- packages/client/src/components/form/radio.vue | 4 +- packages/client/src/components/form/range.vue | 6 +- .../client/src/components/form/select.vue | 12 +- .../client/src/components/form/suspense.vue | 3 +- .../client/src/components/form/switch.vue | 4 +- .../client/src/components/form/textarea.vue | 6 +- .../client/src/components/global/MkAcct.vue | 2 +- .../client/src/components/global/MkAd.vue | 2 +- .../client/src/components/global/MkAvatar.vue | 2 +- .../client/src/components/global/MkEmoji.vue | 2 +- .../global/MkMisskeyFlavoredMarkdown.vue | 4 +- .../src/components/global/MkPageHeader.vue | 20 +- .../client/src/components/global/MkSpacer.vue | 8 +- .../components/global/MkStickyContainer.vue | 9 +- .../client/src/components/global/MkTime.vue | 6 +- .../src/components/global/MkUserName.vue | 2 +- .../src/components/global/RouterView.vue | 14 +- packages/client/src/ui/deck.vue | 10 +- .../client/src/ui/deck/antenna-column.vue | 5 +- .../client/src/ui/deck/channel-column.vue | 5 +- packages/client/src/ui/deck/column-core.vue | 2 +- packages/client/src/ui/deck/column.vue | 26 +- packages/client/src/ui/deck/deck-store.ts | 4 +- packages/client/src/ui/deck/direct-column.vue | 2 +- packages/client/src/ui/deck/list-column.vue | 5 +- packages/client/src/ui/deck/main-column.vue | 10 +- .../client/src/ui/deck/mentions-column.vue | 2 +- .../src/ui/deck/notifications-column.vue | 2 +- packages/client/src/ui/deck/tl-column.vue | 9 +- .../client/src/ui/deck/widgets-column.vue | 2 +- packages/client/src/ui/universal.vue | 9 +- packages/client/src/ui/universal.widgets.vue | 4 +- packages/client/src/ui/visitor.vue | 2 +- packages/client/src/ui/visitor/a.vue | 2 +- packages/client/src/ui/visitor/b.vue | 13 +- packages/client/src/ui/visitor/kanban.vue | 2 +- packages/client/src/ui/zen.vue | 5 +- .../client/src/widgets/activity.chart.vue | 20 +- packages/client/src/widgets/activity.vue | 11 +- packages/client/src/widgets/aiscript.vue | 11 +- packages/client/src/widgets/button.vue | 11 +- packages/client/src/widgets/calendar.vue | 13 +- packages/client/src/widgets/clock.vue | 11 +- packages/client/src/widgets/digital-clock.vue | 11 +- packages/client/src/widgets/federation.vue | 11 +- .../client/src/widgets/instance-cloud.vue | 8 +- packages/client/src/widgets/job-queue.vue | 11 +- packages/client/src/widgets/memo.vue | 11 +- packages/client/src/widgets/notifications.vue | 11 +- packages/client/src/widgets/online-users.vue | 11 +- packages/client/src/widgets/photos.vue | 11 +- packages/client/src/widgets/post-form.vue | 11 +- packages/client/src/widgets/rss-ticker.vue | 11 +- packages/client/src/widgets/rss.vue | 11 +- packages/client/src/widgets/server-info.vue | 7 +- .../src/widgets/server-metric/cpu-mem.vue | 32 +- .../client/src/widgets/server-metric/cpu.vue | 2 +- .../src/widgets/server-metric/index.vue | 11 +- .../src/widgets/server-metric/meilisearch.vue | 12 +- .../client/src/widgets/server-metric/mem.vue | 10 +- .../client/src/widgets/server-metric/net.vue | 32 +- packages/client/src/widgets/slideshow.vue | 11 +- packages/client/src/widgets/timeline.vue | 11 +- packages/client/src/widgets/trends.vue | 11 +- packages/client/src/widgets/unix-clock.vue | 11 +- packages/client/src/widgets/user-list.vue | 15 +- packages/megalodon/package.json | 2 +- packages/megalodon/src/axios.d.ts | 2 +- packages/megalodon/src/cancel.ts | 16 +- packages/megalodon/src/converter.ts | 2 +- packages/megalodon/src/default.ts | 6 +- packages/megalodon/src/entity.ts | 2 +- packages/megalodon/src/filter_context.ts | 14 +- packages/megalodon/src/index.ts | 54 +- packages/megalodon/src/megalodon.ts | 2753 ++++---- packages/megalodon/src/misskey.ts | 5701 +++++++++-------- packages/megalodon/src/notification.ts | 20 +- packages/megalodon/src/oauth.ts | 204 +- packages/megalodon/src/parser.ts | 142 +- packages/megalodon/src/proxy_config.ts | 165 +- packages/megalodon/src/response.ts | 12 +- packages/sw/package.json | 2 +- pnpm-lock.yaml | 1269 +++- rome.json | 4 + 116 files changed, 6537 insertions(+), 4697 deletions(-) create mode 100644 packages/client/.eslintrc.json diff --git a/package.json b/package.json index 818b50ab3..d4460c878 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "gulp-replace": "1.1.4", "gulp-terser": "2.1.0", "install-peers": "^1.0.4", - "rome": "^12.1.3", + "rome": "^v12.1.3-nightly.f65b0d9", "start-server-and-test": "1.15.2", "typescript": "5.1.6" } diff --git a/packages/backend/migration/1678426061773-tweak-varchar-length.js b/packages/backend/migration/1678426061773-tweak-varchar-length.js index 883374599..00ddcaebe 100644 --- a/packages/backend/migration/1678426061773-tweak-varchar-length.js +++ b/packages/backend/migration/1678426061773-tweak-varchar-length.js @@ -1,10 +1,16 @@ export class tweakVarcharLength1678426061773 { - name = 'tweakVarcharLength1678426061773' + name = "tweakVarcharLength1678426061773"; - async up(queryRunner) { - await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "smtpUser" TYPE character varying(1024)`, undefined); - await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "smtpPass" TYPE character varying(1024)`, undefined); - } + async up(queryRunner) { + await queryRunner.query( + `ALTER TABLE "meta" ALTER COLUMN "smtpUser" TYPE character varying(1024)`, + undefined, + ); + await queryRunner.query( + `ALTER TABLE "meta" ALTER COLUMN "smtpPass" TYPE character varying(1024)`, + undefined, + ); + } - async down(queryRunner) {} + async down(queryRunner) {} } diff --git a/packages/backend/native-utils/package.json b/packages/backend/native-utils/package.json index 385330d77..962b4bc4c 100644 --- a/packages/backend/native-utils/package.json +++ b/packages/backend/native-utils/package.json @@ -43,6 +43,7 @@ "universal": "napi universal", "version": "napi version", "format": "cargo fmt --all", + "lint": "cargo clippy --fix", "cargo:test": "pnpm run cargo:unit && pnpm run cargo:integration", "cargo:unit": "cargo test unit_test && cargo test -F napi unit_test", "cargo:integration": "cargo test -F noarray int_test -- --test-threads=1" diff --git a/packages/backend/native-utils/src/model/repository/antenna.rs b/packages/backend/native-utils/src/model/repository/antenna.rs index 7c614b954..2b761173e 100644 --- a/packages/backend/native-utils/src/model/repository/antenna.rs +++ b/packages/backend/native-utils/src/model/repository/antenna.rs @@ -46,7 +46,7 @@ impl Repository<Antenna> for antenna::Model { src: self.src.try_into()?, user_list_id: self.user_list_id, user_group_id, - users: self.users.into(), + users: self.users, instances: self.instances.into(), case_sensitive: self.case_sensitive, notify: self.notify, diff --git a/packages/backend/native-utils/src/model/schema/antenna.rs b/packages/backend/native-utils/src/model/schema/antenna.rs index 4ec1e0794..da2c3061b 100644 --- a/packages/backend/native-utils/src/model/schema/antenna.rs +++ b/packages/backend/native-utils/src/model/schema/antenna.rs @@ -58,7 +58,7 @@ impl TryFrom<AntennaSrcEnum> for super::AntennaSrc { // ---- TODO: could be macro impl Schema<Self> for super::Antenna {} -pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(|| super::Antenna::validator()); +pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(super::Antenna::validator); // ---- cfg_if! { diff --git a/packages/backend/native-utils/src/model/schema/app.rs b/packages/backend/native-utils/src/model/schema/app.rs index 682b82ec0..9b5691154 100644 --- a/packages/backend/native-utils/src/model/schema/app.rs +++ b/packages/backend/native-utils/src/model/schema/app.rs @@ -91,7 +91,7 @@ pub enum AppPermission { impl Schema<Self> for App {} -pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(|| App::validator()); +pub static VALIDATOR: Lazy<JSONSchema> = Lazy::new(App::validator); #[cfg(test)] mod unit_test { diff --git a/packages/backend/native-utils/tests/common.rs b/packages/backend/native-utils/tests/common.rs index 186e862bd..b134319ca 100644 --- a/packages/backend/native-utils/tests/common.rs +++ b/packages/backend/native-utils/tests/common.rs @@ -148,8 +148,8 @@ async fn setup_model(db: &DbConn) { let user_model = entity::user::Model { id: user_id.to_owned(), created_at: Utc::now().into(), - username: name.to_lowercase().to_string(), - username_lower: name.to_lowercase().to_string(), + username: name.to_lowercase(), + username_lower: name.to_lowercase(), name: Some(name.to_string()), token: Some(gen_string(16)), is_admin: true, diff --git a/packages/backend/native-utils/tests/model/repository/antenna.rs b/packages/backend/native-utils/tests/model/repository/antenna.rs index 3bda2ca18..80eea6771 100644 --- a/packages/backend/native-utils/tests/model/repository/antenna.rs +++ b/packages/backend/native-utils/tests/model/repository/antenna.rs @@ -43,18 +43,16 @@ mod int_test { keywords: vec![ vec!["foo".to_string(), "bar".to_string()], vec!["foobar".to_string()], - ] - .into(), + ], exclude_keywords: vec![ vec!["abc".to_string()], vec!["def".to_string(), "ghi".to_string()], - ] - .into(), + ], src: schema::AntennaSrc::All, user_list_id: None, user_group_id: None, - users: vec![].into(), - instances: vec![].into(), + users: vec![], + instances: vec![], case_sensitive: true, notify: true, with_replies: false, diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 49f012c5e..2a955ee52 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,5 +1,8 @@ import config from "@/config/index.js"; -import { DB_MAX_NOTE_TEXT_LENGTH, DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; +import { + DB_MAX_NOTE_TEXT_LENGTH, + DB_MAX_IMAGE_COMMENT_LENGTH, +} from "@/misc/hard-limits.js"; export const MAX_NOTE_TEXT_LENGTH = Math.min( config.maxNoteLength ?? 3000, diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index b96871e72..e9975f348 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -21,10 +21,10 @@ export async function downloadUrl(url: string, path: string): Promise<void> { const maxSize = config.maxFileSize || 262144000; const req = got - .stream(url, { + .stream(url, { headers: { "User-Agent": config.userAgent, - "Host": new URL(url).hostname, + Host: new URL(url).hostname, }, timeout: { lookup: timeout, diff --git a/packages/client/.eslintrc.json b/packages/client/.eslintrc.json new file mode 100644 index 000000000..fd4718003 --- /dev/null +++ b/packages/client/.eslintrc.json @@ -0,0 +1,7 @@ +{ + "extends": ["@eslint-sets/vue3", "@eslint-sets/vue3-ts"], + "plugins": ["file-progress", "prettier"], + "rules": { + "file-progress/activate": 1 + } +} diff --git a/packages/client/package.json b/packages/client/package.json index 95fb9f9b2..3fe101b81 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -4,11 +4,14 @@ "scripts": { "watch": "pnpm vite build --watch --mode development", "build": "pnpm vite build", - "lint": "pnpm rome check \"src/**/*.{ts,vue}\"", - "format": "pnpm rome format * --write && pnpm prettier --write '**/*.{scss,vue}'" + "lint": "pnpm rome check **/*.ts --apply && pnpm run lint:vue", + "lint:vue": "pnpm paralint --ext .vue --fix '**/*.vue' --cache", + "format": "pnpm rome format * --write && pnpm prettier --write '**/*.{scss,vue}' --cache --cache-strategy metadata" }, "devDependencies": { "@discordapp/twemoji": "14.1.2", + "@eslint-sets/eslint-config-vue3": "^5.6.1", + "@eslint-sets/eslint-config-vue3-ts": "^3.3.0", "@phosphor-icons/web": "^2.0.3", "@rollup/plugin-alias": "3.1.9", "@rollup/plugin-json": "4.1.0", @@ -46,6 +49,8 @@ "date-fns": "2.30.0", "emojilib": "github:thatonecalculator/emojilib", "escape-regexp": "0.0.1", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-file-progress": "^1.3.0", "eventemitter3": "5.0.1", "fast-blurhash": "^1.1.2", "focus-trap": "^7.5.2", @@ -57,6 +62,7 @@ "katex": "0.16.8", "matter-js": "0.18.0", "mfm-js": "0.23.3", + "paralint": "^1.2.1", "photoswipe": "5.3.8", "prettier": "3.0.0", "prettier-plugin-vue": "1.1.6", diff --git a/packages/client/src/components/MkAbuseReport.vue b/packages/client/src/components/MkAbuseReport.vue index ccb85d722..f92d10ba7 100644 --- a/packages/client/src/components/MkAbuseReport.vue +++ b/packages/client/src/components/MkAbuseReport.vue @@ -80,11 +80,11 @@ const emit = defineEmits<{ (ev: "resolved", reportId: string): void; }>(); -let forward = $ref(props.report.forwarded); +const forward = $ref(props.report.forwarded); function resolve() { os.apiWithDialog("admin/resolve-abuse-user-report", { - forward: forward, + forward, reportId: props.report.id, }).then(() => { emit("resolved", props.report.id); diff --git a/packages/client/src/components/MkAbuseReportWindow.vue b/packages/client/src/components/MkAbuseReportWindow.vue index 6fdf3b9e0..fc80cd66f 100644 --- a/packages/client/src/components/MkAbuseReportWindow.vue +++ b/packages/client/src/components/MkAbuseReportWindow.vue @@ -41,7 +41,7 @@ <script setup lang="ts"> import { ref } from "vue"; -import * as Misskey from "calckey-js"; +import type * as Misskey from "calckey-js"; import XWindow from "@/components/MkWindow.vue"; import MkTextarea from "@/components/form/textarea.vue"; import MkButton from "@/components/MkButton.vue"; diff --git a/packages/client/src/components/MkAnalogClock.vue b/packages/client/src/components/MkAnalogClock.vue index 2c67d2dcd..13b662ac3 100644 --- a/packages/client/src/components/MkAnalogClock.vue +++ b/packages/client/src/components/MkAnalogClock.vue @@ -109,12 +109,12 @@ <script lang="ts" setup> import { - ref, computed, - onMounted, - onBeforeUnmount, - shallowRef, nextTick, + onBeforeUnmount, + onMounted, + ref, + shallowRef, } from "vue"; import tinycolor from "tinycolor2"; import { globalEvents } from "@/events.js"; @@ -173,21 +173,21 @@ const texts = computed(() => { return angles; }); -let enabled = true; -let majorGraduationColor = $ref<string>(); -//let minorGraduationColor = $ref<string>(); -let sHandColor = $ref<string>(); -let mHandColor = $ref<string>(); -let hHandColor = $ref<string>(); -let nowColor = $ref<string>(); -let h = $ref<number>(0); -let m = $ref<number>(0); -let s = $ref<number>(0); -let hAngle = $ref<number>(0); -let mAngle = $ref<number>(0); -let sAngle = $ref<number>(0); -let disableSAnimate = $ref(false); -let sOneRound = false; +let enabled = true, + majorGraduationColor = $ref<string>(), + // let minorGraduationColor = $ref<string>(); + sHandColor = $ref<string>(), + mHandColor = $ref<string>(), + hHandColor = $ref<string>(), + nowColor = $ref<string>(), + h = $ref<number>(0), + m = $ref<number>(0), + s = $ref<number>(0), + hAngle = $ref<number>(0), + mAngle = $ref<number>(0), + sAngle = $ref<number>(0), + disableSAnimate = $ref(false), + sOneRound = false; function tick() { const now = new Date(); @@ -230,7 +230,7 @@ function calcColors() { majorGraduationColor = dark ? "rgba(255, 255, 255, 0.3)" : "rgba(0, 0, 0, 0.3)"; - //minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'; + // minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'; sHandColor = dark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.3)"; mHandColor = tinycolor( computedStyle.getPropertyValue("--fg"), diff --git a/packages/client/src/components/MkAutocomplete.vue b/packages/client/src/components/MkAutocomplete.vue index e1a61f11f..3e234ddbc 100644 --- a/packages/client/src/components/MkAutocomplete.vue +++ b/packages/client/src/components/MkAutocomplete.vue @@ -85,11 +85,11 @@ <script lang="ts"> import { markRaw, - ref, - onUpdated, - onMounted, - onBeforeUnmount, nextTick, + onBeforeUnmount, + onMounted, + onUpdated, + ref, watch, } from "vue"; import contains from "@/scripts/contains"; @@ -99,17 +99,17 @@ import { acct } from "@/filters/user"; import * as os from "@/os"; import { MFM_TAGS } from "@/scripts/mfm-tags"; import { defaultStore } from "@/store"; -import { emojilist, addSkinTone } from "@/scripts/emojilist"; +import { addSkinTone, emojilist } from "@/scripts/emojilist"; import { instance } from "@/instance"; import { i18n } from "@/i18n"; -type EmojiDef = { +interface EmojiDef { emoji: string; name: string; aliasOf?: string; url?: string; isCustomEmoji?: boolean; -}; +} const lib = emojilist.filter((x) => x.category !== "flags"); @@ -140,7 +140,7 @@ for (const x of lib) { emjdb.sort((a, b) => a.name.length - b.name.length); -//#region Construct Emoji DB +// #region Construct Emoji DB const customEmojis = instance.emojis; const emojiDefinitions: EmojiDef[] = []; @@ -168,7 +168,7 @@ for (const x of customEmojis) { emojiDefinitions.sort((a, b) => a.name.length - b.name.length); const emojiDb = markRaw(emojiDefinitions.concat(emjdb)); -//#endregion +// #endregion export default { emojiDb, diff --git a/packages/client/src/components/MkButton.vue b/packages/client/src/components/MkButton.vue index ab0281908..3a6b8f321 100644 --- a/packages/client/src/components/MkButton.vue +++ b/packages/client/src/components/MkButton.vue @@ -49,8 +49,8 @@ const emit = defineEmits<{ (ev: "click", payload: MouseEvent): void; }>(); -let el = $ref<HTMLElement | null>(null); -let ripples = $ref<HTMLElement | null>(null); +const el = $ref<HTMLElement | null>(null); +const ripples = $ref<HTMLElement | null>(null); onMounted(() => { if (props.autofocus) { diff --git a/packages/client/src/components/MkCaptcha.vue b/packages/client/src/components/MkCaptcha.vue index 71d8c2996..146c512fb 100644 --- a/packages/client/src/components/MkCaptcha.vue +++ b/packages/client/src/components/MkCaptcha.vue @@ -6,11 +6,11 @@ </template> <script lang="ts" setup> -import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue"; +import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue"; import { defaultStore } from "@/store"; import { i18n } from "@/i18n"; -type Captcha = { +interface Captcha { render( container: string | Node, options: { @@ -31,7 +31,7 @@ type Captcha = { execute(id: string): void; reset(id?: string): void; getResponse(id: string): string; -}; +} type CaptchaProvider = "hcaptcha" | "recaptcha"; @@ -105,7 +105,7 @@ function requestRender() { captcha.value.render(captchaEl.value, { sitekey: props.sitekey, theme: defaultStore.state.darkMode ? "dark" : "light", - callback: callback, + callback, "expired-callback": callback, "error-callback": callback, }); diff --git a/packages/client/src/components/MkChannelList.vue b/packages/client/src/components/MkChannelList.vue index c5452cd12..0861bf5a8 100644 --- a/packages/client/src/components/MkChannelList.vue +++ b/packages/client/src/components/MkChannelList.vue @@ -24,7 +24,8 @@ <script lang="ts" setup> import MkChannelPreview from "@/components/MkChannelPreview.vue"; -import MkPagination, { Paging } from "@/components/MkPagination.vue"; +import type { Paging } from "@/components/MkPagination.vue"; +import MkPagination from "@/components/MkPagination.vue"; import { i18n } from "@/i18n"; const props = withDefaults( diff --git a/packages/client/src/components/MkChart.vue b/packages/client/src/components/MkChart.vue index fab89e0b0..fdb0245f5 100644 --- a/packages/client/src/components/MkChart.vue +++ b/packages/client/src/components/MkChart.vue @@ -8,30 +8,31 @@ </template> <script lang="ts" setup> -import { onMounted, ref, watch, PropType, onUnmounted } from "vue"; +import type { PropType } from "vue"; +import { onMounted, onUnmounted, ref, watch } from "vue"; import { - Chart, ArcElement, - LineElement, - BarElement, - PointElement, BarController, - LineController, + BarElement, CategoryScale, - LinearScale, - TimeScale, + Chart, + Filler, Legend, + LineController, + LineElement, + LinearScale, + PointElement, + SubTitle, + TimeScale, Title, Tooltip, - SubTitle, - Filler, } from "chart.js"; import "chartjs-adapter-date-fns"; import { enUS } from "date-fns/locale"; import zoomPlugin from "chartjs-plugin-zoom"; // https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114242002 // We can't use gradient because Vite throws a error. -//import gradient from 'chartjs-plugin-gradient'; +// import gradient from 'chartjs-plugin-gradient'; import * as os from "@/os"; import { defaultStore } from "@/store"; import { useChartTooltip } from "@/scripts/use-chart-tooltip"; @@ -92,7 +93,7 @@ Chart.register( SubTitle, Filler, zoomPlugin, - //gradient, + // gradient, ); const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b)); @@ -127,20 +128,20 @@ const getColor = (i) => { }; const now = new Date(); -let chartInstance: Chart = null; -let chartData: { - series: { - name: string; - type: "line" | "area"; - color?: string; - dashed?: boolean; - hidden?: boolean; - data: { - x: number; - y: number; +let chartInstance: Chart = null, + chartData: { + series: { + name: string; + type: "line" | "area"; + color?: string; + dashed?: boolean; + hidden?: boolean; + data: { + x: number; + y: number; + }[]; }[]; - }[]; -} = null; + } = null; const chartEl = ref<HTMLCanvasElement>(null); const fetching = ref(true); @@ -210,7 +211,7 @@ const render = () => { ? x.color : getColor(i) : alpha(x.color ? x.color : getColor(i), 0.1), - /*gradient: props.bar ? undefined : { + /* gradient: props.bar ? undefined : { backgroundColor: { axis: 'y', colors: { @@ -218,7 +219,7 @@ const render = () => { [maxes[i]]: alpha(x.color ? x.color : getColor(i), 0.2), }, }, - },*/ + }, */ barPercentage: 0.9, categoryPercentage: 0.9, fill: x.type === "area", @@ -271,7 +272,7 @@ const render = () => { }, ticks: { display: props.detailed, - //mirror: true, + // mirror: true, }, }, }, @@ -331,7 +332,7 @@ const render = () => { }, } : undefined, - //gradient, + // gradient, }, }, plugins: [ diff --git a/packages/client/src/components/MkChatPreview.vue b/packages/client/src/components/MkChatPreview.vue index 2d7e1296d..e857560e8 100644 --- a/packages/client/src/components/MkChatPreview.vue +++ b/packages/client/src/components/MkChatPreview.vue @@ -26,7 +26,7 @@ : message.user " :show-indicator="true" - disableLink + disable-link /> <header v-if="message.groupId"> <span class="name">{{ message.group.name }}</span> diff --git a/packages/client/src/components/MkContextMenu.vue b/packages/client/src/components/MkContextMenu.vue index d615b6352..a21547780 100644 --- a/packages/client/src/components/MkContextMenu.vue +++ b/packages/client/src/components/MkContextMenu.vue @@ -12,9 +12,9 @@ </template> <script lang="ts" setup> -import { onMounted, onBeforeUnmount } from "vue"; +import { onBeforeUnmount, onMounted } from "vue"; import MkMenu from "./MkMenu.vue"; -import { MenuItem } from "./types/menu.vue"; +import type { MenuItem } from "./types/menu.vue"; import contains from "@/scripts/contains"; import * as os from "@/os"; @@ -27,13 +27,13 @@ const emit = defineEmits<{ (ev: "closed"): void; }>(); -let rootEl = $ref<HTMLDivElement>(); +const rootEl = $ref<HTMLDivElement>(); -let zIndex = $ref<number>(os.claimZIndex("high")); +const zIndex = $ref<number>(os.claimZIndex("high")); onMounted(() => { - let left = props.ev.pageX + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 - let top = props.ev.pageY + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 + let left = props.ev.pageX + 1, // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 + top = props.ev.pageY + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 const width = rootEl.offsetWidth; const height = rootEl.offsetHeight; diff --git a/packages/client/src/components/MkCropperDialog.vue b/packages/client/src/components/MkCropperDialog.vue index 748132fbc..f67523841 100644 --- a/packages/client/src/components/MkCropperDialog.vue +++ b/packages/client/src/components/MkCropperDialog.vue @@ -37,7 +37,7 @@ <script lang="ts" setup> import { nextTick, onMounted } from "vue"; -import * as misskey from "calckey-js"; +import type * as misskey from "calckey-js"; import Cropper from "cropperjs"; import tinycolor from "tinycolor2"; import XModalWindow from "@/components/MkModalWindow.vue"; @@ -62,10 +62,10 @@ const props = defineProps<{ const imgUrl = `${url}/proxy/image.webp?${query({ url: props.file.url, })}`; -let dialogEl = $ref<InstanceType<typeof XModalWindow>>(); -let imgEl = $ref<HTMLImageElement>(); -let cropper: Cropper | null = null; -let loading = $ref(true); +const dialogEl = $ref<InstanceType<typeof XModalWindow>>(); +const imgEl = $ref<HTMLImageElement>(); +let cropper: Cropper | null = null, + loading = $ref(true); const ok = async () => { const promise = new Promise<misskey.entities.DriveFile>(async (res) => { diff --git a/packages/client/src/components/MkCwButton.vue b/packages/client/src/components/MkCwButton.vue index 4db39f1ac..8baa02af7 100644 --- a/packages/client/src/components/MkCwButton.vue +++ b/packages/client/src/components/MkCwButton.vue @@ -15,7 +15,7 @@ <script lang="ts" setup> import { computed, ref } from "vue"; import { length } from "stringz"; -import * as misskey from "calckey-js"; +import type * as misskey from "calckey-js"; import { concat } from "@/scripts/array"; import { i18n } from "@/i18n"; diff --git a/packages/client/src/components/MkDateSeparatedList.vue b/packages/client/src/components/MkDateSeparatedList.vue index ebb66ea1f..4958d8770 100644 --- a/packages/client/src/components/MkDateSeparatedList.vue +++ b/packages/client/src/components/MkDateSeparatedList.vue @@ -1,5 +1,6 @@ <script lang="ts"> -import { defineComponent, h, PropType, TransitionGroup } from "vue"; +import type { PropType } from "vue"; +import { TransitionGroup, defineComponent, h } from "vue"; import MkAd from "@/components/global/MkAd.vue"; import { i18n } from "@/i18n"; import { defaultStore } from "@/store"; @@ -51,7 +52,7 @@ export default defineComponent({ if (!slots || !slots.default) return; const el = slots.default({ - item: item, + item, })[0]; if (el.key == null && item.id) el.key = item.id; diff --git a/packages/client/src/components/MkDialog.vue b/packages/client/src/components/MkDialog.vue index 5a106a5b2..2f51d3b1b 100644 --- a/packages/client/src/components/MkDialog.vue +++ b/packages/client/src/components/MkDialog.vue @@ -57,17 +57,17 @@ <Mfm :text="text" /> </div> <MkInput - ref="inputEl" v-if="input && input.type !== 'paragraph'" + ref="inputEl" v-model="inputValue" autofocus :autocomplete="input.autocomplete" :type="input.type == 'search' ? 'search' : input.type || 'text'" :placeholder="input.placeholder || undefined" - @keydown="onInputKeydown" :style="{ width: input.type === 'search' ? '300px' : null, }" + @keydown="onInputKeydown" > <template v-if="input.type === 'password'" #prefix ><i class="ph-password ph-bold ph-lg"></i @@ -100,9 +100,9 @@ </template> <template v-if="input.type === 'search'" #suffix> <button + v-tooltip.noDelay="i18n.ts.filter" class="_buttonIcon" @click.stop="openSearchFilters" - v-tooltip.noDelay="i18n.ts.filter" > <i class="ph-funnel ph-bold"></i> </button> @@ -200,6 +200,7 @@ <script lang="ts" setup> import { onBeforeUnmount, onMounted, ref, shallowRef } from "vue"; +import * as Acct from "calckey-js/built/acct"; import MkModal from "@/components/MkModal.vue"; import MkButton from "@/components/MkButton.vue"; import MkInput from "@/components/form/input.vue"; @@ -207,18 +208,17 @@ import MkTextarea from "@/components/form/textarea.vue"; import MkSelect from "@/components/form/select.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; -import * as Acct from "calckey-js/built/acct"; -type Input = { +interface Input { type: HTMLInputElement["type"]; placeholder?: string | null; autocomplete?: string; default: string | number | null; minLength?: number; maxLength?: number; -}; +} -type Select = { +interface Select { items: { value: string; text: string; @@ -231,7 +231,7 @@ type Select = { }[]; }[]; default: string | null; -}; +} const props = withDefaults( defineProps<{ diff --git a/packages/client/src/components/MkDonation.vue b/packages/client/src/components/MkDonation.vue index 5dab6b614..4087526da 100644 --- a/packages/client/src/components/MkDonation.vue +++ b/packages/client/src/components/MkDonation.vue @@ -49,8 +49,8 @@ <button class="_button" :class="$style.close" - @click="close" :aria-label="i18n.t('close')" + @click="close" > <i class="ph-x ph-bold ph-lg"></i> </button> @@ -59,14 +59,14 @@ </template> <script lang="ts" setup> -import { ref, nextTick } from "vue"; +import { nextTick, ref } from "vue"; import MkButton from "@/components/MkButton.vue"; import { host } from "@/config"; import { i18n } from "@/i18n"; import * as os from "@/os"; import { instance } from "@/instance"; -let show = ref(false); +const show = ref(false); const emit = defineEmits<{ (ev: "closed"): void; diff --git a/packages/client/src/components/MkEmojiPickerDialog.vue b/packages/client/src/components/MkEmojiPickerDialog.vue index 99afe9b6a..c3212cd40 100644 --- a/packages/client/src/components/MkEmojiPickerDialog.vue +++ b/packages/client/src/components/MkEmojiPickerDialog.vue @@ -59,7 +59,6 @@ const emit = defineEmits<{ const modal = ref<InstanceType<typeof MkModal>>(); const picker = ref<InstanceType<typeof MkEmojiPicker>>(); - function checkForShift(ev?: MouseEvent) { if (ev?.shiftKey) return; modal.value?.close(ev); diff --git a/packages/client/src/components/MkMedia.vue b/packages/client/src/components/MkMedia.vue index 2cbb881f3..993eeb516 100644 --- a/packages/client/src/components/MkMedia.vue +++ b/packages/client/src/components/MkMedia.vue @@ -108,7 +108,9 @@ const url = : props.media.thumbnailUrl; const mediaType = computed(() => { - return props.media.type === 'video/quicktime' ? 'video/mp4' : props.media.type; + return props.media.type === "video/quicktime" + ? "video/mp4" + : props.media.type; }); function captionPopup() { diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue index 71c11350d..7b571d8b2 100644 --- a/packages/client/src/components/MkNoteDetailed.vue +++ b/packages/client/src/components/MkNoteDetailed.vue @@ -33,11 +33,7 @@ detailedView ></MkNote> - <MkTab - v-model="tab" - :style="'underline'" - @update:modelValue="loadTab" - > + <MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab"> <option value="replies"> <!-- <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> --> <span v-if="note.repliesCount > 0" class="count">{{ diff --git a/packages/client/src/components/MkTab.vue b/packages/client/src/components/MkTab.vue index bc5f20d4c..8e3108ecb 100644 --- a/packages/client/src/components/MkTab.vue +++ b/packages/client/src/components/MkTab.vue @@ -106,7 +106,7 @@ export default defineComponent({ ); padding-right: 90px !important; white-space: nowrap; - + &::-webkit-scrollbar { display: none; } diff --git a/packages/client/src/components/form/input.vue b/packages/client/src/components/form/input.vue index cb9aa46c7..f54e25fdc 100644 --- a/packages/client/src/components/form/input.vue +++ b/packages/client/src/components/form/input.vue @@ -47,13 +47,13 @@ <script lang="ts" setup> import { + computed, + nextTick, onMounted, onUnmounted, - nextTick, ref, - watch, - computed, toRefs, + watch, } from "vue"; import { debounce } from "throttle-debounce"; import MkButton from "@/components/MkButton.vue"; diff --git a/packages/client/src/components/form/radio.vue b/packages/client/src/components/form/radio.vue index d2b3c343b..31316fb85 100644 --- a/packages/client/src/components/form/radio.vue +++ b/packages/client/src/components/form/radio.vue @@ -4,7 +4,7 @@ type="radio" :disabled="disabled" :checked="checked" - v-on:change="(x) => toggle(x)" + @change="(x) => toggle(x)" /> <span class="button"> <span></span> @@ -26,7 +26,7 @@ const emit = defineEmits<{ (ev: "update:modelValue", value: any): void; }>(); -let checked = $computed(() => props.modelValue === props.value); +const checked = $computed(() => props.modelValue === props.value); function toggle(x) { if (props.disabled) return; diff --git a/packages/client/src/components/form/range.vue b/packages/client/src/components/form/range.vue index aeb1ee8a2..38ebe29e3 100644 --- a/packages/client/src/components/form/range.vue +++ b/packages/client/src/components/form/range.vue @@ -12,7 +12,7 @@ :list="id" :value="modelValue" :disabled="disabled" - v-on:change="(x) => onChange(x)" + @change="(x) => onChange(x)" @focus="tooltipShow" @blur="tooltipHide" @touchstart="tooltipShow" @@ -35,7 +35,7 @@ </template> <script lang="ts" setup> -import { ref, computed, defineAsyncComponent } from "vue"; +import { computed, defineAsyncComponent, ref } from "vue"; import * as os from "@/os"; const id = os.getUniqueId(); @@ -59,7 +59,7 @@ const props = withDefaults( ); const inputEl = ref<HTMLElement>(); -let inputVal = $ref(props.modelValue); +const inputVal = $ref(props.modelValue); const emit = defineEmits<{ (ev: "update:modelValue", value: number): void; diff --git a/packages/client/src/components/form/select.vue b/packages/client/src/components/form/select.vue index 06a8e40e0..08f0e47df 100644 --- a/packages/client/src/components/form/select.vue +++ b/packages/client/src/components/form/select.vue @@ -43,15 +43,15 @@ </template> <script lang="ts" setup> +import type { VNode } from "vue"; import { - onMounted, - nextTick, - ref, - watch, computed, + nextTick, + onMounted, + ref, toRefs, - VNode, useSlots, + watch, } from "vue"; import MkButton from "@/components/MkButton.vue"; import * as os from "@/os"; @@ -151,7 +151,7 @@ function show(ev: MouseEvent) { opening.value = true; const menu = []; - let options = slots.default!(); + const options = slots.default!(); const pushOption = (option: VNode) => { menu.push({ diff --git a/packages/client/src/components/form/suspense.vue b/packages/client/src/components/form/suspense.vue index e1aacb42b..2b06bcbbb 100644 --- a/packages/client/src/components/form/suspense.vue +++ b/packages/client/src/components/form/suspense.vue @@ -22,7 +22,8 @@ </template> <script lang="ts"> -import { defineComponent, PropType, ref, watch } from "vue"; +import type { PropType } from "vue"; +import { defineComponent, ref, watch } from "vue"; import MkButton from "@/components/MkButton.vue"; import { i18n } from "@/i18n"; diff --git a/packages/client/src/components/form/switch.vue b/packages/client/src/components/form/switch.vue index 511d472ea..2b7c7663c 100644 --- a/packages/client/src/components/form/switch.vue +++ b/packages/client/src/components/form/switch.vue @@ -4,7 +4,7 @@ type="checkbox" :checked="modelValue" :disabled="disabled" - v-on:change="(x) => toggle(x)" + @change="(x) => toggle(x)" /> <div class="button"> <div class="knob"></div> @@ -18,7 +18,7 @@ </template> <script lang="ts" setup> -import { Ref } from "vue"; +import type { Ref } from "vue"; const props = defineProps<{ modelValue: boolean | Ref<boolean>; diff --git a/packages/client/src/components/form/textarea.vue b/packages/client/src/components/form/textarea.vue index 459df36ad..a54f8830f 100644 --- a/packages/client/src/components/form/textarea.vue +++ b/packages/client/src/components/form/textarea.vue @@ -39,14 +39,14 @@ <script lang="ts"> import { + computed, defineComponent, + nextTick, onMounted, onUnmounted, - nextTick, ref, - watch, - computed, toRefs, + watch, } from "vue"; import { debounce } from "throttle-debounce"; import MkButton from "@/components/MkButton.vue"; diff --git a/packages/client/src/components/global/MkAcct.vue b/packages/client/src/components/global/MkAcct.vue index c77ad6a4e..27d3e7db7 100644 --- a/packages/client/src/components/global/MkAcct.vue +++ b/packages/client/src/components/global/MkAcct.vue @@ -10,7 +10,7 @@ </template> <script lang="ts" setup> -import * as misskey from "calckey-js"; +import type * as misskey from "calckey-js"; import { toUnicode } from "punycode/"; import { host as hostRaw } from "@/config"; diff --git a/packages/client/src/components/global/MkAd.vue b/packages/client/src/components/global/MkAd.vue index 89498c5dc..09012a032 100644 --- a/packages/client/src/components/global/MkAd.vue +++ b/packages/client/src/components/global/MkAd.vue @@ -1,7 +1,7 @@ <template> <div - v-if="chosen && chosen.length > 0 && defaultStore.state.showAds" v-for="chosenItem in chosen" + v-if="chosen && chosen.length > 0 && defaultStore.state.showAds" class="qiivuoyo" > <div v-if="!showMenu" class="main" :class="chosenItem.place"> diff --git a/packages/client/src/components/global/MkAvatar.vue b/packages/client/src/components/global/MkAvatar.vue index 9340b84e9..308d77215 100644 --- a/packages/client/src/components/global/MkAvatar.vue +++ b/packages/client/src/components/global/MkAvatar.vue @@ -37,7 +37,7 @@ <script lang="ts" setup> import { onMounted, watch } from "vue"; -import * as misskey from "calckey-js"; +import type * as misskey from "calckey-js"; import { getStaticImageUrl } from "@/scripts/get-static-image-url"; import { extractAvgColorFromBlurhash } from "@/scripts/extract-avg-color-from-blurhash"; import { acct, userPage } from "@/filters/user"; diff --git a/packages/client/src/components/global/MkEmoji.vue b/packages/client/src/components/global/MkEmoji.vue index 5da567a0f..ad9ae12e4 100644 --- a/packages/client/src/components/global/MkEmoji.vue +++ b/packages/client/src/components/global/MkEmoji.vue @@ -22,7 +22,7 @@ <script lang="ts" setup> import { computed, ref, watch } from "vue"; -import { CustomEmoji } from "calckey-js/built/entities"; +import type { CustomEmoji } from "calckey-js/built/entities"; import { getStaticImageUrl } from "@/scripts/get-static-image-url"; import { char2filePath } from "@/scripts/twemoji-base"; import { defaultStore } from "@/store"; diff --git a/packages/client/src/components/global/MkMisskeyFlavoredMarkdown.vue b/packages/client/src/components/global/MkMisskeyFlavoredMarkdown.vue index 91966f9fb..4305f4782 100644 --- a/packages/client/src/components/global/MkMisskeyFlavoredMarkdown.vue +++ b/packages/client/src/components/global/MkMisskeyFlavoredMarkdown.vue @@ -4,8 +4,8 @@ :plain="plain" :nowrap="nowrap" :author="author" - :customEmojis="customEmojis" - :isNote="isNote" + :custom-emojis="customEmojis" + :is-note="isNote" class="mfm-object" :class="{ nowrap, diff --git a/packages/client/src/components/global/MkPageHeader.vue b/packages/client/src/components/global/MkPageHeader.vue index cd24c97fc..7faec6882 100644 --- a/packages/client/src/components/global/MkPageHeader.vue +++ b/packages/client/src/components/global/MkPageHeader.vue @@ -11,10 +11,10 @@ <div class="buttons"> <button v-if="displayBackButton" + v-tooltip.noDelay="i18n.ts.goBack" class="_buttonIcon button icon backButton" @click.stop="goBack()" @touchstart="preventDrag" - v-tooltip.noDelay="i18n.ts.goBack" > <i class="ph-caret-left ph-bold ph-lg"></i> </button> @@ -23,7 +23,7 @@ class="avatar button" :user="$i" :disable-preview="true" - disableLink + disable-link @click.stop="openAccountMenu" /> </div> @@ -68,8 +68,8 @@ </div> <template v-if="metadata"> <nav - ref="tabsEl" v-if="hasTabs" + ref="tabsEl" class="tabs" :class="{ collapse: hasTabs && tabs.length > 3 }" > @@ -123,14 +123,14 @@ <script lang="ts" setup> import { computed, + inject, + nextTick, onMounted, onUnmounted, - ref, - inject, - watch, - shallowReactive, - nextTick, reactive, + ref, + shallowReactive, + watch, } from "vue"; import MkFollowButton from "@/components/MkFollowButton.vue"; import { popupMenu } from "@/os"; @@ -140,13 +140,13 @@ import { injectPageMetadata } from "@/scripts/page-metadata"; import { $i, openAccountMenu as openAccountMenu_ } from "@/account"; import { i18n } from "@/i18n"; -type Tab = { +interface Tab { key?: string | null; title: string; icon?: string; iconOnly?: boolean; onClick?: (ev: MouseEvent) => void; -}; +} const props = defineProps<{ tabs?: Tab[]; diff --git a/packages/client/src/components/global/MkSpacer.vue b/packages/client/src/components/global/MkSpacer.vue index 1fd8281c5..f5054bfbc 100644 --- a/packages/client/src/components/global/MkSpacer.vue +++ b/packages/client/src/components/global/MkSpacer.vue @@ -24,10 +24,10 @@ const props = withDefaults( }, ); -let ro: ResizeObserver; -let root = $ref<HTMLElement>(); -let content = $ref<HTMLElement>(); -let margin = $ref(0); +let ro: ResizeObserver, + root = $ref<HTMLElement>(), + content = $ref<HTMLElement>(), + margin = $ref(0); const shouldSpacerMin = inject("shouldSpacerMin", false); const adjust = (rect: { width: number; height: number }) => { diff --git a/packages/client/src/components/global/MkStickyContainer.vue b/packages/client/src/components/global/MkStickyContainer.vue index 8826fe1f9..94fa2752e 100644 --- a/packages/client/src/components/global/MkStickyContainer.vue +++ b/packages/client/src/components/global/MkStickyContainer.vue @@ -11,19 +11,20 @@ <script lang="ts"> // なんか動かない -//const CURRENT_STICKY_TOP = Symbol('CURRENT_STICKY_TOP'); +// const CURRENT_STICKY_TOP = Symbol('CURRENT_STICKY_TOP'); const CURRENT_STICKY_TOP = "CURRENT_STICKY_TOP"; </script> <script lang="ts" setup> -import { onMounted, onUnmounted, provide, inject, Ref, ref, watch } from "vue"; +import type { Ref } from "vue"; +import { inject, onMounted, onUnmounted, provide, ref, watch } from "vue"; const rootEl = $ref<HTMLElement>(); const headerEl = $ref<HTMLElement>(); const bodyEl = $ref<HTMLElement>(); -let headerHeight = $ref<string | undefined>(); -let childStickyTop = $ref(0); +let headerHeight = $ref<string | undefined>(), + childStickyTop = $ref(0); const parentStickyTop = inject<Ref<number>>(CURRENT_STICKY_TOP, ref(0)); provide(CURRENT_STICKY_TOP, $$(childStickyTop)); diff --git a/packages/client/src/components/global/MkTime.vue b/packages/client/src/components/global/MkTime.vue index 9c2002c9b..a8cfcee47 100644 --- a/packages/client/src/components/global/MkTime.vue +++ b/packages/client/src/components/global/MkTime.vue @@ -42,7 +42,7 @@ const relative = $computed<string>(() => { if (props.mode === "absolute") return ""; // absoluteではrelativeを使わないので計算しない if (invalid) return i18n.ts._ago.invalid; - const ago = (now - _time) / 1000; /*ms*/ + const ago = (now - _time) / 1000; /* ms */ return ago >= 31536000 ? i18n.t("_ago.yearsAgo", { n: Math.round(ago / 31536000).toString() }) : ago >= 2592000 @@ -66,11 +66,11 @@ let tickId: number; function tick() { const _now = new Date().getTime(); - const agoPrev = (now - _time) / 1000; /*ms*/ // 現状のinterval + const agoPrev = (now - _time) / 1000; /* ms */ // 現状のinterval now = _now; - const ago = (now - _time) / 1000; /*ms*/ // 次のinterval + const ago = (now - _time) / 1000; /* ms */ // 次のinterval const prev = agoPrev < 60 ? 10000 : agoPrev < 3600 ? 60000 : 180000; const next = ago < 60 ? 10000 : ago < 3600 ? 60000 : 180000; diff --git a/packages/client/src/components/global/MkUserName.vue b/packages/client/src/components/global/MkUserName.vue index 3ece1c981..66a54dbd0 100644 --- a/packages/client/src/components/global/MkUserName.vue +++ b/packages/client/src/components/global/MkUserName.vue @@ -10,7 +10,7 @@ <script lang="ts" setup> import {} from "vue"; -import * as misskey from "calckey-js"; +import type * as misskey from "calckey-js"; const props = withDefaults( defineProps<{ diff --git a/packages/client/src/components/global/RouterView.vue b/packages/client/src/components/global/RouterView.vue index f8ad22f28..2073c3a55 100644 --- a/packages/client/src/components/global/RouterView.vue +++ b/packages/client/src/components/global/RouterView.vue @@ -5,8 +5,8 @@ :is="currentPageComponent" :key="key" v-bind="Object.fromEntries(currentPageProps)" - tabindex="-1" v-focus + tabindex="-1" style="outline: none" /> @@ -27,7 +27,7 @@ import { provide, watch, } from "vue"; -import { Resolved, Router } from "@/nirax"; +import type { Resolved, Router } from "@/nirax"; import { defaultStore } from "@/store"; const props = defineProps<{ @@ -56,11 +56,11 @@ function resolveNested(current: Resolved, d = 0): Resolved | null { } const current = resolveNested(router.current)!; -let currentPageComponent = $shallowRef(current.route.component); -let currentPageProps = $ref(current.props); -let key = $ref( - current.route.path + JSON.stringify(Object.fromEntries(current.props)), -); +let currentPageComponent = $shallowRef(current.route.component), + currentPageProps = $ref(current.props), + key = $ref( + current.route.path + JSON.stringify(Object.fromEntries(current.props)), + ); function onChange({ resolved, key: newKey }) { const current = resolveNested(resolved); diff --git a/packages/client/src/ui/deck.vue b/packages/client/src/ui/deck.vue index 36914fbbe..6fdcfb28d 100644 --- a/packages/client/src/ui/deck.vue +++ b/packages/client/src/ui/deck.vue @@ -193,12 +193,12 @@ import { import { v4 as uuid } from "uuid"; import XCommon from "./_common_/common.vue"; import { - deckStore, addColumn as addColumnToStore, - loadDeck, - getProfiles, - renameProfile as renameProfile_, + deckStore, deleteProfile as deleteProfile_, + getProfiles, + loadDeck, + renameProfile as renameProfile_, } from "./deck/deck-store"; import DeckColumnCore from "@/ui/deck/column-core.vue"; import XSidebar from "@/ui/_common_/navbar.vue"; @@ -253,7 +253,7 @@ function showSettings() { os.pageWindow("/settings/deck"); } -let columnsEl = $ref<HTMLElement>(); +const columnsEl = $ref<HTMLElement>(); const addColumn = async (ev) => { const columns = [ diff --git a/packages/client/src/ui/deck/antenna-column.vue b/packages/client/src/ui/deck/antenna-column.vue index 958a80724..8e3001738 100644 --- a/packages/client/src/ui/deck/antenna-column.vue +++ b/packages/client/src/ui/deck/antenna-column.vue @@ -23,7 +23,8 @@ <script lang="ts" setup> import { onMounted } from "vue"; import XColumn from "./column.vue"; -import { updateColumn, Column } from "./deck-store"; +import type { Column } from "./deck-store"; +import { updateColumn } from "./deck-store"; import XTimeline from "@/components/MkTimeline.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; @@ -38,7 +39,7 @@ const emit = defineEmits<{ (ev: "parent-focus", direction: "up" | "down" | "left" | "right"): void; }>(); -let timeline = $ref<InstanceType<typeof XTimeline>>(); +const timeline = $ref<InstanceType<typeof XTimeline>>(); onMounted(() => { if (props.column.antennaId == null) { diff --git a/packages/client/src/ui/deck/channel-column.vue b/packages/client/src/ui/deck/channel-column.vue index b6f143381..e53290d97 100644 --- a/packages/client/src/ui/deck/channel-column.vue +++ b/packages/client/src/ui/deck/channel-column.vue @@ -23,7 +23,8 @@ <script lang="ts" setup> import {} from "vue"; import XColumn from "./column.vue"; -import { updateColumn, Column } from "./deck-store"; +import type { Column } from "./deck-store"; +import { updateColumn } from "./deck-store"; import XTimeline from "@/components/MkTimeline.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; @@ -38,7 +39,7 @@ const emit = defineEmits<{ (ev: "parent-focus", direction: "up" | "down" | "left" | "right"): void; }>(); -let timeline = $ref<InstanceType<typeof XTimeline>>(); +const timeline = $ref<InstanceType<typeof XTimeline>>(); if (props.column.channelId == null) { setChannel(); diff --git a/packages/client/src/ui/deck/column-core.vue b/packages/client/src/ui/deck/column-core.vue index 23a7683a5..4c3c93734 100644 --- a/packages/client/src/ui/deck/column-core.vue +++ b/packages/client/src/ui/deck/column-core.vue @@ -68,7 +68,7 @@ import XWidgetsColumn from "./widgets-column.vue"; import XMentionsColumn from "./mentions-column.vue"; import XDirectColumn from "./direct-column.vue"; import XChannelColumn from "./channel-column.vue"; -import { Column } from "./deck-store"; +import type { Column } from "./deck-store"; defineProps<{ column?: Column; diff --git a/packages/client/src/ui/deck/column.vue b/packages/client/src/ui/deck/column.vue index e57a2a3c2..d9262d149 100644 --- a/packages/client/src/ui/deck/column.vue +++ b/packages/client/src/ui/deck/column.vue @@ -56,23 +56,23 @@ </template> <script lang="ts" setup> -import { onBeforeUnmount, onMounted, provide, Ref, watch } from "vue"; +import { Ref, onBeforeUnmount, onMounted, provide, watch } from "vue"; +import type { Column } from "./deck-store"; import { - updateColumn, + deckStore, + popRightColumn, + removeColumn, + stackLeftColumn, + swapColumn, + swapDownColumn, swapLeftColumn, swapRightColumn, swapUpColumn, - swapDownColumn, - stackLeftColumn, - popRightColumn, - removeColumn, - swapColumn, - Column, - deckStore, + updateColumn, } from "./deck-store"; import * as os from "@/os"; import { i18n } from "@/i18n"; -import { MenuItem } from "@/types/menu"; +import type { MenuItem } from "@/types/menu"; provide("shouldHeaderThin", true); provide("shouldOmitHeaderTitle", true); @@ -99,15 +99,15 @@ const emit = defineEmits<{ (ev: "headerWheel", ctx: WheelEvent): void; }>(); -let body = $ref<HTMLDivElement>(); +const body = $ref<HTMLDivElement>(); let dragging = $ref(false); watch($$(dragging), (v) => os.deckGlobalEvents.emit(v ? "column.dragStart" : "column.dragEnd"), ); -let draghover = $ref(false); -let dropready = $ref(false); +let draghover = $ref(false), + dropready = $ref(false); const isMainColumn = $computed(() => props.column.type === "main"); const active = $computed(() => props.column.active !== false); diff --git a/packages/client/src/ui/deck/deck-store.ts b/packages/client/src/ui/deck/deck-store.ts index a6db02ac5..8f25d3794 100644 --- a/packages/client/src/ui/deck/deck-store.ts +++ b/packages/client/src/ui/deck/deck-store.ts @@ -20,6 +20,7 @@ export type Column = { | "notifications" | "tl" | "antenna" + | "channel" | "list" | "mentions" | "direct"; @@ -29,9 +30,10 @@ export type Column = { active?: boolean; flexible?: boolean; antennaId?: string; + channelId?: string; listId?: string; includingTypes?: typeof notificationTypes[number][]; - tl?: "home" | "local" | "social" | "global"; + tl?: "home" | "local" | "social" | "recommended" | "global"; }; export const deckStore = markRaw( diff --git a/packages/client/src/ui/deck/direct-column.vue b/packages/client/src/ui/deck/direct-column.vue index 67ebca16f..5973cbe37 100644 --- a/packages/client/src/ui/deck/direct-column.vue +++ b/packages/client/src/ui/deck/direct-column.vue @@ -19,8 +19,8 @@ <script lang="ts" setup> import {} from "vue"; import XColumn from "./column.vue"; +import type { Column } from "./deck-store"; import XNotes from "@/components/MkNotes.vue"; -import { Column } from "./deck-store"; defineProps<{ column: Column; diff --git a/packages/client/src/ui/deck/list-column.vue b/packages/client/src/ui/deck/list-column.vue index 82bf58f85..110258f0e 100644 --- a/packages/client/src/ui/deck/list-column.vue +++ b/packages/client/src/ui/deck/list-column.vue @@ -23,7 +23,8 @@ <script lang="ts" setup> import {} from "vue"; import XColumn from "./column.vue"; -import { updateColumn, Column } from "./deck-store"; +import type { Column } from "./deck-store"; +import { updateColumn } from "./deck-store"; import XTimeline from "@/components/MkTimeline.vue"; import * as os from "@/os"; import { i18n } from "@/i18n"; @@ -38,7 +39,7 @@ const emit = defineEmits<{ (ev: "parent-focus", direction: "up" | "down" | "left" | "right"): void; }>(); -let timeline = $ref<InstanceType<typeof XTimeline>>(); +const timeline = $ref<InstanceType<typeof XTimeline>>(); if (props.column.listId == null) { setList(); diff --git a/packages/client/src/ui/deck/main-column.vue b/packages/client/src/ui/deck/main-column.vue index 3cb7343b3..b284f9073 100644 --- a/packages/client/src/ui/deck/main-column.vue +++ b/packages/client/src/ui/deck/main-column.vue @@ -20,14 +20,16 @@ </template> <script lang="ts" setup> -import { ComputedRef, provide } from "vue"; +import type { ComputedRef } from "vue"; +import { provide } from "vue"; import XColumn from "./column.vue"; -import { deckStore, Column } from "@/ui/deck/deck-store"; +import type { Column } from "@/ui/deck/deck-store"; +import { deckStore } from "@/ui/deck/deck-store"; import * as os from "@/os"; import { i18n } from "@/i18n"; import { mainRouter } from "@/router"; +import type { PageMetadata } from "@/scripts/page-metadata"; import { - PageMetadata, provideMetadataReceiver, setPageMetadata, } from "@/scripts/page-metadata"; @@ -67,7 +69,7 @@ function onContextmenu(ev: MouseEvent) { ["INPUT", "TEXTAREA", "IMG", "VIDEO", "CANVAS"].includes( (ev.target as HTMLElement).tagName, ) || - (ev.target as HTMLElement).attributes["contenteditable"] + (ev.target as HTMLElement).attributes.contenteditable ) return; if (window.getSelection()?.toString() !== "") return; diff --git a/packages/client/src/ui/deck/mentions-column.vue b/packages/client/src/ui/deck/mentions-column.vue index 83eff7297..08e11dd21 100644 --- a/packages/client/src/ui/deck/mentions-column.vue +++ b/packages/client/src/ui/deck/mentions-column.vue @@ -16,8 +16,8 @@ <script lang="ts" setup> import {} from "vue"; import XColumn from "./column.vue"; +import type { Column } from "./deck-store"; import XNotes from "@/components/MkNotes.vue"; -import { Column } from "./deck-store"; defineProps<{ column: Column; diff --git a/packages/client/src/ui/deck/notifications-column.vue b/packages/client/src/ui/deck/notifications-column.vue index 9c3c0eb67..37cbe30a7 100644 --- a/packages/client/src/ui/deck/notifications-column.vue +++ b/packages/client/src/ui/deck/notifications-column.vue @@ -44,7 +44,7 @@ function func(): void { done: async (res) => { const { includingTypes } = res; updateColumn(props.column.id, { - includingTypes: includingTypes, + includingTypes, }); }, }, diff --git a/packages/client/src/ui/deck/tl-column.vue b/packages/client/src/ui/deck/tl-column.vue index 7e801dc99..c419b0469 100644 --- a/packages/client/src/ui/deck/tl-column.vue +++ b/packages/client/src/ui/deck/tl-column.vue @@ -46,7 +46,8 @@ <script lang="ts" setup> import { onMounted } from "vue"; import XColumn from "./column.vue"; -import { removeColumn, updateColumn, Column } from "./deck-store"; +import type { Column } from "./deck-store"; +import { removeColumn, updateColumn } from "./deck-store"; import XTimeline from "@/components/MkTimeline.vue"; import * as os from "@/os"; import { $i } from "@/account"; @@ -63,9 +64,9 @@ const emit = defineEmits<{ (ev: "parent-focus", direction: "up" | "down" | "left" | "right"): void; }>(); -let disabled = $ref(false); -let indicated = $ref(false); -let columnActive = $ref(true); +let disabled = $ref(false), + indicated = $ref(false), + columnActive = $ref(true); onMounted(() => { if (props.column.tl == null) { diff --git a/packages/client/src/ui/deck/widgets-column.vue b/packages/client/src/ui/deck/widgets-column.vue index 8bfd40cf4..6f4090a9e 100644 --- a/packages/client/src/ui/deck/widgets-column.vue +++ b/packages/client/src/ui/deck/widgets-column.vue @@ -34,9 +34,9 @@ <script lang="ts" setup> import {} from "vue"; import XColumn from "./column.vue"; +import type { Column } from "./deck-store"; import { addColumnWidget, - Column, removeColumnWidget, setColumnWidgets, updateColumnWidget, diff --git a/packages/client/src/ui/universal.vue b/packages/client/src/ui/universal.vue index dc4cba684..acbcd5153 100644 --- a/packages/client/src/ui/universal.vue +++ b/packages/client/src/ui/universal.vue @@ -169,10 +169,10 @@ </template> <script lang="ts" setup> -import { defineAsyncComponent, provide, onMounted, computed, ref } from "vue"; -import XCommon from "./_common_/common.vue"; +import { computed, defineAsyncComponent, onMounted, provide, ref } from "vue"; import * as Acct from "calckey-js/built/acct"; import type { ComputedRef } from "vue"; +import XCommon from "./_common_/common.vue"; import type { PageMetadata } from "@/scripts/page-metadata"; import { instanceName, ui } from "@/config"; import XDrawerMenu from "@/ui/_common_/navbar-for-mobile.vue"; @@ -232,7 +232,7 @@ const menuIndicated = computed(() => { }); function updateButtonState(): void { - let routerState = window.location.pathname; + const routerState = window.location.pathname; if (routerState === "/") { buttonAnimIndex.value = 0; return; @@ -246,7 +246,6 @@ function updateButtonState(): void { return; } buttonAnimIndex.value = 3; - return; } updateButtonState(); @@ -358,7 +357,7 @@ const onContextmenu = (ev: MouseEvent) => { ["INPUT", "TEXTAREA", "IMG", "VIDEO", "CANVAS"].includes( ev.target.tagName, ) || - ev.target.attributes["contenteditable"] + ev.target.attributes.contenteditable ) return; if (window.getSelection()?.toString() !== "") return; diff --git a/packages/client/src/ui/universal.widgets.vue b/packages/client/src/ui/universal.widgets.vue index 612453d7b..dc6257cc3 100644 --- a/packages/client/src/ui/universal.widgets.vue +++ b/packages/client/src/ui/universal.widgets.vue @@ -39,8 +39,8 @@ const emit = defineEmits<{ (ev: "mounted", el: Element): void; }>(); -let editMode = $ref(false); -let rootEl = $ref<HTMLDivElement>(); +const editMode = $ref(false); +const rootEl = $ref<HTMLDivElement>(); onMounted(() => { emit("mounted", rootEl); diff --git a/packages/client/src/ui/visitor.vue b/packages/client/src/ui/visitor.vue index a00813415..9b602b5b0 100644 --- a/packages/client/src/ui/visitor.vue +++ b/packages/client/src/ui/visitor.vue @@ -4,7 +4,7 @@ </template> <script lang="ts"> -import { defineComponent, defineAsyncComponent } from "vue"; +import { defineAsyncComponent, defineComponent } from "vue"; import DesignA from "./visitor/a.vue"; import DesignB from "./visitor/b.vue"; import XCommon from "./_common_/common.vue"; diff --git a/packages/client/src/ui/visitor/a.vue b/packages/client/src/ui/visitor/a.vue index 8996ab836..5e7594547 100644 --- a/packages/client/src/ui/visitor/a.vue +++ b/packages/client/src/ui/visitor/a.vue @@ -74,7 +74,7 @@ </template> <script lang="ts"> -import { defineComponent, defineAsyncComponent } from "vue"; +import { defineAsyncComponent, defineComponent } from "vue"; import XHeader from "./header.vue"; import { host, instanceName } from "@/config"; import { search } from "@/scripts/search"; diff --git a/packages/client/src/ui/visitor/b.vue b/packages/client/src/ui/visitor/b.vue index c3d5ae29f..c05f1c2ae 100644 --- a/packages/client/src/ui/visitor/b.vue +++ b/packages/client/src/ui/visitor/b.vue @@ -71,7 +71,8 @@ </template> <script lang="ts" setup> -import { ComputedRef, onMounted, provide } from "vue"; +import type { ComputedRef } from "vue"; +import { onMounted, provide } from "vue"; import XHeader from "./header.vue"; import XKanban from "./kanban.vue"; import { host, instanceName } from "@/config"; @@ -84,8 +85,8 @@ import XSignupDialog from "@/components/MkSignupDialog.vue"; import MkButton from "@/components/MkButton.vue"; import { ColdDeviceStorage, defaultStore } from "@/store"; import { mainRouter } from "@/router"; +import type { PageMetadata } from "@/scripts/page-metadata"; import { - PageMetadata, provideMetadataReceiver, setPageMetadata, } from "@/scripts/page-metadata"; @@ -111,10 +112,10 @@ const isTimelineAvailable = !instance.disableLocalTimeline || !instance.disableRecommendedTimeline || !instance.disableGlobalTimeline; -let showMenu = $ref(false); -let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD); -let narrow = $ref(window.innerWidth < 1280); -let meta = $ref(); +const showMenu = $ref(false); +let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD), + narrow = $ref(window.innerWidth < 1280), + meta = $ref(); const keymap = $computed(() => { return { diff --git a/packages/client/src/ui/visitor/kanban.vue b/packages/client/src/ui/visitor/kanban.vue index 3da173a04..3624610df 100644 --- a/packages/client/src/ui/visitor/kanban.vue +++ b/packages/client/src/ui/visitor/kanban.vue @@ -81,7 +81,7 @@ </template> <script lang="ts"> -import { defineComponent, defineAsyncComponent } from "vue"; +import { defineAsyncComponent, defineComponent } from "vue"; import { host, instanceName } from "@/config"; import * as os from "@/os"; import MkPagination from "@/components/MkPagination.vue"; diff --git a/packages/client/src/ui/zen.vue b/packages/client/src/ui/zen.vue index cb2354a2e..b171420d7 100644 --- a/packages/client/src/ui/zen.vue +++ b/packages/client/src/ui/zen.vue @@ -7,11 +7,12 @@ </template> <script lang="ts" setup> -import { provide, ComputedRef } from "vue"; +import type { ComputedRef } from "vue"; +import { provide } from "vue"; import XCommon from "./_common_/common.vue"; import { mainRouter } from "@/router"; +import type { PageMetadata } from "@/scripts/page-metadata"; import { - PageMetadata, provideMetadataReceiver, setPageMetadata, } from "@/scripts/page-metadata"; diff --git a/packages/client/src/widgets/activity.chart.vue b/packages/client/src/widgets/activity.chart.vue index 7c6ff80e3..0f8eccb3c 100644 --- a/packages/client/src/widgets/activity.chart.vue +++ b/packages/client/src/widgets/activity.chart.vue @@ -36,14 +36,14 @@ const props = defineProps<{ activity: any[]; }>(); -let viewBoxX: number = $ref(147); -let viewBoxY: number = $ref(60); -let zoom: number = $ref(1); -let pos: number = $ref(0); -let pointsNote: any = $ref(null); -let pointsReply: any = $ref(null); -let pointsRenote: any = $ref(null); -let pointsTotal: any = $ref(null); +const viewBoxX: number = $ref(147); +const viewBoxY: number = $ref(60); +let zoom: number = $ref(1), + pos: number = $ref(0), + pointsNote: any = $ref(null), + pointsReply: any = $ref(null), + pointsRenote: any = $ref(null), + pointsTotal: any = $ref(null); function dragListen(fn) { window.addEventListener("mousemove", fn); @@ -65,8 +65,8 @@ function onMousedown(ev) { // 動かした時 dragListen((me) => { - let moveLeft = me.clientX - clickX; - let moveTop = me.clientY - clickY; + const moveLeft = me.clientX - clickX; + const moveTop = me.clientY - clickY; zoom = Math.max(1, baseZoom + -moveTop / 20); pos = Math.min(0, basePos + moveLeft); diff --git a/packages/client/src/widgets/activity.vue b/packages/client/src/widgets/activity.vue index 950c9a494..beeba81d7 100644 --- a/packages/client/src/widgets/activity.vue +++ b/packages/client/src/widgets/activity.vue @@ -38,17 +38,16 @@ <script lang="ts" setup> import { onMounted, onUnmounted, reactive, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; import XCalendar from "./activity.calendar.vue"; import XChart from "./activity.chart.vue"; import MkHeatmap from "@/components/MkHeatmap.vue"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import { $i } from "@/account"; @@ -79,8 +78,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/aiscript.vue b/packages/client/src/widgets/aiscript.vue index 547d1e6d2..ac1472da1 100644 --- a/packages/client/src/widgets/aiscript.vue +++ b/packages/client/src/widgets/aiscript.vue @@ -28,14 +28,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref, watch } from "vue"; import { AiScript, parse, utils } from "@syuilo/aiscript"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import { createAiScriptEnv } from "@/scripts/aiscript/api"; @@ -60,8 +59,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/button.vue b/packages/client/src/widgets/button.vue index b4ac5cb62..b9378e0ea 100644 --- a/packages/client/src/widgets/button.vue +++ b/packages/client/src/widgets/button.vue @@ -9,14 +9,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref, watch } from "vue"; import { AiScript, parse, utils } from "@syuilo/aiscript"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import { createAiScriptEnv } from "@/scripts/aiscript/api"; import { $i } from "@/account"; @@ -43,8 +42,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/calendar.vue b/packages/client/src/widgets/calendar.vue index 0027c8bbd..eb2ec6c41 100644 --- a/packages/client/src/widgets/calendar.vue +++ b/packages/client/src/widgets/calendar.vue @@ -45,14 +45,13 @@ <script lang="ts" setup> import { onUnmounted, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import { i18n } from "@/i18n"; import { useInterval } from "@/scripts/use-interval"; import { $i } from "@/account"; @@ -69,8 +68,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); @@ -113,7 +112,7 @@ const tick = () => { ][now.getDay()]; const dayNumer = now.getTime() - new Date(ny, nm, nd).getTime(); - const dayDenom = 1000 /*ms*/ * 60 /*s*/ * 60 /*m*/ * 24; /*h*/ + const dayDenom = 1000 /* ms */ * 60 /* s */ * 60 /* m */ * 24; /* h */ const monthNumer = now.getTime() - new Date(ny, nm, 1).getTime(); const monthDenom = new Date(ny, nm + 1, 1).getTime() - new Date(ny, nm, 1).getTime(); diff --git a/packages/client/src/widgets/clock.vue b/packages/client/src/widgets/clock.vue index 0b6575dac..d1a6385b3 100644 --- a/packages/client/src/widgets/clock.vue +++ b/packages/client/src/widgets/clock.vue @@ -47,14 +47,13 @@ <script lang="ts" setup> import {} from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import MkContainer from "@/components/MkContainer.vue"; import MkAnalogClock from "@/components/MkAnalogClock.vue"; import MkDigitalClock from "@/components/MkDigitalClock.vue"; @@ -189,8 +188,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/digital-clock.vue b/packages/client/src/widgets/digital-clock.vue index 7c2602c58..9b16a62de 100644 --- a/packages/client/src/widgets/digital-clock.vue +++ b/packages/client/src/widgets/digital-clock.vue @@ -16,14 +16,13 @@ <script lang="ts" setup> import { onUnmounted, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import { timezones } from "@/scripts/timezones"; import MkDigitalClock from "@/components/MkDigitalClock.vue"; @@ -66,8 +65,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/federation.vue b/packages/client/src/widgets/federation.vue index f10264711..a8e121519 100644 --- a/packages/client/src/widgets/federation.vue +++ b/packages/client/src/widgets/federation.vue @@ -49,14 +49,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import MkContainer from "@/components/MkContainer.vue"; import MkMiniChart from "@/components/MkMiniChart.vue"; import * as os from "@/os"; @@ -76,8 +75,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps> & { foldable?: boolean; scrollable?: boolean; }>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps> & { foldable?: boolean; scrollable?: boolean; }>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps>; foldable?: boolean; diff --git a/packages/client/src/widgets/instance-cloud.vue b/packages/client/src/widgets/instance-cloud.vue index 80f6653c4..e42037ed9 100644 --- a/packages/client/src/widgets/instance-cloud.vue +++ b/packages/client/src/widgets/instance-cloud.vue @@ -22,9 +22,9 @@ <script lang="ts" setup> import {} from "vue"; import { - useWidgetPropsManager, WidgetComponentEmits, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; import type { Widget, WidgetComponentExpose } from "./widget"; import type { GetFormResultType } from "@/scripts/form"; @@ -46,8 +46,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); @@ -58,7 +58,7 @@ const { widgetProps, configure } = useWidgetPropsManager( emit, ); -let cloud = $ref<InstanceType<typeof MkTagCloud> | null>(); +const cloud = $ref<InstanceType<typeof MkTagCloud> | null>(); let activeInstances = $shallowRef(null); function onInstanceClick(i) { diff --git a/packages/client/src/widgets/job-queue.vue b/packages/client/src/widgets/job-queue.vue index 7a07c5362..05cf59ab8 100644 --- a/packages/client/src/widgets/job-queue.vue +++ b/packages/client/src/widgets/job-queue.vue @@ -124,14 +124,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, reactive, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import { stream } from "@/stream"; import number from "@/filters/number"; import * as sound from "@/scripts/sound"; @@ -154,8 +153,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/memo.vue b/packages/client/src/widgets/memo.vue index 85cb1f747..78c5ad5a6 100644 --- a/packages/client/src/widgets/memo.vue +++ b/packages/client/src/widgets/memo.vue @@ -24,14 +24,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, reactive, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import { defaultStore } from "@/store"; @@ -49,8 +48,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // Currently, due to a limitation of vue, imported types cannot be passed to generics. -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/notifications.vue b/packages/client/src/widgets/notifications.vue index 74350db81..cc253b5cc 100644 --- a/packages/client/src/widgets/notifications.vue +++ b/packages/client/src/widgets/notifications.vue @@ -31,14 +31,13 @@ <script lang="ts" setup> import { defineAsyncComponent } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import MkContainer from "@/components/MkContainer.vue"; import XNotifications from "@/components/MkNotifications.vue"; import * as os from "@/os"; @@ -65,8 +64,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/online-users.vue b/packages/client/src/widgets/online-users.vue index 2ee37d2a2..6293094e7 100644 --- a/packages/client/src/widgets/online-users.vue +++ b/packages/client/src/widgets/online-users.vue @@ -21,14 +21,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import { useInterval } from "@/scripts/use-interval"; import { i18n } from "@/i18n"; @@ -45,8 +44,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/photos.vue b/packages/client/src/widgets/photos.vue index 773d7d618..3a0130624 100644 --- a/packages/client/src/widgets/photos.vue +++ b/packages/client/src/widgets/photos.vue @@ -27,14 +27,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, reactive, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import { stream } from "@/stream"; import { getStaticImageUrl } from "@/scripts/get-static-image-url"; import * as os from "@/os"; @@ -58,8 +57,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/post-form.vue b/packages/client/src/widgets/post-form.vue index 2e524bb8e..e76d6ba6f 100644 --- a/packages/client/src/widgets/post-form.vue +++ b/packages/client/src/widgets/post-form.vue @@ -9,14 +9,13 @@ <script lang="ts" setup> import {} from "vue"; -import { GetFormResultType } from "@/scripts/form"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; +import type { GetFormResultType } from "@/scripts/form"; import XPostForm from "@/components/MkPostForm.vue"; const name = "postForm"; @@ -26,8 +25,8 @@ const widgetPropsDef = {}; type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/rss-ticker.vue b/packages/client/src/widgets/rss-ticker.vue index efb57eac7..bb696a7ca 100644 --- a/packages/client/src/widgets/rss-ticker.vue +++ b/packages/client/src/widgets/rss-ticker.vue @@ -38,15 +38,14 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; import MarqueeText from "@/components/MkMarquee.vue"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import { useInterval } from "@/scripts/use-interval"; @@ -91,8 +90,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/rss.vue b/packages/client/src/widgets/rss.vue index 1fe8a0b20..9ba99e2d2 100644 --- a/packages/client/src/widgets/rss.vue +++ b/packages/client/src/widgets/rss.vue @@ -30,14 +30,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import { useInterval } from "@/scripts/use-interval"; @@ -62,8 +61,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/server-info.vue b/packages/client/src/widgets/server-info.vue index 52677687e..7b2b63d2a 100644 --- a/packages/client/src/widgets/server-info.vue +++ b/packages/client/src/widgets/server-info.vue @@ -30,14 +30,13 @@ </template> <script lang="ts" setup> +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import { host } from "@/config"; const name = "serverInfo"; diff --git a/packages/client/src/widgets/server-metric/cpu-mem.vue b/packages/client/src/widgets/server-metric/cpu-mem.vue index ec2101bd8..ac7e7f7c1 100644 --- a/packages/client/src/widgets/server-metric/cpu-mem.vue +++ b/packages/client/src/widgets/server-metric/cpu-mem.vue @@ -82,7 +82,7 @@ </template> <script lang="ts" setup> -import { onMounted, onBeforeUnmount } from "vue"; +import { onBeforeUnmount, onMounted } from "vue"; import { v4 as uuid } from "uuid"; const props = defineProps<{ @@ -90,23 +90,23 @@ const props = defineProps<{ meta: any; }>(); -let viewBoxX: number = $ref(50); -let viewBoxY: number = $ref(30); -let stats: any[] = $ref([]); +const viewBoxX: number = $ref(50); +const viewBoxY: number = $ref(30); +const stats: any[] = $ref([]); const cpuGradientId = uuid(); const cpuMaskId = uuid(); const memGradientId = uuid(); const memMaskId = uuid(); -let cpuPolylinePoints: string = $ref(""); -let memPolylinePoints: string = $ref(""); -let cpuPolygonPoints: string = $ref(""); -let memPolygonPoints: string = $ref(""); -let cpuHeadX: any = $ref(null); -let cpuHeadY: any = $ref(null); -let memHeadX: any = $ref(null); -let memHeadY: any = $ref(null); -let cpuP: string = $ref(""); -let memP: string = $ref(""); +let cpuPolylinePoints: string = $ref(""), + memPolylinePoints: string = $ref(""), + cpuPolygonPoints: string = $ref(""), + memPolygonPoints: string = $ref(""), + cpuHeadX: any = $ref(null), + cpuHeadY: any = $ref(null), + memHeadX: any = $ref(null), + memHeadY: any = $ref(null), + cpuP: string = $ref(""), + memP: string = $ref(""); onMounted(() => { props.connection.on("stats", onStats); @@ -125,11 +125,11 @@ function onStats(connStats) { stats.push(connStats); if (stats.length > 50) stats.shift(); - let cpuPolylinePointsStats = stats.map((s, i) => [ + const cpuPolylinePointsStats = stats.map((s, i) => [ viewBoxX - (stats.length - 1 - i), (1 - s.cpu) * viewBoxY, ]); - let memPolylinePointsStats = stats.map((s, i) => [ + const memPolylinePointsStats = stats.map((s, i) => [ viewBoxX - (stats.length - 1 - i), (1 - s.mem.active / props.meta.mem.total) * viewBoxY, ]); diff --git a/packages/client/src/widgets/server-metric/cpu.vue b/packages/client/src/widgets/server-metric/cpu.vue index 563fe3b0f..46843363b 100644 --- a/packages/client/src/widgets/server-metric/cpu.vue +++ b/packages/client/src/widgets/server-metric/cpu.vue @@ -10,7 +10,7 @@ </template> <script lang="ts" setup> -import { onMounted, onBeforeUnmount } from "vue"; +import { onBeforeUnmount, onMounted } from "vue"; import XPie from "./pie.vue"; const props = defineProps<{ diff --git a/packages/client/src/widgets/server-metric/index.vue b/packages/client/src/widgets/server-metric/index.vue index c92943ad1..ce8ddfc96 100644 --- a/packages/client/src/widgets/server-metric/index.vue +++ b/packages/client/src/widgets/server-metric/index.vue @@ -51,12 +51,11 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "../widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "../widget"; import XCpuMemory from "./cpu-mem.vue"; import XNet from "./net.vue"; @@ -65,7 +64,7 @@ import XMemory from "./mem.vue"; import XDisk from "./disk.vue"; import XMeili from "./meilisearch.vue"; import MkContainer from "@/components/MkContainer.vue"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import { stream } from "@/stream"; import { i18n } from "@/i18n"; @@ -92,8 +91,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/server-metric/meilisearch.vue b/packages/client/src/widgets/server-metric/meilisearch.vue index f7c7bd593..1c3b07fd1 100644 --- a/packages/client/src/widgets/server-metric/meilisearch.vue +++ b/packages/client/src/widgets/server-metric/meilisearch.vue @@ -18,8 +18,8 @@ <script lang="ts" setup> import { onBeforeUnmount, onMounted } from "vue"; -import bytes from "@/filters/bytes"; import XPie from "./pie.vue"; +import bytes from "@/filters/bytes"; import { i18n } from "@/i18n"; import * as os from "@/os"; @@ -28,11 +28,11 @@ const props = defineProps<{ meta: any; }>(); -let progress: number = $ref(0); -let serverStats = $ref(null); -let totalSize: number = $ref(0); -let indexCount: number = $ref(0); -let available: string = $ref("unavailable"); +let progress: number = $ref(0), + serverStats = $ref(null), + totalSize: number = $ref(0), + indexCount: number = $ref(0), + available: string = $ref("unavailable"); function onStats(stats) { totalSize = stats.meilisearch.size; diff --git a/packages/client/src/widgets/server-metric/mem.vue b/packages/client/src/widgets/server-metric/mem.vue index 80cad4a82..97e7a63ce 100644 --- a/packages/client/src/widgets/server-metric/mem.vue +++ b/packages/client/src/widgets/server-metric/mem.vue @@ -11,7 +11,7 @@ </template> <script lang="ts" setup> -import { onMounted, onBeforeUnmount } from "vue"; +import { onBeforeUnmount, onMounted } from "vue"; import XPie from "./pie.vue"; import bytes from "@/filters/bytes"; @@ -20,10 +20,10 @@ const props = defineProps<{ meta: any; }>(); -let usage: number = $ref(0); -let total: number = $ref(0); -let used: number = $ref(0); -let free: number = $ref(0); +let usage: number = $ref(0), + total: number = $ref(0), + used: number = $ref(0), + free: number = $ref(0); function onStats(stats) { usage = stats.mem.active / props.meta.mem.total; diff --git a/packages/client/src/widgets/server-metric/net.vue b/packages/client/src/widgets/server-metric/net.vue index 1363142b2..b5e7cc8ef 100644 --- a/packages/client/src/widgets/server-metric/net.vue +++ b/packages/client/src/widgets/server-metric/net.vue @@ -40,7 +40,7 @@ </template> <script lang="ts" setup> -import { onMounted, onBeforeUnmount } from "vue"; +import { onBeforeUnmount, onMounted } from "vue"; import bytes from "@/filters/bytes"; const props = defineProps<{ @@ -48,19 +48,19 @@ const props = defineProps<{ meta: any; }>(); -let viewBoxX: number = $ref(50); -let viewBoxY: number = $ref(30); -let stats: any[] = $ref([]); -let inPolylinePoints: string = $ref(""); -let outPolylinePoints: string = $ref(""); -let inPolygonPoints: string = $ref(""); -let outPolygonPoints: string = $ref(""); -let inHeadX: any = $ref(null); -let inHeadY: any = $ref(null); -let outHeadX: any = $ref(null); -let outHeadY: any = $ref(null); -let inRecent: number = $ref(0); -let outRecent: number = $ref(0); +const viewBoxX: number = $ref(50); +const viewBoxY: number = $ref(30); +const stats: any[] = $ref([]); +let inPolylinePoints: string = $ref(""), + outPolylinePoints: string = $ref(""), + inPolygonPoints: string = $ref(""), + outPolygonPoints: string = $ref(""), + inHeadX: any = $ref(null), + inHeadY: any = $ref(null), + outHeadX: any = $ref(null), + outHeadY: any = $ref(null), + inRecent: number = $ref(0), + outRecent: number = $ref(0); onMounted(() => { props.connection.on("stats", onStats); @@ -85,11 +85,11 @@ function onStats(connStats) { Math.max(...stats.map((s) => s.net.tx)), ); - let inPolylinePointsStats = stats.map((s, i) => [ + const inPolylinePointsStats = stats.map((s, i) => [ viewBoxX - (stats.length - 1 - i), (1 - s.net.rx / inPeak) * viewBoxY, ]); - let outPolylinePointsStats = stats.map((s, i) => [ + const outPolylinePointsStats = stats.map((s, i) => [ viewBoxX - (stats.length - 1 - i), (1 - s.net.tx / outPeak) * viewBoxY, ]); diff --git a/packages/client/src/widgets/slideshow.vue b/packages/client/src/widgets/slideshow.vue index 243875f36..70601466d 100644 --- a/packages/client/src/widgets/slideshow.vue +++ b/packages/client/src/widgets/slideshow.vue @@ -24,14 +24,13 @@ <script lang="ts" setup> import { nextTick, onMounted, onUnmounted, reactive, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import { useInterval } from "@/scripts/use-interval"; import { i18n } from "@/i18n"; @@ -53,8 +52,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/timeline.vue b/packages/client/src/widgets/timeline.vue index 39f4f8337..8ff30d299 100644 --- a/packages/client/src/widgets/timeline.vue +++ b/packages/client/src/widgets/timeline.vue @@ -68,14 +68,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, reactive, ref, watch } from "vue"; -import { GetFormResultType } from "@/scripts/form"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; +import type { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; import MkContainer from "@/components/MkContainer.vue"; import XTimeline from "@/components/MkTimeline.vue"; @@ -113,8 +112,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/trends.vue b/packages/client/src/widgets/trends.vue index dd50b22e7..52b068127 100644 --- a/packages/client/src/widgets/trends.vue +++ b/packages/client/src/widgets/trends.vue @@ -38,14 +38,13 @@ <script lang="ts" setup> import { onMounted, onUnmounted, ref } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; import MkContainer from "@/components/MkContainer.vue"; import MkMiniChart from "@/components/MkMiniChart.vue"; import * as os from "@/os"; @@ -64,8 +63,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/unix-clock.vue b/packages/client/src/widgets/unix-clock.vue index dbb858354..3d2a89318 100644 --- a/packages/client/src/widgets/unix-clock.vue +++ b/packages/client/src/widgets/unix-clock.vue @@ -18,14 +18,13 @@ <script lang="ts" setup> import { onUnmounted, ref, watch } from "vue"; +import type { Widget, WidgetComponentExpose } from "./widget"; import { - useWidgetPropsManager, - Widget, WidgetComponentEmits, - WidgetComponentExpose, WidgetComponentProps, + useWidgetPropsManager, } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { GetFormResultType } from "@/scripts/form"; const name = "unixClock"; @@ -52,8 +51,8 @@ const widgetPropsDef = { type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); diff --git a/packages/client/src/widgets/user-list.vue b/packages/client/src/widgets/user-list.vue index 1692f6264..45cdad00e 100644 --- a/packages/client/src/widgets/user-list.vue +++ b/packages/client/src/widgets/user-list.vue @@ -28,8 +28,9 @@ </template> <script lang="ts" setup> -import { useWidgetPropsManager, Widget, WidgetComponentExpose } from "./widget"; -import { GetFormResultType } from "@/scripts/form"; +import type { Widget, WidgetComponentExpose } from "./widget"; +import { useWidgetPropsManager } from "./widget"; +import type { GetFormResultType } from "@/scripts/form"; import MkContainer from "@/components/MkContainer.vue"; import MkAvatars from "@/components/MkAvatars.vue"; import * as os from "@/os"; @@ -51,8 +52,8 @@ const widgetPropsDef = { }; type WidgetProps = GetFormResultType<typeof widgetPropsDef>; // 現時点ではvueの制限によりimportしたtypeをジェネリックに渡せない -//const props = defineProps<WidgetComponentProps<WidgetProps>>(); -//const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); +// const props = defineProps<WidgetComponentProps<WidgetProps>>(); +// const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const props = defineProps<{ widget?: Widget<WidgetProps> }>(); const emit = defineEmits<{ (ev: "updateProps", props: WidgetProps) }>(); const { widgetProps, configure, save } = useWidgetPropsManager( @@ -61,9 +62,9 @@ const { widgetProps, configure, save } = useWidgetPropsManager( props, emit, ); -let list = $ref(); -let users = $ref([]); -let fetching = $ref(true); +let list = $ref(), + users = $ref([]), + fetching = $ref(true); async function chooseList() { const lists = await os.api("users/lists/list"); const { canceled, result: list } = await os.select({ diff --git a/packages/megalodon/package.json b/packages/megalodon/package.json index bd1b80c1d..dea59b579 100644 --- a/packages/megalodon/package.json +++ b/packages/megalodon/package.json @@ -5,7 +5,7 @@ "typings": "./lib/src/index.d.ts", "scripts": { "build": "tsc -p ./", - "lint": "pnpm rome check --apply src/**/*.ts", + "lint": "pnpm rome check **/*.ts --apply", "format": "pnpm rome format --write src/**/*.ts", "doc": "typedoc --out ../docs ./src", "test": "NODE_ENV=test jest -u --maxWorkers=3" diff --git a/packages/megalodon/src/axios.d.ts b/packages/megalodon/src/axios.d.ts index 114cb06aa..f19fe38a2 100644 --- a/packages/megalodon/src/axios.d.ts +++ b/packages/megalodon/src/axios.d.ts @@ -1 +1 @@ -declare module 'axios/lib/adapters/http' +declare module "axios/lib/adapters/http"; diff --git a/packages/megalodon/src/cancel.ts b/packages/megalodon/src/cancel.ts index 3b905a492..f8e4729b8 100644 --- a/packages/megalodon/src/cancel.ts +++ b/packages/megalodon/src/cancel.ts @@ -1,13 +1,13 @@ export class RequestCanceledError extends Error { - public isCancel: boolean + public isCancel: boolean; - constructor(msg: string) { - super(msg) - this.isCancel = true - Object.setPrototypeOf(this, RequestCanceledError) - } + constructor(msg: string) { + super(msg); + this.isCancel = true; + Object.setPrototypeOf(this, RequestCanceledError); + } } export const isCancel = (value: any): boolean => { - return value && value.isCancel -} + return value && value.isCancel; +}; diff --git a/packages/megalodon/src/converter.ts b/packages/megalodon/src/converter.ts index 113be823c..93d669fa7 100644 --- a/packages/megalodon/src/converter.ts +++ b/packages/megalodon/src/converter.ts @@ -1,3 +1,3 @@ import MisskeyAPI from "./misskey/api_client"; -export default MisskeyAPI.Converter \ No newline at end of file +export default MisskeyAPI.Converter; diff --git a/packages/megalodon/src/default.ts b/packages/megalodon/src/default.ts index 0194b3dcc..45bce13e2 100644 --- a/packages/megalodon/src/default.ts +++ b/packages/megalodon/src/default.ts @@ -1,3 +1,3 @@ -export const NO_REDIRECT = 'urn:ietf:wg:oauth:2.0:oob' -export const DEFAULT_SCOPE = ['read', 'write', 'follow'] -export const DEFAULT_UA = 'megalodon' +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/entity.ts b/packages/megalodon/src/entity.ts index 39dd4b617..b73d2b359 100644 --- a/packages/megalodon/src/entity.ts +++ b/packages/megalodon/src/entity.ts @@ -35,4 +35,4 @@ /// <reference path="./entities/token.ts" /> /// <reference path="./entities/urls.ts" /> -export default Entity +export default Entity; diff --git a/packages/megalodon/src/filter_context.ts b/packages/megalodon/src/filter_context.ts index c69be98cd..4c83cb15f 100644 --- a/packages/megalodon/src/filter_context.ts +++ b/packages/megalodon/src/filter_context.ts @@ -1,11 +1,11 @@ -import Entity from './entity' +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 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 +export default FilterContext; diff --git a/packages/megalodon/src/index.ts b/packages/megalodon/src/index.ts index 15486ad28..758d3a46a 100644 --- a/packages/megalodon/src/index.ts +++ b/packages/megalodon/src/index.ts @@ -1,28 +1,32 @@ -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' +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 -} + Response, + OAuth, + RequestCanceledError, + isCancel, + ProxyConfig, + detector, + MegalodonInterface, + WebSocketInterface, + NotificationType, + FilterContext, + Misskey, + Entity, + Converter, +}; -export default generator +export default generator; diff --git a/packages/megalodon/src/megalodon.ts b/packages/megalodon/src/megalodon.ts index 1cd0a7db3..1fd1f9f93 100644 --- a/packages/megalodon/src/megalodon.ts +++ b/packages/megalodon/src/megalodon.ts @@ -1,155 +1,179 @@ -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' +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 + 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 + /** + * 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<string>; redirect_uris: string; website: string }> - ): Promise<OAuth.AppData> + /** + * 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<string>; + redirect_uris: string; + website: string; + }>, + ): Promise<OAuth.AppData>; - /** - * 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<string>; redirect_uris: string; website: string }> - ): Promise<OAuth.AppData> + /** + * 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<string>; + redirect_uris: string; + website: string; + }>, + ): Promise<OAuth.AppData>; - // ====================================== - // apps - // ====================================== - /** - * GET /api/v1/apps/verify_credentials - * - * @return An Application - */ - verifyAppCredentials(): Promise<Response<Entity.Application>> + // ====================================== + // apps + // ====================================== + /** + * GET /api/v1/apps/verify_credentials + * + * @return An Application + */ + verifyAppCredentials(): Promise<Response<Entity.Application>>; - // ====================================== - // apps/oauth - // ====================================== + // ====================================== + // 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<OAuth.TokenData> + /** + * 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<OAuth.TokenData>; - /** - * 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<OAuth.TokenData> + /** + * 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<OAuth.TokenData>; - /** - * 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<Response<{}>> + /** + * 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<Response<{}>>; - // ====================================== - // 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<Response<Entity.Token>> - /** - * GET /api/v1/accounts/verify_credentials - * - * @return Account. - */ - verifyAccountCredentials(): Promise<Response<Entity.Account>> - /** - * 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<Response<Entity.Account>> - /** - * GET /api/v1/accounts/:id - * - * @param id The account ID. - * @return An account. - */ - getAccount(id: string): Promise<Response<Entity.Account>> - /** + // ====================================== + // 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<Response<Entity.Token>>; + /** + * GET /api/v1/accounts/verify_credentials + * + * @return Account. + */ + verifyAccountCredentials(): Promise<Response<Entity.Account>>; + /** + * 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<Response<Entity.Account>>; + /** + * GET /api/v1/accounts/:id + * + * @param id The account ID. + * @return An account. + */ + getAccount(id: string): Promise<Response<Entity.Account>>; + /** * GET /api/v1/accounts/:id/statuses * * @param id The account ID. @@ -164,1186 +188,1279 @@ export interface MegalodonInterface { * @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<Response<Array<Entity.Status>>> - /** - * 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<Response<Array<Entity.Status>>> - /** - * POST /api/v1/pleroma/accounts/:id/subscribe - * - * @param id Target account ID. - * @return Relationship. - */ - subscribeAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/pleroma/accounts/:id/unsubscribe - * - * @param id Target account ID. - * @return Relationship. - */ - unsubscribeAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * 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<Response<Array<Entity.Account>>> + 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<Response<Array<Entity.Status>>>; + /** + * 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<Response<Array<Entity.Status>>>; + /** + * POST /api/v1/pleroma/accounts/:id/subscribe + * + * @param id Target account ID. + * @return Relationship. + */ + subscribeAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/pleroma/accounts/:id/unsubscribe + * + * @param id Target account ID. + * @return Relationship. + */ + unsubscribeAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * 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<Response<Array<Entity.Account>>>; - /** - * GET /api/v1/accounts/:id/featured_tags - * - * @param id The account ID. - * @return The array of accounts. - */ - getAccountFeaturedTags( - id: string - ): Promise<Response<Array<Entity.FeaturedTag>>> + /** + * GET /api/v1/accounts/:id/featured_tags + * + * @param id The account ID. + * @return The array of accounts. + */ + getAccountFeaturedTags( + id: string, + ): Promise<Response<Array<Entity.FeaturedTag>>>; - /** - * 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<Response<Array<Entity.Account>>> - /** - * GET /api/v1/accounts/:id/lists - * - * @param id The account ID. - * @return The array of lists. - */ - getAccountLists(id: string): Promise<Response<Array<Entity.List>>> - /** - * GET /api/v1/accounts/:id/identity_proofs - * - * @param id The account ID. - * @return Array of IdentityProof - */ - getIdentityProof(id: string): Promise<Response<Array<Entity.IdentityProof>>> - /** - * 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<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/unfollow - * - * @param id The account ID. - * @return Relationship - */ - unfollowAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/block - * - * @param id The account ID. - * @return Relationship - */ - blockAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/unblock - * - * @param id The account ID. - * @return RElationship - */ - unblockAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * 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<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/unmute - * - * @param id The account ID. - * @return Relationship - */ - unmuteAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/pin - * - * @param id The account ID. - * @return Relationship - */ - pinAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/accounts/:id/unpin - * - * @param id The account ID. - * @return Relationship - */ - unpinAccount(id: string): Promise<Response<Entity.Relationship>> - /** - * GET /api/v1/accounts/relationships - * - * @param id The account ID. - * @return Relationship - */ - getRelationship(id: string): Promise<Response<Entity.Relationship>> - /** - * Get multiple relationships in one method - * - * @param ids Array of account IDs. - * @return Array of Relationship. - */ - getRelationships(ids: Array<string>): Promise<Response<Array<Entity.Relationship>>> - /** - * 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<Response<Array<Entity.Account>>> - // ====================================== - // 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<Response<Array<Entity.Status>>> - // ====================================== - // 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<Response<Array<Entity.Status>>> - // ====================================== - // 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<Response<Array<Entity.Account>>> - // ====================================== - // 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<Response<Array<Entity.Account>>> - // ====================================== - // 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<Response<Array<string>>> - /** - * POST/api/v1/domain_blocks - * - * @param domain Domain to block. - */ - blockDomain(domain: string): Promise<Response<{}>> - /** - * DELETE /api/v1/domain_blocks - * - * @param domain Domain to unblock - */ - unblockDomain(domain: string): Promise<Response<{}>> - // ====================================== - // accounts/filters - // ====================================== - /** - * GET /api/v1/filters - * - * @return Array of filters. - */ - getFilters(): Promise<Response<Array<Entity.Filter>>> - /** - * GET /api/v1/filters/:id - * - * @param id The filter ID. - * @return Filter. - */ - getFilter(id: string): Promise<Response<Entity.Filter>> - /** - * 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<Entity.FilterContext>, - options?: { - irreversible?: boolean - whole_word?: boolean - expires_in?: string - } - ): Promise<Response<Entity.Filter>> - /** - * 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<Entity.FilterContext>, - options?: { - irreversible?: boolean - whole_word?: boolean - expires_in?: string - } - ): Promise<Response<Entity.Filter>> - /** - * DELETE /api/v1/filters/:id - * - * @param id The filter ID. - * @return Removed filter. - */ - deleteFilter(id: string): Promise<Response<Entity.Filter>> - // ====================================== - // 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<string>; forward?: boolean }): Promise<Response<Entity.Report>> - // ====================================== - // accounts/follow_requests - // ====================================== - /** - * GET /api/v1/follow_requests - * - * @param limit Maximum number of results. - * @return Array of account. - */ - getFollowRequests(limit?: number): Promise<Response<Array<Entity.Account>>> - /** - * POST /api/v1/follow_requests/:id/authorize - * - * @param id Target account ID. - * @return Relationship. - */ - acceptFollowRequest(id: string): Promise<Response<Entity.Relationship>> - /** - * POST /api/v1/follow_requests/:id/reject - * - * @param id Target account ID. - * @return Relationship. - */ - rejectFollowRequest(id: string): Promise<Response<Entity.Relationship>> - // ====================================== - // 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<Response<Array<Entity.Account>>> - // ====================================== - // accounts/featured_tags - // ====================================== - /** - * GET /api/v1/featured_tags - * - * @return Array of featured tag. - */ - getFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> - /** - * POST /api/v1/featured_tags - * - * @param name Target hashtag name. - * @return FeaturedTag. - */ - createFeaturedTag(name: string): Promise<Response<Entity.FeaturedTag>> - /** - * DELETE /api/v1/featured_tags/:id - * - * @param id Target featured tag id. - * @return Empty - */ - deleteFeaturedTag(id: string): Promise<Response<{}>> - /** - * GET /api/v1/featured_tags/suggestions - * - * @return Array of tag. - */ - getSuggestedTags(): Promise<Response<Array<Entity.Tag>>> - // ====================================== - // accounts/preferences - // ====================================== - /** - * GET /api/v1/preferences - * - * @return Preferences. - */ - getPreferences(): Promise<Response<Entity.Preferences>> - // ====================================== - // accounts/suggestions - // ====================================== - /** - * GET /api/v1/suggestions - * - * @param limit Maximum number of results. - * @return Array of accounts. - */ - getSuggestions(limit?: number): Promise<Response<Array<Entity.Account>>> - // ====================================== - // accounts/tags - // ====================================== - getFollowedTags(): Promise<Response<Array<Entity.Tag>>> - /** - * GET /api/v1/tags/:id - * - * @param id Target hashtag id. - * @return Tag - */ - getTag(id: string): Promise<Response<Entity.Tag>> - /** - * POST /api/v1/tags/:id/follow - * - * @param id Target hashtag id. - * @return Tag - */ - followTag(id: string): Promise<Response<Entity.Tag>> - /** - * POST /api/v1/tags/:id/unfollow - * - * @param id Target hashtag id. - * @return Tag - */ - unfollowTag(id: string): Promise<Response<Entity.Tag>> - // ====================================== - // 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<string> - poll?: { options: Array<string>; 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<Response<Entity.Status>> - /** - * GET /api/v1/statuses/:id - * - * @param id The target status id. - * @return Status - */ - getStatus(id: string): Promise<Response<Entity.Status>> - /** + /** + * 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<Response<Array<Entity.Account>>>; + /** + * GET /api/v1/accounts/:id/lists + * + * @param id The account ID. + * @return The array of lists. + */ + getAccountLists(id: string): Promise<Response<Array<Entity.List>>>; + /** + * GET /api/v1/accounts/:id/identity_proofs + * + * @param id The account ID. + * @return Array of IdentityProof + */ + getIdentityProof(id: string): Promise<Response<Array<Entity.IdentityProof>>>; + /** + * 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<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/unfollow + * + * @param id The account ID. + * @return Relationship + */ + unfollowAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/block + * + * @param id The account ID. + * @return Relationship + */ + blockAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/unblock + * + * @param id The account ID. + * @return RElationship + */ + unblockAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * 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<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/unmute + * + * @param id The account ID. + * @return Relationship + */ + unmuteAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/pin + * + * @param id The account ID. + * @return Relationship + */ + pinAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/accounts/:id/unpin + * + * @param id The account ID. + * @return Relationship + */ + unpinAccount(id: string): Promise<Response<Entity.Relationship>>; + /** + * GET /api/v1/accounts/relationships + * + * @param id The account ID. + * @return Relationship + */ + getRelationship(id: string): Promise<Response<Entity.Relationship>>; + /** + * Get multiple relationships in one method + * + * @param ids Array of account IDs. + * @return Array of Relationship. + */ + getRelationships( + ids: Array<string>, + ): Promise<Response<Array<Entity.Relationship>>>; + /** + * 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<Response<Array<Entity.Account>>>; + // ====================================== + // 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<Response<Array<Entity.Status>>>; + // ====================================== + // 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<Response<Array<Entity.Status>>>; + // ====================================== + // 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<Response<Array<Entity.Account>>>; + // ====================================== + // 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<Response<Array<Entity.Account>>>; + // ====================================== + // 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<Response<Array<string>>>; + /** + * POST/api/v1/domain_blocks + * + * @param domain Domain to block. + */ + blockDomain(domain: string): Promise<Response<{}>>; + /** + * DELETE /api/v1/domain_blocks + * + * @param domain Domain to unblock + */ + unblockDomain(domain: string): Promise<Response<{}>>; + // ====================================== + // accounts/filters + // ====================================== + /** + * GET /api/v1/filters + * + * @return Array of filters. + */ + getFilters(): Promise<Response<Array<Entity.Filter>>>; + /** + * GET /api/v1/filters/:id + * + * @param id The filter ID. + * @return Filter. + */ + getFilter(id: string): Promise<Response<Entity.Filter>>; + /** + * 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<Entity.FilterContext>, + options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }, + ): Promise<Response<Entity.Filter>>; + /** + * 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<Entity.FilterContext>, + options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }, + ): Promise<Response<Entity.Filter>>; + /** + * DELETE /api/v1/filters/:id + * + * @param id The filter ID. + * @return Removed filter. + */ + deleteFilter(id: string): Promise<Response<Entity.Filter>>; + // ====================================== + // 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<string>; forward?: boolean }, + ): Promise<Response<Entity.Report>>; + // ====================================== + // accounts/follow_requests + // ====================================== + /** + * GET /api/v1/follow_requests + * + * @param limit Maximum number of results. + * @return Array of account. + */ + getFollowRequests(limit?: number): Promise<Response<Array<Entity.Account>>>; + /** + * POST /api/v1/follow_requests/:id/authorize + * + * @param id Target account ID. + * @return Relationship. + */ + acceptFollowRequest(id: string): Promise<Response<Entity.Relationship>>; + /** + * POST /api/v1/follow_requests/:id/reject + * + * @param id Target account ID. + * @return Relationship. + */ + rejectFollowRequest(id: string): Promise<Response<Entity.Relationship>>; + // ====================================== + // 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<Response<Array<Entity.Account>>>; + // ====================================== + // accounts/featured_tags + // ====================================== + /** + * GET /api/v1/featured_tags + * + * @return Array of featured tag. + */ + getFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>>; + /** + * POST /api/v1/featured_tags + * + * @param name Target hashtag name. + * @return FeaturedTag. + */ + createFeaturedTag(name: string): Promise<Response<Entity.FeaturedTag>>; + /** + * DELETE /api/v1/featured_tags/:id + * + * @param id Target featured tag id. + * @return Empty + */ + deleteFeaturedTag(id: string): Promise<Response<{}>>; + /** + * GET /api/v1/featured_tags/suggestions + * + * @return Array of tag. + */ + getSuggestedTags(): Promise<Response<Array<Entity.Tag>>>; + // ====================================== + // accounts/preferences + // ====================================== + /** + * GET /api/v1/preferences + * + * @return Preferences. + */ + getPreferences(): Promise<Response<Entity.Preferences>>; + // ====================================== + // accounts/suggestions + // ====================================== + /** + * GET /api/v1/suggestions + * + * @param limit Maximum number of results. + * @return Array of accounts. + */ + getSuggestions(limit?: number): Promise<Response<Array<Entity.Account>>>; + // ====================================== + // accounts/tags + // ====================================== + getFollowedTags(): Promise<Response<Array<Entity.Tag>>>; + /** + * GET /api/v1/tags/:id + * + * @param id Target hashtag id. + * @return Tag + */ + getTag(id: string): Promise<Response<Entity.Tag>>; + /** + * POST /api/v1/tags/:id/follow + * + * @param id Target hashtag id. + * @return Tag + */ + followTag(id: string): Promise<Response<Entity.Tag>>; + /** + * POST /api/v1/tags/:id/unfollow + * + * @param id Target hashtag id. + * @return Tag + */ + unfollowTag(id: string): Promise<Response<Entity.Tag>>; + // ====================================== + // 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<string>; + poll?: { + options: Array<string>; + 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<Response<Entity.Status>>; + /** + * GET /api/v1/statuses/:id + * + * @param id The target status id. + * @return Status + */ + getStatus(id: string): Promise<Response<Entity.Status>>; + /** 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<string> - poll?: { options?: Array<string>; expires_in?: number; multiple?: boolean; hide_totals?: boolean } - } - ): Promise<Response<Entity.Status>> - /** - * DELETE /api/v1/statuses/:id - * - * @param id The target status id. - * @return Status - */ - deleteStatus(id: string): Promise<Response<{}>> - /** - * 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<Response<Entity.Context>> - /** - * GET /api/v1/statuses/:id/history - * - * Get status edit history. - * @param id The target status id. - * @return StatusEdit - */ - getStatusHistory(id: string): Promise<Response<Array<Entity.StatusEdit>>> - /** - * GET /api/v1/statuses/:id/reblogged_by - * - * @param id The target status id. - * @return Array of accounts. - */ - getStatusRebloggedBy(id: string): Promise<Response<Array<Entity.Account>>> - /** - * GET /api/v1/statuses/:id/favourited_by - * - * @param id The target status id. - * @return Array of accounts. - */ - getStatusFavouritedBy(id: string): Promise<Response<Array<Entity.Account>>> - /** - * POST /api/v1/statuses/:id/favourite - * - * @param id The target status id. - * @return Status. - */ - favouriteStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/unfavourite - * - * @param id The target status id. - * @return Status. - */ - unfavouriteStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/reblog - * - * @param id The target status id. - * @return Status. - */ - reblogStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/unreblog - * - * @param id The target status id. - * @return Status. - */ - unreblogStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/bookmark - * - * @param id The target status id. - * @return Status. - */ - bookmarkStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/unbookmark - * - * @param id The target status id. - * @return Status. - */ - unbookmarkStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/mute - * - * @param id The target status id. - * @return Status - */ - muteStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/unmute - * - * @param id The target status id. - * @return Status - */ - unmuteStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/pin - * @param id The target status id. - * @return Status - */ - pinStatus(id: string): Promise<Response<Entity.Status>> - /** - * POST /api/v1/statuses/:id/unpin - * - * @param id The target status id. - * @return Status - */ - unpinStatus(id: string): Promise<Response<Entity.Status>> - // ====================================== - // 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<Response<Entity.Attachment | Entity.AsyncAttachment>> - /** - * GET /api/v1/media/:id - * - * @param id Target media ID. - * @return Attachment - */ - getMedia(id: string): Promise<Response<Entity.Attachment>> - /** - * 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<Response<Entity.Attachment>> - // ====================================== - // statuses/polls - // ====================================== - /** - * GET /api/v1/polls/:id - * - * @param id Target poll ID. - * @return Poll - */ - getPoll(id: string): Promise<Response<Entity.Poll>> - /** - * 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<number>): Promise<Response<Entity.Poll>> - // ====================================== - // 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<Response<Array<Entity.ScheduledStatus>>> - /** - * GET /api/v1/scheduled_statuses/:id - * - * @param id Target status ID. - * @return ScheduledStatus. - */ - getScheduledStatus(id: string): Promise<Response<Entity.ScheduledStatus>> - /** - * 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<Response<Entity.ScheduledStatus>> - /** - * DELETE /api/v1/scheduled_statuses/:id - * - * @param id Target scheduled status ID. - */ - cancelScheduledStatus(id: string): Promise<Response<{}>> - // ====================================== - // 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<Response<Array<Entity.Status>>> - /** - * 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<Response<Array<Entity.Status>>> - /** - * 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<Response<Array<Entity.Status>>> - /** - * 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<Response<Array<Entity.Status>>> - /** - * 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<Response<Array<Entity.Status>>> - // ====================================== - // 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<Response<Array<Entity.Conversation>>> - /** - * DELETE /api/v1/conversations/:id - * - * @param id Target conversation ID. - */ - deleteConversation(id: string): Promise<Response<{}>> - /** - * POST /api/v1/conversations/:id/read - * - * @param id Target conversation ID. - * @return Conversation. - */ - readConversation(id: string): Promise<Response<Entity.Conversation>> - // ====================================== - // timelines/lists - // ====================================== - /** - * GET /api/v1/lists - * - * @return Array of lists. - */ - getLists(): Promise<Response<Array<Entity.List>>> - /** - * GET /api/v1/lists/:id - * - * @param id Target list ID. - * @return List. - */ - getList(id: string): Promise<Response<Entity.List>> - /** - * POST /api/v1/lists - * - * @param title List name. - * @return List. - */ - createList(title: string): Promise<Response<Entity.List>> - /** - * PUT /api/v1/lists/:id - * - * @param id Target list ID. - * @param title New list name. - * @return List. - */ - updateList(id: string, title: string): Promise<Response<Entity.List>> - /** - * DELETE /api/v1/lists/:id - * - * @param id Target list ID. - */ - deleteList(id: string): Promise<Response<{}>> - /** - * 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<Response<Array<Entity.Account>>> - /** - * 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<string>): Promise<Response<{}>> - /** - * 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<string>): Promise<Response<{}>> - // ====================================== - // 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<string>): Promise<Response<Entity.Marker | {}>> - /** - * 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<Response<Entity.Marker>> - // ====================================== - // 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<Entity.NotificationType> - account_id?: string - }): Promise<Response<Array<Entity.Notification>>> - /** - * GET /api/v1/notifications/:id - * - * @param id Target notification ID. - * @return Notification. - */ - getNotification(id: string): Promise<Response<Entity.Notification>> - /** - * POST /api/v1/notifications/clear - */ - dismissNotifications(): Promise<Response<{}>> - /** - * POST /api/v1/notifications/:id/dismiss - * - * @param id Target notification ID. - */ - dismissNotification(id: string): Promise<Response<{}>> - /** - * 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<Entity.Notification | Array<Entity.Notification>>> - // ====================================== - // 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<Response<Entity.PushSubscription>> - /** - * GET /api/v1/push/subscription - * - * @return PushSubscription. - */ - getPushSubscription(): Promise<Response<Entity.PushSubscription>> - /** - * 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<Response<Entity.PushSubscription>> - /** - * DELETE /api/v1/push/subscription - */ - deletePushSubscription(): Promise<Response<{}>> - // ====================================== - // 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<Response<Entity.Results>> + editStatus( + id: string, + options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array<string>; + poll?: { + options?: Array<string>; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }, + ): Promise<Response<Entity.Status>>; + /** + * DELETE /api/v1/statuses/:id + * + * @param id The target status id. + * @return Status + */ + deleteStatus(id: string): Promise<Response<{}>>; + /** + * 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<Response<Entity.Context>>; + /** + * GET /api/v1/statuses/:id/history + * + * Get status edit history. + * @param id The target status id. + * @return StatusEdit + */ + getStatusHistory(id: string): Promise<Response<Array<Entity.StatusEdit>>>; + /** + * GET /api/v1/statuses/:id/reblogged_by + * + * @param id The target status id. + * @return Array of accounts. + */ + getStatusRebloggedBy(id: string): Promise<Response<Array<Entity.Account>>>; + /** + * GET /api/v1/statuses/:id/favourited_by + * + * @param id The target status id. + * @return Array of accounts. + */ + getStatusFavouritedBy(id: string): Promise<Response<Array<Entity.Account>>>; + /** + * POST /api/v1/statuses/:id/favourite + * + * @param id The target status id. + * @return Status. + */ + favouriteStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/unfavourite + * + * @param id The target status id. + * @return Status. + */ + unfavouriteStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/reblog + * + * @param id The target status id. + * @return Status. + */ + reblogStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/unreblog + * + * @param id The target status id. + * @return Status. + */ + unreblogStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/bookmark + * + * @param id The target status id. + * @return Status. + */ + bookmarkStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/unbookmark + * + * @param id The target status id. + * @return Status. + */ + unbookmarkStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/mute + * + * @param id The target status id. + * @return Status + */ + muteStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/unmute + * + * @param id The target status id. + * @return Status + */ + unmuteStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/pin + * @param id The target status id. + * @return Status + */ + pinStatus(id: string): Promise<Response<Entity.Status>>; + /** + * POST /api/v1/statuses/:id/unpin + * + * @param id The target status id. + * @return Status + */ + unpinStatus(id: string): Promise<Response<Entity.Status>>; + // ====================================== + // 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<Response<Entity.Attachment | Entity.AsyncAttachment>>; + /** + * GET /api/v1/media/:id + * + * @param id Target media ID. + * @return Attachment + */ + getMedia(id: string): Promise<Response<Entity.Attachment>>; + /** + * 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<Response<Entity.Attachment>>; + // ====================================== + // statuses/polls + // ====================================== + /** + * GET /api/v1/polls/:id + * + * @param id Target poll ID. + * @return Poll + */ + getPoll(id: string): Promise<Response<Entity.Poll>>; + /** + * 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<number>): Promise<Response<Entity.Poll>>; + // ====================================== + // 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<Response<Array<Entity.ScheduledStatus>>>; + /** + * GET /api/v1/scheduled_statuses/:id + * + * @param id Target status ID. + * @return ScheduledStatus. + */ + getScheduledStatus(id: string): Promise<Response<Entity.ScheduledStatus>>; + /** + * 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<Response<Entity.ScheduledStatus>>; + /** + * DELETE /api/v1/scheduled_statuses/:id + * + * @param id Target scheduled status ID. + */ + cancelScheduledStatus(id: string): Promise<Response<{}>>; + // ====================================== + // 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<Response<Array<Entity.Status>>>; + /** + * 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<Response<Array<Entity.Status>>>; + /** + * 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<Response<Array<Entity.Status>>>; + /** + * 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<Response<Array<Entity.Status>>>; + /** + * 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<Response<Array<Entity.Status>>>; + // ====================================== + // 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<Response<Array<Entity.Conversation>>>; + /** + * DELETE /api/v1/conversations/:id + * + * @param id Target conversation ID. + */ + deleteConversation(id: string): Promise<Response<{}>>; + /** + * POST /api/v1/conversations/:id/read + * + * @param id Target conversation ID. + * @return Conversation. + */ + readConversation(id: string): Promise<Response<Entity.Conversation>>; + // ====================================== + // timelines/lists + // ====================================== + /** + * GET /api/v1/lists + * + * @return Array of lists. + */ + getLists(): Promise<Response<Array<Entity.List>>>; + /** + * GET /api/v1/lists/:id + * + * @param id Target list ID. + * @return List. + */ + getList(id: string): Promise<Response<Entity.List>>; + /** + * POST /api/v1/lists + * + * @param title List name. + * @return List. + */ + createList(title: string): Promise<Response<Entity.List>>; + /** + * PUT /api/v1/lists/:id + * + * @param id Target list ID. + * @param title New list name. + * @return List. + */ + updateList(id: string, title: string): Promise<Response<Entity.List>>; + /** + * DELETE /api/v1/lists/:id + * + * @param id Target list ID. + */ + deleteList(id: string): Promise<Response<{}>>; + /** + * 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<Response<Array<Entity.Account>>>; + /** + * 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<string>, + ): Promise<Response<{}>>; + /** + * 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<string>, + ): Promise<Response<{}>>; + // ====================================== + // 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<string>): Promise<Response<Entity.Marker | {}>>; + /** + * 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<Response<Entity.Marker>>; + // ====================================== + // 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<Entity.NotificationType>; + account_id?: string; + }): Promise<Response<Array<Entity.Notification>>>; + /** + * GET /api/v1/notifications/:id + * + * @param id Target notification ID. + * @return Notification. + */ + getNotification(id: string): Promise<Response<Entity.Notification>>; + /** + * POST /api/v1/notifications/clear + */ + dismissNotifications(): Promise<Response<{}>>; + /** + * POST /api/v1/notifications/:id/dismiss + * + * @param id Target notification ID. + */ + dismissNotification(id: string): Promise<Response<{}>>; + /** + * 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<Entity.Notification | Array<Entity.Notification>> + >; + // ====================================== + // 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<Response<Entity.PushSubscription>>; + /** + * GET /api/v1/push/subscription + * + * @return PushSubscription. + */ + getPushSubscription(): Promise<Response<Entity.PushSubscription>>; + /** + * 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<Response<Entity.PushSubscription>>; + /** + * DELETE /api/v1/push/subscription + */ + deletePushSubscription(): Promise<Response<{}>>; + // ====================================== + // 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<Response<Entity.Results>>; - // ====================================== - // instance - // ====================================== - /** - * GET /api/v1/instance - */ - getInstance(): Promise<Response<Entity.Instance>> + // ====================================== + // instance + // ====================================== + /** + * GET /api/v1/instance + */ + getInstance(): Promise<Response<Entity.Instance>>; - /** - * GET /api/v1/instance/peers - */ - getInstancePeers(): Promise<Response<Array<string>>> + /** + * GET /api/v1/instance/peers + */ + getInstancePeers(): Promise<Response<Array<string>>>; - /** - * GET /api/v1/instance/activity - */ - getInstanceActivity(): Promise<Response<Array<Entity.Activity>>> + /** + * GET /api/v1/instance/activity + */ + getInstanceActivity(): Promise<Response<Array<Entity.Activity>>>; - // ====================================== - // instance/trends - // ====================================== - /** - * GET /api/v1/trends - * - * @param limit Maximum number of results to return. Defaults to 10. - */ - getInstanceTrends(limit?: number | null): Promise<Response<Array<Entity.Tag>>> + // ====================================== + // instance/trends + // ====================================== + /** + * GET /api/v1/trends + * + * @param limit Maximum number of results to return. Defaults to 10. + */ + getInstanceTrends( + limit?: number | null, + ): Promise<Response<Array<Entity.Tag>>>; - // ====================================== - // 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<Response<Array<Entity.Account>>> + // ====================================== + // 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<Response<Array<Entity.Account>>>; - // ====================================== - // instance/custom_emojis - // ====================================== - /** - * GET /api/v1/custom_emojis - * - * @return Array of emojis. - */ - getInstanceCustomEmojis(): Promise<Response<Array<Entity.Emoji>>> + // ====================================== + // instance/custom_emojis + // ====================================== + /** + * GET /api/v1/custom_emojis + * + * @return Array of emojis. + */ + getInstanceCustomEmojis(): Promise<Response<Array<Entity.Emoji>>>; - // ====================================== - // 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<Response<Array<Entity.Announcement>>> + // ====================================== + // 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<Response<Array<Entity.Announcement>>>; - /** - * POST /api/v1/announcements/:id/dismiss - */ - dismissInstanceAnnouncement(id: string): Promise<Response<{}>> + /** + * POST /api/v1/announcements/:id/dismiss + */ + dismissInstanceAnnouncement(id: string): Promise<Response<{}>>; - // ====================================== - // Emoji reactions - // ====================================== - createEmojiReaction(id: string, emoji: string): Promise<Response<Entity.Status>> - deleteEmojiReaction(id: string, emoji: string): Promise<Response<Entity.Status>> - getEmojiReactions(id: string): Promise<Response<Array<Entity.Reaction>>> - getEmojiReaction(id: string, emoji: string): Promise<Response<Entity.Reaction>> + // ====================================== + // Emoji reactions + // ====================================== + createEmojiReaction( + id: string, + emoji: string, + ): Promise<Response<Entity.Status>>; + deleteEmojiReaction( + id: string, + emoji: string, + ): Promise<Response<Entity.Status>>; + getEmojiReactions(id: string): Promise<Response<Array<Entity.Reaction>>>; + getEmojiReaction( + id: string, + emoji: string, + ): Promise<Response<Entity.Reaction>>; - // ====================================== - // WebSocket - // ====================================== - userSocket(): WebSocketInterface - publicSocket(): WebSocketInterface - localSocket(): WebSocketInterface - tagSocket(tag: string): WebSocketInterface - listSocket(list_id: string): WebSocketInterface - directSocket(): WebSocketInterface + // ====================================== + // 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) + constructor(err?: string) { + super(err); - this.name = new.target.name - Object.setPrototypeOf(this, new.target.prototype) - } + this.name = new.target.name; + Object.setPrototypeOf(this, new.target.prototype); + } } export class ArgumentError extends Error { - constructor(err?: string) { - super(err) + constructor(err?: string) { + super(err); - this.name = new.target.name - Object.setPrototypeOf(this, new.target.prototype) - } + this.name = new.target.name; + Object.setPrototypeOf(this, new.target.prototype); + } } export class UnexpectedError extends Error { - constructor(err?: string) { - super(err) + constructor(err?: string) { + super(err); - this.name = new.target.name - Object.setPrototypeOf(this, new.target.prototype) - } + this.name = new.target.name; + Object.setPrototypeOf(this, new.target.prototype); + } } type Instance = { - title: string - uri: string - urls: { - streaming_api: string - } - version: string -} + title: string; + uri: string; + urls: { + streaming_api: string; + }; + version: string; +}; /** * Detect SNS type. @@ -1353,29 +1470,32 @@ type Instance = { * @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<Instance>(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' - } -} +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<Instance>(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. @@ -1387,10 +1507,11 @@ export const detector = async (url: string, proxyConfig: ProxyConfig | false = f * @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) + baseUrl: string, + accessToken: string | null = null, + userAgent: string | null = null, + proxyConfig: ProxyConfig | false = false, +): MegalodonInterface => + new Misskey(baseUrl, accessToken, userAgent, proxyConfig); -export default generator +export default generator; diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index ca418439e..faae6e56a 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1,109 +1,130 @@ -import FormData from 'form-data' -import AsyncLock from 'async-lock'; +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 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[] -} + 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 + public client: MisskeyAPI.Interface; + public converter: MisskeyAPI.Converter; + public baseUrl: string; + public proxyConfig: ProxyConfig | false; - /** - * @param baseUrl hostname or base URL - * @param accessToken access token from OAuth2 authorization - * @param userAgent UserAgent is specified in header on request. - * @param proxyConfig Proxy setting, or set false if don't use proxy. - */ - constructor( - baseUrl: string, - accessToken: string | null = null, - userAgent: string | null = DEFAULT_UA, - proxyConfig: ProxyConfig | false = false - ) { - let token: string = '' - if (accessToken) { - token = accessToken - } - let agent: string = DEFAULT_UA - if (userAgent) { - agent = userAgent - } - this.converter = new MisskeyAPI.Converter(baseUrl) - this.client = new MisskeyAPI.Client(baseUrl, token, agent, proxyConfig, this.converter) - this.baseUrl = baseUrl - this.proxyConfig = proxyConfig - } + /** + * @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://', '') - } + private baseUrlToHost(baseUrl: string): string { + return baseUrl.replace("https://", ""); + } - public cancel(): void { - return this.client.cancel() - } + public cancel(): void { + return this.client.cancel(); + } - public async registerApp( - client_name: string, - options: Partial<{ scopes: Array<string>; redirect_uris: string; website: string }> = { - scopes: MisskeyAPI.DEFAULT_SCOPE, - redirect_uris: this.baseUrl - } - ): Promise<OAuth.AppData> { - 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 - }) - }) - } + public async registerApp( + client_name: string, + options: Partial<{ + scopes: Array<string>; + redirect_uris: string; + website: string; + }> = { + scopes: MisskeyAPI.DEFAULT_SCOPE, + redirect_uris: this.baseUrl, + }, + ): Promise<OAuth.AppData> { + 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<string>; + redirect_uris: string; + website: string; + }> = { + scopes: MisskeyAPI.DEFAULT_SCOPE, + redirect_uris: this.baseUrl, + }, + ): Promise<OAuth.AppData> { + const redirect_uris = options.redirect_uris || this.baseUrl; + const scopes = options.scopes || MisskeyAPI.DEFAULT_SCOPE; - /** - * 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<string>; redirect_uris: string; website: string }> = { - scopes: MisskeyAPI.DEFAULT_SCOPE, - redirect_uris: this.baseUrl - } - ): Promise<OAuth.AppData> { - const redirect_uris = options.redirect_uris || this.baseUrl - const scopes = options.scopes || MisskeyAPI.DEFAULT_SCOPE + const params: { + name: string; + description: string; + permission: Array<string>; + callbackUrl: string; + } = { + name: client_name, + description: "", + permission: scopes, + callbackUrl: redirect_uris, + }; - const params: { - name: string - description: string - permission: Array<string> - callbackUrl: string - } = { - name: client_name, - description: '', - permission: scopes, - callbackUrl: redirect_uris - } - - /** + /** * The response is: { "id": "xxxxxxxxxx", @@ -115,1148 +136,1362 @@ export default class Misskey implements MegalodonInterface { "secret": "string" } */ - return this.client.post<MisskeyAPI.Entity.App>('/api/app/create', params).then((res: Response<MisskeyAPI.Entity.App>) => { - 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) - }) - } + return this.client + .post<MisskeyAPI.Entity.App>("/api/app/create", params) + .then((res: Response<MisskeyAPI.Entity.App>) => { + 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<MisskeyAPI.Entity.Session> { - return this.client - .post<MisskeyAPI.Entity.Session>('/api/auth/session/generate', { - appSecret: clientSecret - }) - .then((res: Response<MisskeyAPI.Entity.Session>) => res.data) - } - - // ====================================== - // apps - // ====================================== - public async verifyAppCredentials(): Promise<Response<Entity.Application>> { - 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<OAuth.TokenData> { - return this.client - .post<MisskeyAPI.Entity.UserKey>('/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<OAuth.TokenData> { - 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<Response<{}>> { - 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<Response<Entity.Token>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - /** - * POST /api/i - */ - public async verifyAccountCredentials(): Promise<Response<Entity.Account>> { - return this.client.post<MisskeyAPI.Entity.UserDetail>('/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<Response<Entity.Account>> { - 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<MisskeyAPI.Entity.UserDetail>('/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<Response<Entity.Account>> { - return this.client - .post<MisskeyAPI.Entity.UserDetail>('/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<Response<Entity.Account>> { - return this.client - .post<MisskeyAPI.Entity.UserDetail>('/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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); - - if (options?.pinned) { - return this.client - .post<MisskeyAPI.Entity.UserDetail>('/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<Array<MisskeyAPI.Entity.Note>>('/api/users/notes', params).then(async res => { - const statuses: Array<Entity.Status> = 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<Response<Array<Entity.Status>>> { - 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<Array<MisskeyAPI.Entity.Favorite>>('/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<Response<Entity.Relationship>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async unsubscribeAccount(_id: string): Promise<Response<Entity.Relationship>> { - 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<Response<Array<Entity.Account>>> { - 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<Array<MisskeyAPI.Entity.Follower>>('/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/auth/session/generate + */ + public async generateAuthUrlAndToken( + clientSecret: string, + ): Promise<MisskeyAPI.Entity.Session> { + return this.client + .post<MisskeyAPI.Entity.Session>("/api/auth/session/generate", { + appSecret: clientSecret, }) - }) - } + .then((res: Response<MisskeyAPI.Entity.Session>) => res.data); + } - /** - * POST /api/users/following - */ - public async getAccountFollowing( - id: string, - options?: { - limit?: number - max_id?: string - since_id?: string - } - ): Promise<Response<Array<Entity.Account>>> { - let params = { - userId: id - } - if (options) { - if (options.limit) { - params = Object.assign(params, { - limit: options.limit <= 100 ? options.limit : 100 - }) - } - } - return this.client.post<Array<MisskeyAPI.Entity.Following>>('/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)))) + // ====================================== + // apps + // ====================================== + public async verifyAppCredentials(): Promise<Response<Entity.Application>> { + 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<OAuth.TokenData> { + return this.client + .post<MisskeyAPI.Entity.UserKey>("/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 getAccountLists(_id: string): Promise<Response<Array<Entity.List>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async refreshToken( + _client_id: string, + _client_secret: string, + _refresh_token: string, + ): Promise<OAuth.TokenData> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async getIdentityProof(_id: string): Promise<Response<Array<Entity.IdentityProof>>> { - 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<Response<{}>> { + 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<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/following/create', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/api/users/relation', { - userId: id - }) - .then(res => { - return Object.assign(res, { - data: this.converter.relation(res.data) - }) - }) - } + // ====================================== + // accounts + // ====================================== + public async registerAccount( + _username: string, + _email: string, + _password: string, + _agreement: boolean, + _locale: string, + _reason?: string | null, + ): Promise<Response<Entity.Token>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - /** - * POST /api/following/delete - */ - public async unfollowAccount(id: string): Promise<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/following/delete', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/api/users/relation', { - userId: id - }) - .then(res => { - return Object.assign(res, { - data: this.converter.relation(res.data) - }) - }) - } + /** + * POST /api/i + */ + public async verifyAccountCredentials(): Promise<Response<Entity.Account>> { + return this.client + .post<MisskeyAPI.Entity.UserDetail>("/api/i") + .then((res) => { + return Object.assign(res, { + data: this.converter.userDetail( + res.data, + this.baseUrlToHost(this.baseUrl), + ), + }); + }); + } - /** - * POST /api/blocking/create - */ - public async blockAccount(id: string): Promise<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/blocking/create', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/api/users/relation', { - userId: id - }) - .then(res => { - return Object.assign(res, { - data: this.converter.relation(res.data) - }) - }) - } + /** + * 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<Response<Entity.Account>> { + 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<MisskeyAPI.Entity.UserDetail>("/api/i", params) + .then((res) => { + return Object.assign(res, { + data: this.converter.userDetail( + res.data, + this.baseUrlToHost(this.baseUrl), + ), + }); + }); + } - /** - * POST /api/blocking/delete - */ - public async unblockAccount(id: string): Promise<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/blocking/delete', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/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<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/mute/create', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/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<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/mute/delete', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/api/users/relation', { - userId: id - }) - .then(res => { - return Object.assign(res, { - data: this.converter.relation(res.data) - }) - }) - } - - public async pinAccount(_id: string): Promise<Response<Entity.Relationship>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async unpinAccount(_id: string): Promise<Response<Entity.Relationship>> { - 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<Response<Entity.Relationship>> { - return this.client - .post<MisskeyAPI.Entity.Relation>('/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<string>): Promise<Response<Array<Entity.Relationship>>> { - 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<Response<Array<Entity.Account>>> { - 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<Array<MisskeyAPI.Entity.UserDetail>>('/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<Response<Array<Entity.Status>>> { - 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<Array<MisskeyAPI.Entity.Favorite>>('/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<Response<Array<Entity.Status>>> { - const userId = await this.client.post<MisskeyAPI.Entity.UserDetail>('/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<Response<Array<Entity.Account>>> { - 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<Array<MisskeyAPI.Entity.Mute>>('/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<Response<Array<Entity.Account>>> { - 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<Array<MisskeyAPI.Entity.Blocking>>('/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<Response<Array<string>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async blockDomain(_domain: string): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async unblockDomain(_domain: string): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - // ====================================== - // accounts/filters - // ====================================== - public async getFilters(): Promise<Response<Array<Entity.Filter>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async getFilter(_id: string): Promise<Response<Entity.Filter>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async createFilter( - _phrase: string, - _context: Array<string>, - _options?: { - irreversible?: boolean - whole_word?: boolean - expires_in?: string - } - ): Promise<Response<Entity.Filter>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async updateFilter( - _id: string, - _phrase: string, - _context: Array<string>, - _options?: { - irreversible?: boolean - whole_word?: boolean - expires_in?: string - } - ): Promise<Response<Entity.Filter>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async deleteFilter(_id: string): Promise<Response<Entity.Filter>> { - 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<string> - forward?: boolean - } - ): Promise<Response<Entity.Report>> { - 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<Response<Array<Entity.Account>>> { - return this.client.post<Array<MisskeyAPI.Entity.FollowRequest>>('/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<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/following/requests/accept', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/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<Response<Entity.Relationship>> { - await this.client.post<{}>('/api/following/requests/reject', { - userId: id - }) - return this.client - .post<MisskeyAPI.Entity.Relation>('/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<Response<Array<Entity.Account>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - // ====================================== - // accounts/featured_tags - // ====================================== - public async getFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> { - return this.getAccountFeaturedTags(); - } - - public async getAccountFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> { - 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<Response<Entity.FeaturedTag>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async deleteFeaturedTag(_id: string): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - public async getSuggestedTags(): Promise<Response<Array<Entity.Tag>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } - - // ====================================== - // accounts/preferences - // ====================================== - public async getPreferences(): Promise<Response<Entity.Preferences>> { - return this.client.post<MisskeyAPI.Entity.UserDetailMe>('/api/i').then(async res => { - return Object.assign(res, { - data: this.converter.userPreferences(res.data, await this.getDefaultPostPrivacy()) + /** + * POST /api/users/show + */ + public async getAccount(id: string): Promise<Response<Entity.Account>> { + return this.client + .post<MisskeyAPI.Entity.UserDetail>("/api/users/show", { + userId: id, }) - }) - } + .then((res) => { + return Object.assign(res, { + data: this.converter.userDetail( + res.data, + this.baseUrlToHost(this.baseUrl), + ), + }); + }); + } - // ====================================== - // accounts/suggestions - // ====================================== - /** - * POST /api/users/recommendation - */ - public async getSuggestions(limit?: number): Promise<Response<Array<Entity.Account>>> { - let params = {} - if (limit) { - params = Object.assign(params, { - limit: limit - }) - } - return this.client - .post<Array<MisskeyAPI.Entity.UserDetail>>('/api/users/recommendation', params) - .then(res => ({ ...res, data: res.data.map(u => this.converter.userDetail(u, this.baseUrlToHost(this.baseUrl))) })) - } + public async getAccountByName( + user: string, + host: string | null, + ): Promise<Response<Entity.Account>> { + return this.client + .post<MisskeyAPI.Entity.UserDetail>("/api/users/show", { + username: user, + host: host ?? null, + }) + .then((res) => { + return Object.assign(res, { + data: this.converter.userDetail( + res.data, + this.baseUrlToHost(this.baseUrl), + ), + }); + }); + } - // ====================================== - // accounts/tags - // ====================================== - public async getFollowedTags(): Promise<Response<Array<Entity.Tag>>> { - const tags : Entity.Tag[] = []; - const res : Response = { - headers: undefined, - statusText: "", - status: 200, - data: tags - }; - return new Promise(resolve => resolve(res)) - } + /** + * 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<Response<Array<Entity.Status>>> { + const accountCache = this.getFreshAccountCache(); - public async getTag(_id: string): Promise<Response<Entity.Tag>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + if (options?.pinned) { + return this.client + .post<MisskeyAPI.Entity.UserDetail>("/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: [] }; + }); + } - public async followTag(_id: string): Promise<Response<Entity.Tag>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + 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<Array<MisskeyAPI.Entity.Note>>("/api/users/notes", params) + .then(async (res) => { + const statuses: Array<Entity.Status> = await Promise.all( + res.data.map((note) => + this.noteWithDetails( + note, + this.baseUrlToHost(this.baseUrl), + accountCache, + ), + ), + ); + return Object.assign(res, { + data: statuses, + }); + }); + } - public async unfollowTag(_id: string): Promise<Response<Entity.Tag>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async getAccountFavourites( + id: string, + options?: { + limit?: number; + max_id?: string; + since_id?: string; + }, + ): Promise<Response<Array<Entity.Status>>> { + const accountCache = this.getFreshAccountCache(); - // ====================================== - // statuses - // ====================================== - public async postStatus( - status: string, - options?: { - media_ids?: Array<string> - poll?: { options: Array<string>; 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<Response<Entity.Status>> { - 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<MisskeyAPI.Entity.CreatedNote>('/api/notes/create', params) - .then(async res => ({ - ...res, - data: await this.noteWithDetails(res.data.createdNote, this.baseUrlToHost(this.baseUrl), 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<Array<MisskeyAPI.Entity.Favorite>>("/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, + ), + ), + ), + }); + }); + } - /** - * POST /api/notes/show - */ - public async getStatus(id: string): Promise<Response<Entity.Status>> { - return this.client - .post<MisskeyAPI.Entity.Note>('/api/notes/show', { - noteId: id - }) - .then(async res => ({ ...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); - } + public async subscribeAccount( + _id: string, + ): Promise<Response<Entity.Relationship>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - private getFreshAccountCache() :AccountCache { - return { - locks: new AsyncLock(), - accounts: [] - } - } + public async unsubscribeAccount( + _id: string, + ): Promise<Response<Entity.Relationship>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async notificationWithDetails(n: MisskeyAPI.Entity.Notification, host: string, cache: AccountCache): Promise<MegalodonEntity.Notification> { + /** + * POST /api/users/followers + */ + public async getAccountFollowers( + id: string, + options?: { + limit?: number; + max_id?: string; + since_id?: string; + }, + ): Promise<Response<Array<Entity.Account>>> { + 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<Array<MisskeyAPI.Entity.Follower>>("/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<Response<Array<Entity.Account>>> { + let params = { + userId: id, + }; + if (options) { + if (options.limit) { + params = Object.assign(params, { + limit: options.limit <= 100 ? options.limit : 100, + }); + } + } + return this.client + .post<Array<MisskeyAPI.Entity.Following>>("/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<Response<Array<Entity.List>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async getIdentityProof( + _id: string, + ): Promise<Response<Array<Entity.IdentityProof>>> { + 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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/following/create", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/following/delete", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/blocking/create", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/blocking/delete", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/mute/create", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/mute/delete", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/api/users/relation", { + userId: id, + }) + .then((res) => { + return Object.assign(res, { + data: this.converter.relation(res.data), + }); + }); + } + + public async pinAccount(_id: string): Promise<Response<Entity.Relationship>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async unpinAccount( + _id: string, + ): Promise<Response<Entity.Relationship>> { + 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<Response<Entity.Relationship>> { + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<string>, + ): Promise<Response<Array<Entity.Relationship>>> { + 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<Response<Array<Entity.Account>>> { + 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<Array<MisskeyAPI.Entity.UserDetail>>("/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<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Favorite>>("/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<Response<Array<Entity.Status>>> { + const userId = await this.client + .post<MisskeyAPI.Entity.UserDetail>("/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<Response<Array<Entity.Account>>> { + 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<Array<MisskeyAPI.Entity.Mute>>("/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<Response<Array<Entity.Account>>> { + 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<Array<MisskeyAPI.Entity.Blocking>>("/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<Response<Array<string>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async blockDomain(_domain: string): Promise<Response<{}>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async unblockDomain(_domain: string): Promise<Response<{}>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + // ====================================== + // accounts/filters + // ====================================== + public async getFilters(): Promise<Response<Array<Entity.Filter>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async getFilter(_id: string): Promise<Response<Entity.Filter>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async createFilter( + _phrase: string, + _context: Array<string>, + _options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }, + ): Promise<Response<Entity.Filter>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async updateFilter( + _id: string, + _phrase: string, + _context: Array<string>, + _options?: { + irreversible?: boolean; + whole_word?: boolean; + expires_in?: string; + }, + ): Promise<Response<Entity.Filter>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async deleteFilter(_id: string): Promise<Response<Entity.Filter>> { + 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<string>; + forward?: boolean; + }, + ): Promise<Response<Entity.Report>> { + 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<Response<Array<Entity.Account>>> { + return this.client + .post<Array<MisskeyAPI.Entity.FollowRequest>>( + "/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/following/requests/accept", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Entity.Relationship>> { + await this.client.post<{}>("/api/following/requests/reject", { + userId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Relation>("/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<Response<Array<Entity.Account>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + // ====================================== + // accounts/featured_tags + // ====================================== + public async getFeaturedTags(): Promise<Response<Array<Entity.FeaturedTag>>> { + return this.getAccountFeaturedTags(); + } + + public async getAccountFeaturedTags(): Promise< + Response<Array<Entity.FeaturedTag>> + > { + 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<Response<Entity.FeaturedTag>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async deleteFeaturedTag(_id: string): Promise<Response<{}>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async getSuggestedTags(): Promise<Response<Array<Entity.Tag>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + // ====================================== + // accounts/preferences + // ====================================== + public async getPreferences(): Promise<Response<Entity.Preferences>> { + return this.client + .post<MisskeyAPI.Entity.UserDetailMe>("/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<Response<Array<Entity.Account>>> { + let params = {}; + if (limit) { + params = Object.assign(params, { + limit: limit, + }); + } + return this.client + .post<Array<MisskeyAPI.Entity.UserDetail>>( + "/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<Response<Array<Entity.Tag>>> { + 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<Response<Entity.Tag>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async followTag(_id: string): Promise<Response<Entity.Tag>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async unfollowTag(_id: string): Promise<Response<Entity.Tag>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + // ====================================== + // statuses + // ====================================== + public async postStatus( + status: string, + options?: { + media_ids?: Array<string>; + poll?: { + options: Array<string>; + 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<Response<Entity.Status>> { + 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<MisskeyAPI.Entity.CreatedNote>("/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<Response<Entity.Status>> { + return this.client + .post<MisskeyAPI.Entity.Note>("/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<MegalodonEntity.Notification> { 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 + notification.account = ( + await this.getAccount(notification.account.id) + ).data; return notification; } - public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise<MegalodonEntity.Status> { - const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); + public async noteWithDetails( + n: MisskeyAPI.Entity.Note, + host: string, + cache: AccountCache, + ): Promise<MegalodonEntity.Status> { + 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<boolean> { - return this.client - .post<MisskeyAPI.Entity.State>('/api/notes/state', { - noteId: id - }).then(p => p.data.isFavorited ?? false); + return this.addMentionsToStatus(status, cache); } - public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise<Entity.Status> { - 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; + public async isStatusBookmarked(id: string): Promise<boolean> { + return this.client + .post<MisskeyAPI.Entity.State>("/api/notes/state", { + noteId: id, + }) + .then((p) => p.data.isFavorited ?? false); + } + + public async addUserDetailsToStatus( + status: Entity.Status, + cache: AccountCache, + ): Promise<Entity.Status> { + 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); @@ -1267,9 +1502,11 @@ export default class Misskey implements MegalodonInterface { return status; } - public async addMentionsToStatus(status: Entity.Status, cache: AccountCache) : Promise<Entity.Status> { - if (status.mentions.length > 0) - return status; + public async addMentionsToStatus( + status: Entity.Status, + cache: AccountCache, + ): Promise<Entity.Status> { + if (status.mentions.length > 0) return status; if (status.reblog != null) status.reblog = await this.addMentionsToStatus(status.reblog, cache); @@ -1277,68 +1514,92 @@ export default class Misskey implements MegalodonInterface { if (status.quote != null) status.quote = await this.addMentionsToStatus(status.quote, cache); - status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); - for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { + status.mentions = ( + await this.getMentions(status.plain_content!, cache) + ).filter((p) => p != null); + for (const m of status.mentions.filter( + (value, index, array) => array.indexOf(value) === index, + )) { if (m.acct == m.username) - status.content = status.content.replace(`@${m.acct}@${this.baseUrlToHost(this.baseUrl)}`, `@${m.acct}`); - status.content = status.content.replace(`@${m.acct}`, `<a href="${m.url}" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@${m.acct}</a>`); - } - return status; - } + status.content = status.content.replace( + `@${m.acct}@${this.baseUrlToHost(this.baseUrl)}`, + `@${m.acct}`, + ); + status.content = status.content.replace( + `@${m.acct}`, + `<a href="${m.url}" class="u-url mention" rel="nofollow noopener noreferrer" target="_blank">@${m.acct}</a>`, + ); + } + return status; + } - public async getMentions(text: string, cache: AccountCache): Promise<Entity.Mention[]> { - const mentions :Entity.Mention[] = []; + public async getMentions( + text: string, + cache: AccountCache, + ): Promise<Entity.Mention[]> { + const mentions: Entity.Mention[] = []; - if (text == undefined) - return mentions; + if (text == undefined) return mentions; - const mentionMatch = text.matchAll(/(?<=^|\s)@(?<user>.*?)(?:@(?<host>.*?)|)(?=\s|$)/g); + const mentionMatch = text.matchAll( + /(?<=^|\s)@(?<user>.*?)(?:@(?<host>.*?)|)(?=\s|$)/g, + ); - for (const m of mentionMatch) { + for (const m of mentionMatch) { try { - if (m.groups == null) - continue; + if (m.groups == null) continue; - const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); + const account = await this.getAccountByNameCached( + m.groups.user, + m.groups.host, + cache, + ); - if (account == null) - continue; + if (account == null) continue; mentions.push({ id: account.id, url: account.url, username: account.username, - acct: account.acct + acct: account.acct, }); + } catch {} + } + + return mentions; + } + + public async getAccountByNameCached( + user: string, + host: string | null, + cache: AccountCache, + ): Promise<Entity.Account | undefined | null> { + 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; } - catch {} - } - return mentions; - } + if (cacheHit == null) { + cache.accounts.push(account); + } - public async getAccountByNameCached(user: string, host: string | null, cache: AccountCache): Promise<Entity.Account | undefined | null> { - const acctToFind = host == null ? user : `${user}@${host}`; + return account; + }); + } - 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<Entity.Account | undefined | null> { + public async getAccountCached( + id: string, + acct: string, + cache: AccountCache, + ): Promise<Entity.Account | undefined | null> { return await cache.locks.acquire(acct, async () => { - const cacheHit = cache.accounts.find(p => p.id === id); + const cacheHit = cache.accounts.find((p) => p.id === id); const account = cacheHit ?? (await this.getAccount(id)).data; if (!account) { @@ -1350,1440 +1611,1738 @@ export default class Misskey implements MegalodonInterface { } return account; - }) + }); } - public async editStatus( - _id: string, - _options: { - status?: string - spoiler_text?: string - sensitive?: boolean - media_ids?: Array<string> - poll?: { options?: Array<string>; expires_in?: number; multiple?: boolean; hide_totals?: boolean } - } - ): Promise<Response<Entity.Status>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async editStatus( + _id: string, + _options: { + status?: string; + spoiler_text?: string; + sensitive?: boolean; + media_ids?: Array<string>; + poll?: { + options?: Array<string>; + expires_in?: number; + multiple?: boolean; + hide_totals?: boolean; + }; + }, + ): Promise<Response<Entity.Status>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - /** - * POST /api/notes/delete - */ - public async deleteStatus(id: string): Promise<Response<{}>> { - return this.client.post<{}>('/api/notes/delete', { - noteId: id - }) - } + /** + * POST /api/notes/delete + */ + public async deleteStatus(id: string): Promise<Response<{}>> { + 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<Response<Entity.Context>> { - 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<Array<MisskeyAPI.Entity.Note>>('/api/notes/children', params).then(async res => { - const accountCache = this.getFreshAccountCache(); - const conversation = await this.client.post<Array<MisskeyAPI.Entity.Note>>('/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<Response<Array<Entity.StatusEdit>>> { - // 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<Response<Array<Entity.Account>>> { - return this.client - .post<Array<MisskeyAPI.Entity.Note>>('/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<Response<Array<Entity.Account>>> { + /** + * POST /api/notes/children + */ + public async getStatusContext( + id: string, + options?: { limit?: number; max_id?: string; since_id?: string }, + ): Promise<Response<Entity.Context>> { + 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<Array<MisskeyAPI.Entity.Reaction>>('/api/notes/reactions', { - noteId: id + .post<Array<MisskeyAPI.Entity.Note>>("/api/notes/children", params) + .then(async (res) => { + const accountCache = this.getFreshAccountCache(); + const conversation = await this.client.post< + Array<MisskeyAPI.Entity.Note> + >("/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<Response<Array<Entity.StatusEdit>>> { + // 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<Response<Array<Entity.Account>>> { + return this.client + .post<Array<MisskeyAPI.Entity.Note>>("/api/notes/renotes", { + noteId: id, }) - .then(async res => ({ + .then(async (res) => ({ ...res, - data: (await Promise.all(res.data.map(n => this.getAccount(n.user.id)))).map(p => p.data) - })) - } + data: ( + await Promise.all(res.data.map((n) => this.getAccount(n.user.id))) + ).map((p) => p.data), + })); + } - public async favouriteStatus(id: string): Promise<Response<Entity.Status>> { - return this.createEmojiReaction(id, await this.getDefaultFavoriteEmoji()); - } + public async getStatusFavouritedBy( + id: string, + ): Promise<Response<Array<Entity.Account>>> { + return this.client + .post<Array<MisskeyAPI.Entity.Reaction>>("/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), + })); + } - private async getDefaultFavoriteEmoji(): Promise<string> { - // 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. + public async favouriteStatus(id: string): Promise<Response<Entity.Status>> { + return this.createEmojiReaction(id, await this.getDefaultFavoriteEmoji()); + } - return await this.client - .post<Array<string>>('/api/i/registry/get-unsecure', { - key: 'reactions', - scope: ['client', 'base'], - }) - .then(res => res.data[0] ?? '⭐'); - } + private async getDefaultFavoriteEmoji(): Promise<string> { + // 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. - private async getDefaultPostPrivacy(): Promise<'public' | 'unlisted' | 'private' | 'direct'> { + return await this.client + .post<Array<string>>("/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<string>('/api/i/registry/get-unsecure', { - key: 'defaultNoteVisibility', - scope: ['client', 'base'], + .post<string>("/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'; + .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') + }) + .catch((_) => "public"); } - public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> { - // NOTE: Misskey allows only one reaction per status, so we don't need to care what that emoji was. - return this.deleteEmojiReaction(id, ''); - } + public async unfavouriteStatus(id: string): Promise<Response<Entity.Status>> { + // 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<Response<Entity.Status>> { - return this.client - .post<MisskeyAPI.Entity.CreatedNote>('/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/create + */ + public async reblogStatus(id: string): Promise<Response<Entity.Status>> { + return this.client + .post<MisskeyAPI.Entity.CreatedNote>("/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<Response<Entity.Status>> { - await this.client.post<{}>('/api/notes/unrenote', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/api/notes/show', { - noteId: id - }) - .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) - } + /** + * POST /api/notes/unrenote + */ + public async unreblogStatus(id: string): Promise<Response<Entity.Status>> { + await this.client.post<{}>("/api/notes/unrenote", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Status>> { - await this.client.post<{}>('/api/notes/favorites/create', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/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<Response<Entity.Status>> { + await this.client.post<{}>("/api/notes/favorites/create", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Status>> { - await this.client.post<{}>('/api/notes/favorites/delete', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/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<Response<Entity.Status>> { + await this.client.post<{}>("/api/notes/favorites/delete", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Status>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async muteStatus(_id: string): Promise<Response<Entity.Status>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async unmuteStatus(_id: string): Promise<Response<Entity.Status>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async unmuteStatus(_id: string): Promise<Response<Entity.Status>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - /** - * POST /api/i/pin - */ - public async pinStatus(id: string): Promise<Response<Entity.Status>> { - await this.client.post<{}>('/api/i/pin', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/api/notes/show', { - noteId: id - }) - .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) - } + /** + * POST /api/i/pin + */ + public async pinStatus(id: string): Promise<Response<Entity.Status>> { + await this.client.post<{}>("/api/i/pin", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Status>> { - await this.client.post<{}>('/api/i/unpin', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/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<Response<Entity.Status>> { + await this.client.post<{}>("/api/i/unpin", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Attachment>> { - const formData = new FormData() - formData.append('file', fs.createReadStream(file.path), { - contentType: file.mimetype - }) + // ====================================== + // statuses/media + // ====================================== + /** + * POST /api/drive/files/create + */ + public async uploadMedia( + file: any, + options?: { description?: string; focus?: string }, + ): Promise<Response<Entity.Attachment>> { + 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 (file.originalname != null && file.originalname !== "file") + formData.append("name", file.originalname); if (options?.description != null) - formData.append('comment', options.description); + formData.append("comment", options.description); - let headers: { [key: string]: string } = {} - if (typeof formData.getHeaders === 'function') { - headers = formData.getHeaders() - } - return this.client - .post<MisskeyAPI.Entity.File>('/api/drive/files/create', formData, headers) - .then(res => ({ ...res, data: this.converter.file(res.data) })) + let headers: { [key: string]: string } = {}; + if (typeof formData.getHeaders === "function") { + headers = formData.getHeaders(); + } + return this.client + .post<MisskeyAPI.Entity.File>( + "/api/drive/files/create", + formData, + headers, + ) + .then((res) => ({ ...res, data: this.converter.file(res.data) })); } - public async getMedia(id: string): Promise<Response<Entity.Attachment>> { - const res = await this.client.post<MisskeyAPI.Entity.File>('/api/drive/files/show', { fileId: id }) - return { ...res, data: this.converter.file(res.data) } - } + public async getMedia(id: string): Promise<Response<Entity.Attachment>> { + const res = await this.client.post<MisskeyAPI.Entity.File>( + "/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<Response<Entity.Attachment>> { - let params = { - fileId: id - } - if (options) { - if (options.is_sensitive !== undefined) { - params = Object.assign(params, { - isSensitive: options.is_sensitive - }) - } + /** + * POST /api/drive/files/update + */ + public async updateMedia( + id: string, + options?: { + file?: any; + description?: string; + focus?: string; + is_sensitive?: boolean; + }, + ): Promise<Response<Entity.Attachment>> { + 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 - }) + comment: options.description, + }); } - } - return this.client - .post<MisskeyAPI.Entity.File>('/api/drive/files/update', params) - .then(res => ({ ...res, data: this.converter.file(res.data) })) - } + } + return this.client + .post<MisskeyAPI.Entity.File>("/api/drive/files/update", params) + .then((res) => ({ ...res, data: this.converter.file(res.data) })); + } - // ====================================== - // statuses/polls - // ====================================== - public async getPoll(id: string): Promise<Response<Entity.Poll>> { - const res = await this.getStatus(id); - if (res.data.poll == null) - throw new Error('poll not found'); - return { ...res, data: res.data.poll } - } + // ====================================== + // statuses/polls + // ====================================== + public async getPoll(id: string): Promise<Response<Entity.Poll>> { + 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<number>): Promise<Response<Entity.Poll>> { - if (!id) { - return new Promise((_, reject) => { - const err = new ArgumentError('id is required') - reject(err) - }) - } + /** + * POST /api/notes/polls/vote + */ + public async votePoll( + id: string, + choices: Array<number>, + ): Promise<Response<Entity.Poll>> { + 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) + choice: +c, + }; + await this.client.post<{}>("/api/notes/polls/vote", params); } - const res = await this.client - .post<MisskeyAPI.Entity.Note>('/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 } - } + const res = await this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Array<Entity.ScheduledStatus>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + // ====================================== + // statuses/scheduled_statuses + // ====================================== + public async getScheduledStatuses(_options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise<Response<Array<Entity.ScheduledStatus>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async getScheduledStatus(_id: string): Promise<Response<Entity.ScheduledStatus>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async getScheduledStatus( + _id: string, + ): Promise<Response<Entity.ScheduledStatus>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async scheduleStatus(_id: string, _scheduled_at?: string | null): Promise<Response<Entity.ScheduledStatus>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async scheduleStatus( + _id: string, + _scheduled_at?: string | null, + ): Promise<Response<Entity.ScheduledStatus>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async cancelScheduledStatus(_id: string): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async cancelScheduledStatus(_id: string): Promise<Response<{}>> { + 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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); + // ====================================== + // 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<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Note>>('/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) - })) - } + 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<Array<MisskeyAPI.Entity.Note>>("/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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); + /** + * POST /api/notes/local-timeline + */ + public async getLocalTimeline(options?: { + only_media?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Note>>('/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) - })) - } + 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<Array<MisskeyAPI.Entity.Note>>("/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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); + /** + * 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<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Note>>('/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) - })) - } + 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<Array<MisskeyAPI.Entity.Note>>("/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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); + /** + * POST /api/notes/timeline + */ + public async getHomeTimeline(options?: { + local?: boolean; + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Note>>('/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) - })) - } + 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<Array<MisskeyAPI.Entity.Note>>("/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<Response<Array<Entity.Status>>> { - const accountCache = this.getFreshAccountCache(); + /** + * 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<Response<Array<Entity.Status>>> { + 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<Array<MisskeyAPI.Entity.Note>>('/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) })) - } + 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<Array<MisskeyAPI.Entity.Note>>( + "/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<Response<Array<Entity.Conversation>>> { - 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<Array<MisskeyAPI.Entity.Note>>('/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 - } + // ====================================== + // timelines/conversations + // ====================================== + /** + * POST /api/notes/mentions + */ + public async getConversationTimeline(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + }): Promise<Response<Array<Entity.Conversation>>> { + 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<Array<MisskeyAPI.Entity.Note>>("/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<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async deleteConversation(_id: string): Promise<Response<{}>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async readConversation(_id: string): Promise<Response<Entity.Conversation>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async readConversation( + _id: string, + ): Promise<Response<Entity.Conversation>> { + 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; + 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<Response<Array<Entity.List>>> { - return this.client - .post<Array<MisskeyAPI.Entity.List>>('/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<Response<Entity.List>> { - return this.client - .post<MisskeyAPI.Entity.List>('/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<Response<Entity.List>> { - return this.client - .post<MisskeyAPI.Entity.List>('/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<Response<Entity.List>> { - return this.client - .post<MisskeyAPI.Entity.List>('/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<Response<{}>> { - 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<Response<Array<Entity.Account>>> { - const res = await this.client.post<MisskeyAPI.Entity.List>('/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<string>): Promise<Response<{}>> { - 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<string>): Promise<Response<{}>> { - return this.client.post<{}>('/api/users/lists/pull', { - listId: id, - userId: account_ids[0] - }) - } - - // ====================================== - // timelines/markers - // ====================================== - public async getMarkers(_timeline: Array<string>): Promise<Response<Entity.Marker | {}>> { - 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<Response<Entity.Marker>> { - 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<Entity.NotificationType> - account_id?: string - }): Promise<Response<Array<Entity.Notification>>> { - 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<Array<MisskeyAPI.Entity.Notification>>('/api/i/notifications', params) - .then(async res => ({ + // ====================================== + // timelines/lists + // ====================================== + /** + * POST /api/users/lists/list + */ + public async getLists(): Promise<Response<Array<Entity.List>>> { + return this.client + .post<Array<MisskeyAPI.Entity.List>>("/api/users/lists/list") + .then((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))) - })) - } + data: res.data.map((l) => this.converter.list(l)), + })); + } - public async getNotification(_id: string): Promise<Response<Entity.Notification>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/show + */ + public async getList(id: string): Promise<Response<Entity.List>> { + return this.client + .post<MisskeyAPI.Entity.List>("/api/users/lists/show", { + listId: id, + }) + .then((res) => ({ ...res, data: this.converter.list(res.data) })); + } - /** - * POST /api/notifications/mark-all-as-read - */ - public async dismissNotifications(): Promise<Response<{}>> { - return this.client.post<{}>('/api/notifications/mark-all-as-read') - } + /** + * POST /api/users/lists/create + */ + public async createList(title: string): Promise<Response<Entity.List>> { + return this.client + .post<MisskeyAPI.Entity.List>("/api/users/lists/create", { + name: title, + }) + .then((res) => ({ ...res, data: this.converter.list(res.data) })); + } - public async dismissNotification(_id: string): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/update + */ + public async updateList( + id: string, + title: string, + ): Promise<Response<Entity.List>> { + return this.client + .post<MisskeyAPI.Entity.List>("/api/users/lists/update", { + listId: id, + name: title, + }) + .then((res) => ({ ...res, data: this.converter.list(res.data) })); + } - public async readNotifications(_options: { - id?: string - max_id?: string - }): Promise<Response<Entity.Notification | Array<Entity.Notification>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('mastodon does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/delete + */ + public async deleteList(id: string): Promise<Response<{}>> { + return this.client.post<{}>("/api/users/lists/delete", { + listId: id, + }); + } - // ====================================== - // 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<Response<Entity.PushSubscription>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/show + */ + public async getAccountsInList( + id: string, + _options?: { + limit?: number; + max_id?: string; + since_id?: string; + }, + ): Promise<Response<Array<Entity.Account>>> { + const res = await this.client.post<MisskeyAPI.Entity.List>( + "/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) }; + } - public async getPushSubscription(): Promise<Response<Entity.PushSubscription>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/push + */ + public async addAccountsToList( + id: string, + account_ids: Array<string>, + ): Promise<Response<{}>> { + return this.client.post<{}>("/api/users/lists/push", { + listId: id, + userId: account_ids[0], + }); + } - public async updatePushSubscription( - _data?: { alerts: { follow?: boolean; favourite?: boolean; reblog?: boolean; mention?: boolean; poll?: boolean } } | null - ): Promise<Response<Entity.PushSubscription>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + /** + * POST /api/users/lists/pull + */ + public async deleteAccountsFromList( + id: string, + account_ids: Array<string>, + ): Promise<Response<{}>> { + return this.client.post<{}>("/api/users/lists/pull", { + listId: id, + userId: account_ids[0], + }); + } - /** - * DELETE /api/v1/push/subscription - */ - public async deletePushSubscription(): Promise<Response<{}>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + // ====================================== + // timelines/markers + // ====================================== + public async getMarkers( + _timeline: Array<string>, + ): Promise<Response<Entity.Marker | {}>> { + 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<Response<Entity.Results>> { - const accountCache = this.getFreshAccountCache(); + public async saveMarkers(_options?: { + home?: { last_read_id: string }; + notifications?: { last_read_id: string }; + }): Promise<Response<Entity.Marker>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - switch (type) { - case 'accounts': { + // ====================================== + // notifications + // ====================================== + /** + * POST /api/i/notifications + */ + public async getNotifications(options?: { + limit?: number; + max_id?: string; + since_id?: string; + min_id?: string; + exclude_type?: Array<Entity.NotificationType>; + account_id?: string; + }): Promise<Response<Array<Entity.Notification>>> { + 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<Array<MisskeyAPI.Entity.Notification>>( + "/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<Response<Entity.Notification>> { + 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<Response<{}>> { + return this.client.post<{}>("/api/notifications/mark-all-as-read"); + } + + public async dismissNotification(_id: string): Promise<Response<{}>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async readNotifications(_options: { + id?: string; + max_id?: string; + }): Promise<Response<Entity.Notification | Array<Entity.Notification>>> { + 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<Response<Entity.PushSubscription>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + public async getPushSubscription(): Promise< + Response<Entity.PushSubscription> + > { + 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<Response<Entity.PushSubscription>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } + + /** + * DELETE /api/v1/push/subscription + */ + public async deletePushSubscription(): Promise<Response<{}>> { + 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<Response<Entity.Results>> { + 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 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: [] + 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(/^@(?<user>.*?)(?:@(?<host>.*?)|)$/); + if (match) { + const lookupQuery = { + username: match.groups?.user, + host: match.groups?.host, }; - }) - } - 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(/^@(?<user>.*?)(?:@(?<host>.*?)|)$/); - if (match) { - const lookupQuery = { - username: match.groups?.user, - host: match.groups?.host - }; + const result = await this.client + .post<MisskeyAPI.Entity.UserDetail>( + "/api/users/show", + lookupQuery, + ) + .then((res) => ({ + ...res, + data: { + accounts: [ + this.converter.userDetail( + res.data, + this.baseUrlToHost(this.baseUrl), + ), + ], + statuses: [], + hashtags: [], + }, + })); - const result = await this.client.post<MisskeyAPI.Entity.UserDetail>('/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<Array<MisskeyAPI.Entity.UserDetail>>('/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 = { + if (result.status !== 200) { + result.status = 200; + result.statusText = "OK"; + result.data = { accounts: [], statuses: [], - hashtags: [] + hashtags: [], }; - - return res; } - const post = await this.noteWithDetails(res.data.object as MisskeyAPI.Entity.Note, this.baseUrlToHost(this.baseUrl), accountCache); + return result; + } + } catch {} - return { - ...res, - data: { - accounts: [], - statuses: options?.max_id && options.max_id >= post.id ? [] : [post], - hashtags: [] + return this.client + .post<Array<MisskeyAPI.Entity.UserDetail>>( + "/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<Array<MisskeyAPI.Entity.Note>>('/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<Array<string>>('/api/hashtags/search', params).then(res => ({ - ...res, - data: { - accounts: [], - statuses: [], - hashtags: res.data.map(h => ({ name: h, url: h, history: null, following: false })) - } - })) - } - } - } + 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<Array<MisskeyAPI.Entity.Note>>("/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<Array<string>>("/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<Response<Entity.Instance>> { - const meta = await this.client.post<MisskeyAPI.Entity.Meta>('/api/meta').then(res => res.data) - return this.client - .post<MisskeyAPI.Entity.Stats>('/api/stats') - .then(res => ({ ...res, data: this.converter.meta(meta, res.data) })) - } + // ====================================== + // instance + // ====================================== + /** + * POST /api/meta + * POST /api/stats + */ + public async getInstance(): Promise<Response<Entity.Instance>> { + const meta = await this.client + .post<MisskeyAPI.Entity.Meta>("/api/meta") + .then((res) => res.data); + return this.client + .post<MisskeyAPI.Entity.Stats>("/api/stats") + .then((res) => ({ ...res, data: this.converter.meta(meta, res.data) })); + } - public async getInstancePeers(): Promise<Response<Array<string>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async getInstancePeers(): Promise<Response<Array<string>>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public async getInstanceActivity(): Promise<Response<Array<Entity.Activity>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async getInstanceActivity(): Promise< + Response<Array<Entity.Activity>> + > { + 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<Response<Array<Entity.Tag>>> { - return this.client - .post<Array<MisskeyAPI.Entity.Hashtag>>('/api/hashtags/trend') - .then(res => ({ ...res, data: res.data.map(h => this.converter.hashtag(h)) })) - } + // ====================================== + // instance/trends + // ====================================== + /** + * POST /api/hashtags/trend + */ + public async getInstanceTrends( + _limit?: number | null, + ): Promise<Response<Array<Entity.Tag>>> { + return this.client + .post<Array<MisskeyAPI.Entity.Hashtag>>("/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<Response<Array<Entity.Account>>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + // ====================================== + // instance/directory + // ====================================== + public async getInstanceDirectory(_options?: { + limit?: number; + offset?: number; + order?: "active" | "new"; + local?: boolean; + }): Promise<Response<Array<Entity.Account>>> { + 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<Array<Entity.Emoji>>> { - return this.client - .post<MisskeyAPI.Entity.Meta>('/api/meta') - .then(res => ({ ...res, data: res.data.emojis.map(e => this.converter.emoji(e)) })) - } + // ====================================== + // instance/custom_emojis + // ====================================== + /** + * POST /api/meta + */ + public async getInstanceCustomEmojis(): Promise< + Response<Array<Entity.Emoji>> + > { + return this.client + .post<MisskeyAPI.Entity.Meta>("/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<Response<Array<Entity.Announcement>>> { - let params = {} - if (with_dismissed) { - params = Object.assign(params, { - withUnreads: with_dismissed - }) - } - return this.client.post<Array<MisskeyAPI.Entity.Announcement>>('/api/announcements', params).then(res => ({ - ...res, - data: res.data.map(t => this.converter.announcement(t)) - })) - } + // ====================================== + // instance/announcements + // ====================================== + public async getInstanceAnnouncements( + with_dismissed?: boolean | null, + ): Promise<Response<Array<Entity.Announcement>>> { + let params = {}; + if (with_dismissed) { + params = Object.assign(params, { + withUnreads: with_dismissed, + }); + } + return this.client + .post<Array<MisskeyAPI.Entity.Announcement>>("/api/announcements", params) + .then((res) => ({ + ...res, + data: res.data.map((t) => this.converter.announcement(t)), + })); + } - public async dismissInstanceAnnouncement(id: string): Promise<Response<{}>> { - return this.client.post<{}>('/api/i/read-announcement', { announcementId: id }) - } + public async dismissInstanceAnnouncement(id: string): Promise<Response<{}>> { + 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<Response<Entity.Status>> { - await this.client.post<{}>('/api/notes/reactions/create', { - noteId: id, - reaction: emoji - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/api/notes/show', { - noteId: id - }) - .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) - } + // ====================================== + // 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<Response<Entity.Status>> { + await this.client.post<{}>("/api/notes/reactions/create", { + noteId: id, + reaction: emoji, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Entity.Status>> { - await this.client.post<{}>('/api/notes/reactions/delete', { - noteId: id - }) - return this.client - .post<MisskeyAPI.Entity.Note>('/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<Response<Entity.Status>> { + await this.client.post<{}>("/api/notes/reactions/delete", { + noteId: id, + }); + return this.client + .post<MisskeyAPI.Entity.Note>("/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<Response<Array<Entity.Reaction>>> { - return this.client - .post<Array<MisskeyAPI.Entity.Reaction>>('/api/notes/reactions', { - noteId: id - }) - .then(res => ({ - ...res, - data: this.converter.reactions(res.data) - })) - } + public async getEmojiReactions( + id: string, + ): Promise<Response<Array<Entity.Reaction>>> { + return this.client + .post<Array<MisskeyAPI.Entity.Reaction>>("/api/notes/reactions", { + noteId: id, + }) + .then((res) => ({ + ...res, + data: this.converter.reactions(res.data), + })); + } - public async getEmojiReaction(_id: string, _emoji: string): Promise<Response<Entity.Reaction>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) - } + public async getEmojiReaction( + _id: string, + _emoji: string, + ): Promise<Response<Entity.Reaction>> { + return new Promise((_, reject) => { + const err = new NoImplementedError("misskey does not support"); + reject(err); + }); + } - public userSocket(): WebSocketInterface { - return this.client.socket('user') - } + public userSocket(): WebSocketInterface { + return this.client.socket("user"); + } - public publicSocket(): WebSocketInterface { - return this.client.socket('globalTimeline') - } + public publicSocket(): WebSocketInterface { + return this.client.socket("globalTimeline"); + } - public localSocket(): WebSocketInterface { - return this.client.socket('localTimeline') - } + public localSocket(): WebSocketInterface { + return this.client.socket("localTimeline"); + } - public tagSocket(_tag: string): WebSocketInterface { - throw new NoImplementedError('TODO: implement') - } + public tagSocket(_tag: string): WebSocketInterface { + throw new NoImplementedError("TODO: implement"); + } - public listSocket(list_id: string): WebSocketInterface { - return this.client.socket('list', list_id) - } + public listSocket(list_id: string): WebSocketInterface { + return this.client.socket("list", list_id); + } - public directSocket(): WebSocketInterface { - return this.client.socket('conversation') - } + public directSocket(): WebSocketInterface { + return this.client.socket("conversation"); + } } diff --git a/packages/megalodon/src/notification.ts b/packages/megalodon/src/notification.ts index 8e8c13579..e378bdac1 100644 --- a/packages/megalodon/src/notification.ts +++ b/packages/megalodon/src/notification.ts @@ -1,14 +1,14 @@ -import Entity from './entity' +import Entity from "./entity"; namespace NotificationType { - export const Follow: Entity.NotificationType = 'follow' - export const Favourite: Entity.NotificationType = 'favourite' - export const Reblog: Entity.NotificationType = 'reblog' - export const Mention: Entity.NotificationType = 'mention' - export const EmojiReaction: Entity.NotificationType = 'emoji_reaction' - export const FollowRequest: Entity.NotificationType = 'follow_request' - export const Status: Entity.NotificationType = 'status' - export const Poll: Entity.NotificationType = 'poll' + export const Follow: Entity.NotificationType = "follow"; + export const Favourite: Entity.NotificationType = "favourite"; + export const Reblog: Entity.NotificationType = "reblog"; + export const Mention: Entity.NotificationType = "mention"; + export const EmojiReaction: Entity.NotificationType = "emoji_reaction"; + export const FollowRequest: Entity.NotificationType = "follow_request"; + export const Status: Entity.NotificationType = "status"; + export const Poll: Entity.NotificationType = "poll"; } -export default NotificationType +export default NotificationType; diff --git a/packages/megalodon/src/oauth.ts b/packages/megalodon/src/oauth.ts index 3c3ceb9de..f0df721f0 100644 --- a/packages/megalodon/src/oauth.ts +++ b/packages/megalodon/src/oauth.ts @@ -3,107 +3,121 @@ * 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 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 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 - } + 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) - } + /** + * 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 - } - } + 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 - } + 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) - } + /** + * 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 - } - } + /** + * 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 +export default OAuth; diff --git a/packages/megalodon/src/parser.ts b/packages/megalodon/src/parser.ts index 67abff797..2ddf2ac2e 100644 --- a/packages/megalodon/src/parser.ts +++ b/packages/megalodon/src/parser.ts @@ -1,86 +1,94 @@ -import { EventEmitter } from 'events' -import Entity from './entity' +import { EventEmitter } from "events"; +import Entity from "./entity"; /** * Parser * Parse response data in streaming. **/ export class Parser extends EventEmitter { - private message: string + private message: string; - constructor() { - super() - this.message = '' - } + constructor() { + super(); + this.message = ""; + } - public parse(chunk: string) { - // skip heartbeats - if (chunk === ':thump\n') { - this.emit('heartbeat', {}) - return - } + public parse(chunk: string) { + // skip heartbeats + if (chunk === ":thump\n") { + this.emit("heartbeat", {}); + return; + } - this.message += chunk - chunk = this.message + this.message += chunk; + chunk = this.message; - const size: number = chunk.length - let start: number = 0 - let offset: number = 0 - let curr: string | undefined - let next: string | undefined + 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] + while (offset < size) { + curr = chunk[offset]; + next = chunk[offset + 1]; - if (curr === '\n' && next === '\n') { - const piece: string = chunk.slice(start, offset) + if (curr === "\n" && next === "\n") { + const piece: string = chunk.slice(start, offset); - offset += 2 - start = offset + offset += 2; + start = offset; - if (!piece.length) continue // empty object + if (!piece.length) continue; // empty object - const root: Array<string> = piece.split('\n') + const root: Array<string> = piece.split("\n"); - // should never happen, as long as mastodon doesn't change API messages - if (root.length !== 2) continue + // 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) + // 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) - } + 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 index 7419f664e..fadbcf084 100644 --- a/packages/megalodon/src/proxy_config.ts +++ b/packages/megalodon/src/proxy_config.ts @@ -1,83 +1,92 @@ -import { HttpsProxyAgent, HttpsProxyAgentOptions } from 'https-proxy-agent' -import { SocksProxyAgent, SocksProxyAgentOptions } from 'socks-proxy-agent' +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' -} + 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 +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 index e27596203..13fd8ab57 100644 --- a/packages/megalodon/src/response.ts +++ b/packages/megalodon/src/response.ts @@ -1,8 +1,8 @@ type Response<T = any> = { - data: T - status: number - statusText: string - headers: any -} + data: T; + status: number; + statusText: string; + headers: any; +}; -export default Response +export default Response; diff --git a/packages/sw/package.json b/packages/sw/package.json index 001803825..d97479967 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -4,7 +4,7 @@ "scripts": { "build": "webpack", "watch": "pnpm swc src -d built -D -w", - "lint": "pnpm rome check \"src/**/*.ts\"", + "lint": "pnpm rome check **/*.ts --apply", "format": "pnpm rome format * --write" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adead9c6f..f18b70e91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,7 +70,7 @@ importers: specifier: ^1.0.4 version: 1.0.4 rome: - specifier: ^12.1.3 + specifier: ^v12.1.3-nightly.f65b0d9 version: 12.1.3 start-server-and-test: specifier: 1.15.2 @@ -595,7 +595,7 @@ importers: version: 5.1.6 webpack: specifier: ^5.88.1 - version: 5.88.1(@swc/core@1.3.68) + version: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) ws: specifier: 8.13.0 version: 8.13.0 @@ -673,6 +673,12 @@ importers: '@discordapp/twemoji': specifier: 14.1.2 version: 14.1.2 + '@eslint-sets/eslint-config-vue3': + specifier: ^5.6.1 + version: 5.6.1(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) + '@eslint-sets/eslint-config-vue3-ts': + specifier: ^3.3.0 + version: 3.3.0(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) '@phosphor-icons/web': specifier: ^2.0.3 version: 2.0.3 @@ -780,10 +786,16 @@ importers: version: 2.30.0 emojilib: specifier: github:thatonecalculator/emojilib - version: github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b + version: github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c escape-regexp: specifier: 0.0.1 version: 0.0.1 + eslint-config-prettier: + specifier: ^8.6.0 + version: 8.6.0(eslint@8.44.0) + eslint-plugin-file-progress: + specifier: ^1.3.0 + version: 1.3.0(eslint@8.44.0) eventemitter3: specifier: 5.0.1 version: 5.0.1 @@ -817,6 +829,9 @@ importers: mfm-js: specifier: 0.23.3 version: 0.23.3 + paralint: + specifier: ^1.2.1 + version: 1.2.1 photoswipe: specifier: 5.3.8 version: 5.3.8 @@ -1110,6 +1125,20 @@ packages: transitivePeerDependencies: - supports-color + /@babel/eslint-parser@7.22.9(@babel/core@7.22.9)(eslint@8.44.0): + resolution: {integrity: sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': '>=7.11.0' + eslint: ^7.5.0 || ^8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 8.44.0 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + dev: true + /@babel/generator@7.22.9: resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} engines: {node: '>=6.9.0'} @@ -1697,6 +1726,15 @@ packages: - supports-color dev: false + /@es-joy/jsdoccomment@0.39.4: + resolution: {integrity: sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==} + engines: {node: '>=16'} + dependencies: + comment-parser: 1.3.1 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.0.0 + dev: true + /@esbuild/android-arm64@0.18.12: resolution: {integrity: sha512-BMAlczRqC/LUt2P97E4apTBbkvS9JTJnp2DKFbCwpZ8vBvXVbNdqmvzW/OsdtI/+mGr+apkkpqGM8WecLkPgrA==} engines: {node: '>=12'} @@ -1908,6 +1946,184 @@ packages: resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + /@eslint-sets/eslint-config-basic@3.3.0(@babel/core@7.22.9)(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(prettier@3.0.0): + resolution: {integrity: sha512-x5YH0CvZJxn19/5ehu188XaoLQpxOGlFiIuPHCN6FyONgrmriakT/cmIIBOJg2Vi/y1bn2xbhsgVNb00J3HyTg==} + peerDependencies: + eslint: '>=8.0.0' + prettier: '>=2.0.0' + dependencies: + '@babel/eslint-parser': 7.22.9(@babel/core@7.22.9)(eslint@8.44.0) + eslint: 8.44.0 + eslint-config-prettier: 8.6.0(eslint@8.44.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.44.0) + eslint-plugin-html: 7.1.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.49.0)(eslint@8.44.0) + eslint-plugin-jsonc: 2.9.0(eslint@8.44.0) + eslint-plugin-markdown: 3.0.0(eslint@8.44.0) + eslint-plugin-n: 15.7.0(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-promise: 5.2.0(eslint@8.44.0) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-unicorn: 45.0.2(eslint@8.44.0) + eslint-plugin-yml: 1.8.0(eslint@8.44.0) + jsonc-eslint-parser: 2.3.0 + prettier: 3.0.0 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + yaml-eslint-parser: 1.2.2 + transitivePeerDependencies: + - '@babel/core' + - '@typescript-eslint/parser' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@eslint-sets/eslint-config-basic@5.6.1(@babel/core@7.22.9)(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6): + resolution: {integrity: sha512-9Lgl4v6YZP+V39U149ahmxqNeiAja4dVY4mmPGGWZB13W6D5Cu6K5qq9fY1lI7AnplymE9ghZzgAYYggxZPt4A==} + peerDependencies: + eslint: '>=7.4.0' + prettier: '>=2 <3' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@babel/eslint-parser': 7.22.9(@babel/core@7.22.9)(eslint@8.44.0) + eslint: 8.44.0 + eslint-config-prettier: 8.8.0(eslint@8.44.0) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.44.0) + eslint-plugin-html: 7.1.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0)(eslint@8.44.0) + eslint-plugin-jsonc: 2.9.0(eslint@8.44.0) + eslint-plugin-markdown: 3.0.0(eslint@8.44.0) + eslint-plugin-n: 16.0.1(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-promise: 6.1.1(eslint@8.44.0) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-unicorn: 40.1.0(eslint@8.44.0) + eslint-plugin-yml: 1.8.0(eslint@8.44.0) + jsonc-eslint-parser: 2.3.0 + prettier: 3.0.0 + typescript: 5.1.6 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + yaml-eslint-parser: 1.2.2 + transitivePeerDependencies: + - '@babel/core' + - '@typescript-eslint/parser' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@eslint-sets/eslint-config-ts@3.3.0(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6): + resolution: {integrity: sha512-4Vj3KxYx16hmW6AyEv1mil0gVN8H3rdJt8TRWufbAj0ZN+EjwOPf3TqE7ASCYto/NpA8xWQY3NGm/og9Or/dDQ==} + peerDependencies: + eslint: '>=8.0.0' + prettier: '>=2.0.0' + typescript: '>=4.0.0' + dependencies: + '@eslint-sets/eslint-config-basic': 3.3.0(@babel/core@7.22.9)(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(prettier@3.0.0) + '@typescript-eslint/eslint-plugin': 5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.49.0(eslint@8.44.0)(typescript@5.1.6) + eslint: 8.44.0 + eslint-config-prettier: 8.6.0(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-tsdoc: 0.2.17 + prettier: 3.0.0 + typescript: 5.1.6 + transitivePeerDependencies: + - '@babel/core' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@eslint-sets/eslint-config-ts@5.6.1(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6): + resolution: {integrity: sha512-H5PAWlbv093UczOaAaWSi4cx+oUS10ca2nyryf19FA98ckynlg/CrX2Kycuee8/XouaoZoZYh5dC/9dkCsbWTw==} + peerDependencies: + eslint: '>=7.4.0' + prettier: '>=2 <3' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-sets/eslint-config-basic': 5.6.1(@babel/core@7.22.9)(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + eslint: 8.44.0 + eslint-config-prettier: 8.8.0(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-tsdoc: 0.2.17 + prettier: 3.0.0 + typescript: 5.1.6 + transitivePeerDependencies: + - '@babel/core' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@eslint-sets/eslint-config-vue3-ts@3.3.0(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6): + resolution: {integrity: sha512-KX3VFuS5U4FYKfZ6PABQjl54BMpNapNjYYe103Nm2Zy8y9zphDCBAARbhU97XNSvzkurve7HhJcsi9gXrWlGFA==} + peerDependencies: + eslint: '>=8.0.0' + prettier: '>=2.0.0' + typescript: '>=4.0.0' + dependencies: + '@eslint-sets/eslint-config-ts': 3.3.0(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) + '@typescript-eslint/eslint-plugin': 5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.49.0(eslint@8.44.0)(typescript@5.1.6) + eslint: 8.44.0 + eslint-config-prettier: 8.6.0(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-vitest-globals: 1.4.0 + eslint-plugin-vue: 9.15.1(eslint@8.44.0) + eslint-plugin-vue-scoped-css: 2.5.0(eslint@8.44.0)(vue-eslint-parser@9.3.1) + prettier: 3.0.0 + typescript: 5.1.6 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + transitivePeerDependencies: + - '@babel/core' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@eslint-sets/eslint-config-vue3@5.6.1(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6): + resolution: {integrity: sha512-ueHmU9ItUYZkMMB3bn6N0gMziJLZUCa6xnv9sRYEZIXAjOqiqYpf3Uorm9wQdg4rvwD9dvS3hvjAQLF0qAnGCw==} + peerDependencies: + eslint: '>=7.4.0' + prettier: '>=2 <3' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-sets/eslint-config-basic': 5.6.1(@babel/core@7.22.9)(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) + '@eslint-sets/eslint-config-ts': 5.6.1(@babel/core@7.22.9)(eslint@8.44.0)(prettier@3.0.0)(typescript@5.1.6) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + eslint: 8.44.0 + eslint-config-prettier: 8.8.0(eslint@8.44.0) + eslint-plugin-jsdoc: 46.4.4(eslint@8.44.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@3.0.0) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-vitest-globals: 1.4.0 + eslint-plugin-vue: 9.15.1(eslint@8.44.0) + eslint-plugin-vue-scoped-css: 2.5.0(eslint@8.44.0)(vue-eslint-parser@9.3.1) + local-pkg: 0.4.3 + prettier: 3.0.0 + typescript: 5.1.6 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + transitivePeerDependencies: + - '@babel/core' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + /@eslint/eslintrc@2.1.0: resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2634,6 +2850,12 @@ packages: engines: {node: '>= 10'} hasBin: true + /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + dependencies: + eslint-scope: 5.1.1 + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2659,6 +2881,13 @@ packages: semver: 7.5.4 dev: false + /@npmcli/promise-spawn@6.0.2: + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + which: 3.0.1 + dev: true + /@nsfw-filter/gif-frames@1.0.2: resolution: {integrity: sha512-XZrbJWEN8YfVla5i+PD4Wj51rRlJ8OgnXiPjjOt/OsrbsCR9GZRD4jr953oNWcwiRaoIcOCFWQNMQukO7Yb1dA==} dependencies: @@ -3783,6 +4012,12 @@ packages: resolution: {integrity: sha512-W9UC9DOPNBRTUocqqPZmzX3cbHmlZBI9jLn6SuxZz0n5QrPk382Ig3hbBWHqYU8TRUmTCJJhuanXeyMTavF7Mg==} dev: true + /@types/mdast@3.0.12: + resolution: {integrity: sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==} + dependencies: + '@types/unist': 2.0.7 + dev: true + /@types/mime@1.3.2: resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} @@ -4005,6 +4240,10 @@ packages: async-done: 1.3.2 dev: true + /@types/unist@2.0.7: + resolution: {integrity: sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==} + dev: true + /@types/uuid@8.3.4: resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} dev: true @@ -4104,6 +4343,61 @@ packages: - supports-color dev: true + /@typescript-eslint/eslint-plugin@5.49.0(@typescript-eslint/parser@5.49.0)(eslint@8.44.0)(typescript@5.1.6): + 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@5.1.6) + '@typescript-eslint/scope-manager': 5.49.0 + '@typescript-eslint/type-utils': 5.49.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.49.0(eslint@8.44.0)(typescript@5.1.6) + 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@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.44.0)(typescript@5.1.6): + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + 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: + '@eslint-community/regexpp': 4.5.1 + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - 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} @@ -4124,6 +4418,46 @@ packages: - supports-color dev: true + /@typescript-eslint/parser@5.49.0(eslint@8.44.0)(typescript@5.1.6): + 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@5.1.6) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.62.0(eslint@8.44.0)(typescript@5.1.6): + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + 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.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/scope-manager@5.49.0: resolution: {integrity: sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4132,6 +4466,14 @@ packages: '@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} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.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} @@ -4152,11 +4494,56 @@ packages: - supports-color dev: true + /@typescript-eslint/type-utils@5.49.0(eslint@8.44.0)(typescript@5.1.6): + 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@5.1.6) + '@typescript-eslint/utils': 5.49.0(eslint@8.44.0)(typescript@5.1.6) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/type-utils@5.62.0(eslint@8.44.0)(typescript@5.1.6): + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.44.0)(typescript@5.1.6) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/types@5.49.0: resolution: {integrity: sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@typescript-eslint/typescript-estree@5.49.0(typescript@4.9.4): resolution: {integrity: sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4178,6 +4565,48 @@ packages: - supports-color dev: true + /@typescript-eslint/typescript-estree@5.49.0(typescript@5.1.6): + 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@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.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@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - 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} @@ -4198,6 +4627,46 @@ packages: - typescript dev: true + /@typescript-eslint/utils@5.49.0(eslint@8.44.0)(typescript@5.1.6): + 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@5.1.6) + 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.44.0)(typescript@5.1.6): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.0 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + eslint: 8.44.0 + eslint-scope: 5.1.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/visitor-keys@5.49.0: resolution: {integrity: sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4206,6 +4675,14 @@ packages: eslint-visitor-keys: 3.4.1 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} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.1 + dev: true + /@vitejs/plugin-vue@4.2.3(vite@4.4.2)(vue@3.3.4): resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4772,6 +5249,11 @@ packages: resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} dev: true + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + dev: true + /are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} @@ -5138,7 +5620,7 @@ packages: /axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) transitivePeerDependencies: - debug dev: false @@ -5164,7 +5646,7 @@ packages: /axios@1.4.0: resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -5398,7 +5880,6 @@ packages: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - dev: false /blob-util@2.0.2: resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} @@ -5424,7 +5905,6 @@ packages: /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: false /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -5560,6 +6040,17 @@ packages: node-gyp-build: 4.6.0 dev: false + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + /bull@4.10.4: resolution: {integrity: sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA==} engines: {node: '>=12'} @@ -5783,11 +6274,23 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + /character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + /character-parser@2.2.0: resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} dependencies: is-regex: 1.1.4 + /character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + dev: true + /charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} dev: true @@ -5944,6 +6447,13 @@ packages: static-extend: 0.1.2 dev: true + /clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -5980,6 +6490,11 @@ packages: yargs: 16.2.0 dev: false + /cli-spinners@2.9.0: + resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==} + engines: {node: '>=6'} + dev: true + /cli-table3@0.6.3: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} engines: {node: 10.* || >= 12.*} @@ -6253,6 +6768,11 @@ packages: engines: {node: ^12.20.0 || >=14} dev: true + /comment-parser@1.3.1: + resolution: {integrity: sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==} + engines: {node: '>= 12.0.0'} + dev: true + /common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} dev: true @@ -6640,6 +7160,20 @@ packages: resolution: {integrity: sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==} dev: false + /css@3.0.0: + resolution: {integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==} + dependencies: + inherits: 2.0.4 + source-map: 0.6.1 + source-map-resolve: 0.6.0 + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + /cssnano@3.10.0: resolution: {integrity: sha512-0o0IMQE0Ezo4b41Yrm8U6Rp9/Ag81vNXY1gZMnT1XhO4DpjEf2utKERqWJbOoz3g1Wdc1d3QSta/cIuJ1wSTEg==} dependencies: @@ -6780,6 +7314,11 @@ packages: es5-ext: 0.10.62 type: 1.2.0 + /dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + dev: true + /dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -6843,17 +7382,6 @@ packages: dependencies: ms: 2.0.0 - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: false - /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -6864,7 +7392,6 @@ packages: dependencies: ms: 2.1.3 supports-color: 8.1.1 - dev: true /debug@4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} @@ -6969,6 +7496,12 @@ packages: engines: {node: '>= 0.10'} dev: true + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + /defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -7538,6 +8071,15 @@ packages: eslint: 8.44.0 dev: true + /eslint-config-prettier@8.8.0(eslint@8.44.0): + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.44.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: @@ -7605,6 +8147,46 @@ packages: - supports-color dev: true + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(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.62.0(eslint@8.44.0)(typescript@5.1.6) + debug: 3.2.7(supports-color@8.1.1) + eslint: 8.44.0 + eslint-import-resolver-node: 0.3.7 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es-x@7.1.0(eslint@8.44.0): + resolution: {integrity: sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + '@eslint-community/regexpp': 4.5.1 + eslint: 8.44.0 + dev: true + /eslint-plugin-es@3.0.1(eslint@8.44.0): resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} @@ -7616,6 +8198,44 @@ packages: regexpp: 3.2.0 dev: true + /eslint-plugin-es@4.1.0(eslint@8.44.0): + resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==} + 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-eslint-comments@3.2.0(eslint@8.44.0): + resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==} + engines: {node: '>=6.5.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + escape-string-regexp: 1.0.5 + eslint: 8.44.0 + ignore: 5.2.4 + dev: true + + /eslint-plugin-file-progress@1.3.0(eslint@8.44.0): + resolution: {integrity: sha512-LncpnGHU26KPvCrvDC2Sl9PfjdrsG8qltgiK6BR7KybWtfqrdlsu1ax3+hyPMn5OkKBTF3Wki3oqK1MSMeOtQw==} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + chalk: 4.1.2 + eslint: 8.44.0 + ora: 5.4.1 + dev: true + + /eslint-plugin-html@7.1.0: + resolution: {integrity: sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==} + dependencies: + 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'} @@ -7649,6 +8269,117 @@ packages: - supports-color dev: true + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.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.62.0(eslint@8.44.0)(typescript@5.1.6) + 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.7 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.7)(eslint@8.44.0) + has: 1.0.3 + is-core-module: 2.12.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.6 + resolve: 1.22.2 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsdoc@46.4.4(eslint@8.44.0): + resolution: {integrity: sha512-D8TGPOkq3bnzmYmA7Q6jdsW+Slx7CunhJk1tlouVq6wJjlP1p6eigZPvxFn7aufud/D66xBsNVMhkDQEuqumMg==} + engines: {node: '>=16'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@es-joy/jsdoccomment': 0.39.4 + are-docs-informative: 0.0.2 + comment-parser: 1.3.1 + debug: 4.3.4(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint: 8.44.0 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.5.4 + spdx-expression-parse: 3.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-jsonc@2.9.0(eslint@8.44.0): + resolution: {integrity: sha512-RK+LeONVukbLwT2+t7/OY54NJRccTXh/QbnXzPuTLpFMVZhPuq1C9E07+qWenGx7rrQl0kAalAWl7EmB+RjpGA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + eslint: 8.44.0 + jsonc-eslint-parser: 2.3.0 + natural-compare: 1.4.0 + dev: true + + /eslint-plugin-markdown@3.0.0(eslint@8.44.0): + resolution: {integrity: sha512-hRs5RUJGbeHDLfS7ELanT0e29Ocyssf/7kBM+p7KluY5AwngGkDf8Oyu4658/NZSGTTq05FZeWbkxXtbVyHPwg==} + 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 + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-n@15.7.0(eslint@8.44.0): + resolution: {integrity: sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==} + engines: {node: '>=12.22.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + builtins: 5.0.1 + eslint: 8.44.0 + eslint-plugin-es: 4.1.0(eslint@8.44.0) + eslint-utils: 3.0.0(eslint@8.44.0) + ignore: 5.2.4 + is-core-module: 2.12.1 + minimatch: 3.1.2 + resolve: 1.22.2 + semver: 7.5.4 + dev: true + + /eslint-plugin-n@16.0.1(eslint@8.44.0): + resolution: {integrity: sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + builtins: 5.0.1 + eslint: 8.44.0 + eslint-plugin-es-x: 7.1.0(eslint@8.44.0) + ignore: 5.2.4 + is-core-module: 2.12.1 + minimatch: 3.1.2 + resolve: 1.22.2 + 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'} @@ -7681,6 +8412,49 @@ packages: prettier-linter-helpers: 1.0.0 dev: true + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.6.0)(eslint@8.44.0)(prettier@3.0.0): + 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.6.0(eslint@8.44.0) + prettier: 3.0.0 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.44.0)(prettier@3.0.0): + 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.8.0(eslint@8.44.0) + prettier: 3.0.0 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-promise@5.2.0(eslint@8.44.0): + resolution: {integrity: sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.0.0 + dependencies: + eslint: 8.44.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} @@ -7699,6 +8473,118 @@ packages: eslint: 8.44.0 dev: true + /eslint-plugin-tsdoc@0.2.17: + resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + dev: true + + /eslint-plugin-unicorn@40.1.0(eslint@8.44.0): + resolution: {integrity: sha512-y5doK2DF9Sr5AqKEHbHxjFllJ167nKDRU01HDcWyv4Tnmaoe9iNxMrBnaybZvWZUaE3OC5Unu0lNIevYamloig==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=7.32.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + ci-info: 3.8.0 + clean-regexp: 1.0.0 + eslint: 8.44.0 + eslint-utils: 3.0.0(eslint@8.44.0) + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + safe-regex: 2.1.1 + semver: 7.5.4 + strip-indent: 3.0.0 + dev: true + + /eslint-plugin-unicorn@45.0.2(eslint@8.44.0): + resolution: {integrity: sha512-Y0WUDXRyGDMcKLiwgL3zSMpHrXI00xmdyixEGIg90gHnj0PcHY4moNv3Ppje/kDivdAy5vUeUr7z211ImPv2gw==} + engines: {node: '>=14.18'} + peerDependencies: + eslint: '>=8.28.0' + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + ci-info: 3.8.0 + clean-regexp: 1.0.0 + eslint: 8.44.0 + esquery: 1.5.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + lodash: 4.17.21 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.9.1 + safe-regex: 2.1.1 + semver: 7.5.4 + strip-indent: 3.0.0 + dev: true + + /eslint-plugin-vitest-globals@1.4.0: + resolution: {integrity: sha512-WE+YlK9X9s4vf5EaYRU0Scw7WItDZStm+PapFSYlg2ABNtaQ4zIG7wEqpoUB3SlfM+SgkhgmzR0TeJOO5k3/Nw==} + dev: true + + /eslint-plugin-vue-scoped-css@2.5.0(eslint@8.44.0)(vue-eslint-parser@9.3.1): + resolution: {integrity: sha512-vR+raYNE1aQ69lS1lZGiKoz8rXFI3MWf2fxrfns/XCQ0XT5sIguhDtQS+9JmUQJClenLDEe2CQx7P+eeSdF4cA==} + engines: {node: ^12.22 || ^14.17 || >=16} + peerDependencies: + eslint: '>=5.0.0' + vue-eslint-parser: '>=7.1.0' + dependencies: + eslint: 8.44.0 + eslint-utils: 3.0.0(eslint@8.44.0) + lodash: 4.17.21 + postcss: 8.4.25 + postcss-safe-parser: 6.0.0(postcss@8.4.25) + postcss-scss: 4.0.6(postcss@8.4.25) + postcss-selector-parser: 6.0.13 + postcss-styl: 0.12.3 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-vue@9.15.1(eslint@8.44.0): + resolution: {integrity: sha512-CJE/oZOslvmAR9hf8SClTdQ9JLweghT6JCBQNrT2Iel1uVw0W0OLJxzvPd6CxmABKCvLrtyDnqGV37O7KQv6+A==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.44.0) + eslint: 8.44.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.0.13 + semver: 7.5.4 + vue-eslint-parser: 9.3.1(eslint@8.44.0) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-yml@1.8.0(eslint@8.44.0): + resolution: {integrity: sha512-fgBiJvXD0P2IN7SARDJ2J7mx8t0bLdG6Zcig4ufOqW5hOvSiFxeUyc2g5I1uIm8AExbo26NNYCcTGZT0MXTsyg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + lodash: 4.17.21 + natural-compare: 1.4.0 + yaml-eslint-parser: 1.2.2 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-rule-docs@1.1.235: resolution: {integrity: sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==} dev: true @@ -8377,16 +9263,6 @@ packages: tabbable: 6.2.0 dev: true - /follow-redirects@1.15.2: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: false - /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} @@ -9355,7 +10231,7 @@ packages: engines: {node: '>= 4.5.0'} dependencies: agent-base: 4.3.0 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -9632,6 +10508,17 @@ packages: kind-of: 6.0.3 dev: true + /is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + dev: true + + /is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + dev: true + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -9679,6 +10566,13 @@ packages: /is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -9716,6 +10610,10 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + dev: true + /is-descriptor@0.1.6: resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} engines: {node: '>=0.10.0'} @@ -9804,6 +10702,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + /is-installed-globally@0.4.0: resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} engines: {node: '>=10'} @@ -9812,6 +10714,11 @@ packages: is-path-inside: 3.0.3 dev: true + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + /is-ip@3.1.0: resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==} engines: {node: '>=8'} @@ -11160,6 +12067,11 @@ packages: engines: {node: '>=0.1.90'} dev: false + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + dev: true + /jsdom@16.7.0: resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} engines: {node: '>=10'} @@ -11243,11 +12155,22 @@ packages: - utf-8-validate dev: false + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true + /jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + dev: true + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -11280,7 +12203,7 @@ packages: json5: 2.2.3 loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /json5@1.0.2: @@ -11295,6 +12218,16 @@ packages: engines: {node: '>=6'} hasBin: true + /jsonc-eslint-parser@2.3.0: + resolution: {integrity: sha512-9xZPKVYp9DxnM3sd1yAsh/d59iIaswDkai8oTxbursfKYbg/ibjX0IzFt35+VZ8iEW453TVTXztnRvYUQlAfUQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + eslint-visitor-keys: 3.4.1 + espree: 9.6.0 + semver: 7.5.4 + dev: true + /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true @@ -11535,7 +12468,7 @@ packages: resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} engines: {node: '>= 7.6.0'} dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) koa-send: 5.0.1 transitivePeerDependencies: - supports-color @@ -11815,6 +12748,11 @@ packages: resolution: {integrity: sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==} dev: true + /local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + dev: true + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -11912,6 +12850,10 @@ packages: resolution: {integrity: sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==} dev: false + /lodash.sortedlastindex@4.1.0: + resolution: {integrity: sha512-s8xEQdsp2Tu5zUqVdFSe9C0kR8YlnAJYLqMdkh+pIRBRxF6/apWseLdHl3/+jv2I61dhPwtI/Ff+EqvCpc+N8w==} + dev: true + /lodash.union@4.6.0: resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} dev: false @@ -12123,6 +13065,22 @@ packages: blueimp-md5: 2.19.0 dev: true + /mdast-util-from-markdown@0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.12 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /mdast-util-to-string@2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true + /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -12181,6 +13139,15 @@ packages: dependencies: twemoji-parser: 14.0.0 + /micromark@2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + /micromatch@3.1.10: resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} engines: {node: '>=0.10.0'} @@ -12579,7 +13546,7 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) iconv-lite: 0.4.24 sax: 1.2.4 transitivePeerDependencies: @@ -12828,6 +13795,12 @@ packages: boolbase: 1.0.0 dev: false + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + /num2fraction@1.2.2: resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} dev: true @@ -12996,6 +13969,21 @@ packages: prelude-ls: 1.2.1 type-check: 0.4.0 + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.0 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + /ordered-read-streams@1.0.1: resolution: {integrity: sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==} dependencies: @@ -13135,6 +14123,17 @@ packages: resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} dev: false + /paralint@1.2.1: + resolution: {integrity: sha512-HPGVDd5eUNYBhtftRypBHlUTMy5UAnHBzFO601oLEODZ0uvXUJge1y43GZQM2CnyOOUyDQlNMK/9vcjjAxbfcA==} + hasBin: true + dependencies: + '@npmcli/promise-spawn': 6.0.2 + dargs: 8.1.0 + fast-glob: 3.3.0 + minimist: 1.2.8 + tslib: 2.6.0 + dev: true + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -13147,6 +14146,17 @@ packages: data-uri-to-buffer: 0.0.3 dev: false + /parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + dev: true + /parse-filepath@1.0.2: resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} engines: {node: '>=0.8'} @@ -13476,7 +14486,6 @@ packages: /pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - dev: false /pngjs-nozlib@1.0.0: resolution: {integrity: sha512-N1PggqLp9xDqwAoKvGohmZ3m4/N9xpY0nDZivFqQLcpLHmliHnCp9BuNCsOeqHWMuEEgFjpEaq9dZq6RZyy0fA==} @@ -13662,6 +14671,24 @@ packages: postcss-value-parser: 3.3.1 dev: true + /postcss-safe-parser@6.0.0(postcss@8.4.25): + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + dependencies: + postcss: 8.4.25 + dev: true + + /postcss-scss@4.0.6(postcss@8.4.25): + resolution: {integrity: sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.19 + dependencies: + postcss: 8.4.25 + dev: true + /postcss-selector-parser@2.2.3: resolution: {integrity: sha512-3pqyakeGhrO0BQ5+/tGTfvi5IAUAhHRayGK8WFSu06aEv2BmHoXw/Mhb+w7VY5HERIuC+QoUI7wgrCcq2hqCVA==} dependencies: @@ -13670,6 +14697,27 @@ packages: uniq: 1.0.1 dev: true + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-styl@0.12.3: + resolution: {integrity: sha512-8I7Cd8sxiEITIp32xBK4K/Aj1ukX6vuWnx8oY/oAH35NfQI4OZaY5nd68Yx8HeN5S49uhQ6DL0rNk0ZBu/TaLg==} + engines: {node: ^8.10.0 || ^10.13.0 || ^11.10.1 || >=12.13.0} + dependencies: + debug: 4.3.4(supports-color@8.1.1) + fast-diff: 1.3.0 + lodash.sortedlastindex: 4.1.0 + postcss: 8.4.25 + stylus: 0.57.0 + transitivePeerDependencies: + - supports-color + dev: true + /postcss-svgo@2.1.6: resolution: {integrity: sha512-y5AdQdgBoF4rbpdbeWAJuxE953g/ylRfVNp6mvAi61VCN/Y25Tu9p5mh3CyI42WbTRIiwR9a1GdFtmDnNPeskQ==} dependencies: @@ -14397,6 +15445,11 @@ packages: safe-regex: 1.1.0 dev: true + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + /regexp.prototype.flags@1.5.0: resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} engines: {node: '>= 0.4'} @@ -14411,6 +15464,13 @@ packages: engines: {node: '>=8'} dev: true + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + /remove-bom-buffer@3.0.0: resolution: {integrity: sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==} engines: {node: '>=0.10.0'} @@ -14722,6 +15782,12 @@ packages: ret: 0.1.15 dev: true + /safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + dependencies: + regexp-tree: 0.1.27 + dev: true + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -15102,6 +16168,14 @@ packages: urix: 0.1.0 dev: true + /source-map-resolve@0.6.0: + resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + dev: true + /source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} dependencies: @@ -15459,6 +16533,20 @@ packages: '@tokenizer/token': 0.3.0 peek-readable: 5.0.0 + /stylus@0.57.0: + resolution: {integrity: sha512-yOI6G8WYfr0q8v8rRvE91wbxFU+rJPo760Va4MF6K0I6BZjO4r+xSynkvyPBP9tV1CIEUeRsiidjIs2rzb1CnQ==} + hasBin: true + dependencies: + css: 3.0.0 + debug: 4.3.4(supports-color@8.1.1) + glob: 7.2.3 + safer-buffer: 2.1.2 + sax: 1.2.4 + source-map: 0.7.4 + transitivePeerDependencies: + - supports-color + dev: true + /summaly@2.7.0: resolution: {integrity: sha512-pEz9LL8Gp0oPIQfn6TrnBCcv/HkFE14hxhH3W6LPGdopXlPXjRcMlDMJaO+VupUNMOGaMjCsjq7+0rWnu8sp7w==} dependencies: @@ -15558,7 +16646,7 @@ packages: webpack: '>=2' dependencies: '@swc/core': 1.3.68 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /swiper@10.0.4: @@ -15677,7 +16765,7 @@ packages: schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.0 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /terser@5.19.0: @@ -16016,7 +17104,7 @@ packages: micromatch: 4.0.5 semver: 7.5.4 typescript: 5.1.6 - webpack: 5.88.1(@swc/core@1.3.68) + webpack: 5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3) dev: true /ts-node@10.4.0(@swc/core@1.3.68)(@types/node@20.3.1)(typescript@5.1.3): @@ -16147,6 +17235,16 @@ packages: typescript: 4.9.4 dev: true + /tsutils@3.21.0(typescript@5.1.6): + 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: 5.1.6 + dev: true + /tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} dependencies: @@ -16443,6 +17541,12 @@ packages: through2-filter: 3.0.0 dev: true + /unist-util-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.7 + dev: true + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -16759,6 +17863,24 @@ packages: optional: true dev: true + /vue-eslint-parser@9.3.1(eslint@8.44.0): + resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.44.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.1 + espree: 9.6.0 + esquery: 1.5.0 + lodash: 4.17.21 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + /vue-isyourpasswordsafe@2.0.0: resolution: {integrity: sha512-j3ORj18R9AgFiP2UOM35KuZbSeJAUiwCSyeRBFN3CGFYTJSKsxqU9qGqOHOz6OhLAYKMTin8JOmqugAbF9O+Bg==} dependencies: @@ -16851,6 +17973,12 @@ packages: graceful-fs: 4.2.11 dev: true + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + /web-push@3.6.3: resolution: {integrity: sha512-3RlA0lRmLcwlHCRR94Tz+Fw6wPtm0lFm8oyukQunlEIarANxE84Ox9XBgF4+jNlXgO40DIwblOiC43oR46helA==} engines: {node: '>= 16'} @@ -16933,46 +18061,6 @@ packages: engines: {node: '>=10.13.0'} dev: true - /webpack@5.88.1(@swc/core@1.3.68): - 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.9 - 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.68)(webpack@5.88.1) - watchpack: 2.4.0 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - /webpack@5.88.1(@swc/core@1.3.68)(webpack-cli@5.1.3): resolution: {integrity: sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==} engines: {node: '>=10.13.0'} @@ -17125,6 +18213,14 @@ packages: dependencies: isexe: 2.0.0 + /which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + /wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: @@ -17265,7 +18361,6 @@ packages: /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} - dev: false /xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} @@ -17317,6 +18412,20 @@ packages: resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} dev: false + /yaml-eslint-parser@1.2.2: + resolution: {integrity: sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==} + engines: {node: ^14.17.0 || >=16.0.0} + dependencies: + eslint-visitor-keys: 3.4.1 + lodash: 4.17.21 + yaml: 2.3.1 + dev: true + + /yaml@2.3.1: + resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} + engines: {node: '>= 14'} + dev: true + /yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -17486,8 +18595,8 @@ packages: url-polyfill: 1.1.12 dev: true - github.com/thatonecalculator/emojilib/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b: - resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/1d6adc1af8105b4937d2f0e7479acf5bd565bd9b} + github.com/thatonecalculator/emojilib/d3c8c6a77d4362b3b3180099f1d2eac344ce245c: + resolution: {tarball: https://codeload.github.com/thatonecalculator/emojilib/tar.gz/d3c8c6a77d4362b3b3180099f1d2eac344ce245c} name: emojilib version: 3.0.10 dev: true diff --git a/rome.json b/rome.json index 9b463ea41..d249fffac 100644 --- a/rome.json +++ b/rome.json @@ -10,8 +10,12 @@ "ignore": [ "packages/calckey-js/api-extractor.json", "packages/*/tsconfig.json", + "packages/*/built", + "packages/megalodon/lib", "packages/*/package-lock.json", "packages/backend/src/server/web/manifest.ts", + "packages/megalodon/src/misskey/web_socket.ts", + "packages/megalodon/src/misskey/api_client.ts", "packages/backend/built/", "*/model.json", "*.md", From 7904fcbeab88c83ee06b9eca1be4b88cbd561ffa Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 16 Jul 2023 15:33:17 -0700 Subject: [PATCH 160/162] chore: :art: format --- packages/client/src/components/MkReactionsViewer.vue | 6 +++++- packages/client/src/scripts/get-user-menu.ts | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/client/src/components/MkReactionsViewer.vue b/packages/client/src/components/MkReactionsViewer.vue index 2381b0a02..8b96de6d8 100644 --- a/packages/client/src/components/MkReactionsViewer.vue +++ b/packages/client/src/components/MkReactionsViewer.vue @@ -1,5 +1,9 @@ <template> - <div ref="reactionsEl" class="reactions-list swiper-no-swiping tdflqwzn" :class="{ isMe }"> + <div + ref="reactionsEl" + class="reactions-list swiper-no-swiping tdflqwzn" + :class="{ isMe }" + > <XReaction v-for="(count, reaction) in note.reactions" :key="reaction" diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index 2750df65b..26d6aab30 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -267,8 +267,8 @@ export function getUserMenu(user, router: Router = mainRouter) { text: i18n.ts.showOnRemote, href: user.url, target: "_blank", - - } : undefined, + } + : undefined, null, { icon: "ph-list-bullets ph-bold ph-lg", From 4c11ffa6cfc8fc7346a801de6b3ba6c2636daeeb Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 16 Jul 2023 16:40:57 -0700 Subject: [PATCH 161/162] docs: :memo: changelog --- CALCKEY.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CALCKEY.md b/CALCKEY.md index 619155238..54b3f97e4 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -6,8 +6,6 @@ ## Planned - Stucture - - [DragonflyDB](https://dragonflydb.io/) support as a Redis alternative - - Optionally use [ScyllaDB](https://www.scylladb.com/open-source-nosql-database/) for storing notes - Rewrite backend in Rust and [Rocket](https://rocket.rs/) - Use [Magic RegExP](https://regexp.dev/) for RegEx 🦄 - Function @@ -16,9 +14,6 @@ - Option to publicize server blocks - More antenna options - Groups -- Form - - Lookup/details for post/file/server - - [Rat mode?](https://stop.voring.me/notes/933fx97bmd) ## Work in progress @@ -30,6 +25,7 @@ - Timeline filters - Events - Fully revamp non-logged-in screen +- Optionally use [ScyllaDB](https://www.scylladb.com/open-source-nosql-database/) for storing notes ## Implemented @@ -122,6 +118,7 @@ - Let moderators see moderation nodes - Non-mangled unicode emojis - Skin tone selection support +- [DragonflyDB](https://dragonflydb.io/) support as a Redis alternative ## Implemented (remote) From 8040a0093a665bfcb7a249b2492c8556450357cf Mon Sep 17 00:00:00 2001 From: ThatOneCalculator <kainoa@t1c.dev> Date: Sun, 16 Jul 2023 16:49:24 -0700 Subject: [PATCH 162/162] changelog --- CALCKEY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CALCKEY.md b/CALCKEY.md index 54b3f97e4..bb28e5bbf 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -7,7 +7,6 @@ - Stucture - Rewrite backend in Rust and [Rocket](https://rocket.rs/) - - Use [Magic RegExP](https://regexp.dev/) for RegEx 🦄 - Function - User "choices" (recommended users) and featured hashtags like Mastodon and Soapbox - Join Reason system like Mastodon/Pleroma