├── .config ├── LICENSE ├── devenv.yml ├── docker_example.env ├── example.yml └── helm_values_example.yml ├── .dockerignore ├── .editorconfig ├── .envrc ├── .gitattributes ├── .gitignore ├── .gitlab-ci.yml ├── .node-version ├── .npmrc ├── .vsls.json ├── .weblate ├── .woodpecker ├── commit.yml ├── dockerHubRelease.yml ├── dockerHubReleaseCandidate.yml ├── dockerHubTag.yml └── testDocker.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Procfile ├── README.md ├── animated.svg ├── cliff.toml ├── custom ├── assets │ ├── LICENSE │ ├── badges │ │ ├── error.png │ │ ├── info.png │ │ └── not-found.png │ ├── icons │ │ ├── npf-bold.svg │ │ ├── npf-color.svg │ │ ├── npf-italic.svg │ │ ├── npf-link.svg │ │ ├── npf-read-more-alt.svg │ │ ├── npf-read-more.svg │ │ ├── npf-small.svg │ │ ├── npf-strikethrough.svg │ │ ├── posts-ask.svg │ │ ├── posts-audio-alt.svg │ │ ├── posts-audio.svg │ │ ├── posts-chat.svg │ │ ├── posts-link-alt.svg │ │ ├── posts-link.svg │ │ ├── posts-photo-alt.svg │ │ ├── posts-photo.svg │ │ ├── posts-poll.svg │ │ ├── posts-quote.svg │ │ ├── posts-text.svg │ │ ├── posts-video-alt.svg │ │ ├── posts-video.svg │ │ ├── reblog-compact.svg │ │ ├── reply-empty.svg │ │ ├── snowman.svg │ │ ├── text-font-size.svg │ │ ├── text-indent.svg │ │ ├── text-list-ordered.svg │ │ ├── text-list-unordered.svg │ │ ├── text-lucille.svg │ │ └── text-quote.svg │ └── instance.css └── locales │ └── .gitkeep ├── dev └── docker-compose.yml.example ├── docs └── kubernetes │ ├── cluster_aliases.sh │ ├── goblin-all-in-one.yaml │ ├── only-goblin-deploy.yaml │ ├── readme.md │ └── setup_step_1.sh ├── firefish.nginx.conf ├── flake.lock ├── goblin.apache.conf ├── gulpfile.js ├── locales ├── README.md ├── ar-SA.yml ├── bn-BD.yml ├── bul_BG.yml ├── ca-ES.yml ├── cs-CZ.yml ├── da-DK.yml ├── de-DE.yml ├── el-GR.yml ├── en-US.yml ├── es-ES.yml ├── fi.yml ├── fr-FR.yml ├── gl.yml ├── id-ID.yml ├── index.d.ts ├── index.js ├── it-IT.yml ├── ja-JP.yml ├── ja-KS.yml ├── kab-KAB.yml ├── kn-IN.yml ├── ko-KR.yml ├── nl-NL.yml ├── no-NO.yml ├── pl-PL.yml ├── pt-PT.yml ├── pt_BR.yml ├── ro-RO.yml ├── ru-RU.yml ├── sk-SK.yml ├── sv-SE.yml ├── th-TH.yml ├── tr-TR.yml ├── ug-CN.yml ├── uk-UA.yml ├── vi-VN.yml ├── zh-CN.yml └── zh-TW.yml ├── package.json ├── packages ├── README.md ├── backend │ ├── .idea │ │ └── .gitignore │ ├── .mocharc.json │ ├── .swcrc │ ├── .vscode │ │ └── settings.json │ ├── assets │ │ ├── LICENSE │ │ ├── api-doc.png │ │ ├── apple-touch-icon.png │ │ ├── avatar.png │ │ ├── badges │ │ │ ├── error.png │ │ │ ├── info.png │ │ │ └── not-found.png │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── favicon.png.svg │ │ ├── favicon.svg │ │ ├── icons │ │ │ ├── 192.png │ │ │ ├── 512.png │ │ │ ├── maskable.png │ │ │ ├── monochrome.png │ │ │ ├── npf-bold.svg │ │ │ ├── npf-color.svg │ │ │ ├── npf-italic.svg │ │ │ ├── npf-link.svg │ │ │ ├── npf-read-more-alt.svg │ │ │ ├── npf-read-more.svg │ │ │ ├── npf-small.svg │ │ │ ├── npf-strikethrough.svg │ │ │ ├── posts-ask.svg │ │ │ ├── posts-audio-alt.svg │ │ │ ├── posts-audio.svg │ │ │ ├── posts-chat.svg │ │ │ ├── posts-link-alt.svg │ │ │ ├── posts-link.svg │ │ │ ├── posts-photo-alt.svg │ │ │ ├── posts-photo.svg │ │ │ ├── posts-poll.svg │ │ │ ├── posts-quote.svg │ │ │ ├── posts-text.svg │ │ │ ├── posts-video-alt.svg │ │ │ ├── posts-video.svg │ │ │ ├── reblog-compact.svg │ │ │ ├── reply-empty.svg │ │ │ ├── snowman.svg │ │ │ ├── text-font-size.svg │ │ │ ├── text-indent.svg │ │ │ ├── text-list-ordered.svg │ │ │ ├── text-list-unordered.svg │ │ │ ├── text-lucille.svg │ │ │ └── text-quote.svg │ │ ├── instance.css │ │ ├── mi-white.png │ │ ├── notification-badges │ │ │ ├── LICENSE │ │ │ ├── at.png │ │ │ ├── check.png │ │ │ ├── clipboard-check-solid.png │ │ │ ├── clock.png │ │ │ ├── comments.png │ │ │ ├── id-card-alt.png │ │ │ ├── null.png │ │ │ ├── plus.png │ │ │ ├── poll-h.png │ │ │ ├── quote-right.png │ │ │ ├── reply.png │ │ │ ├── retweet.png │ │ │ └── user-plus.png │ │ ├── robots.txt │ │ ├── screenshots │ │ │ ├── 1.webp │ │ │ └── 2.webp │ │ ├── sounds │ │ │ ├── aisha │ │ │ │ ├── 1.mp3 │ │ │ │ ├── 2.mp3 │ │ │ │ └── 3.mp3 │ │ │ ├── noizenecio │ │ │ │ ├── kick_gaba.mp3 │ │ │ │ └── kick_gaba2.mp3 │ │ │ └── syuilo │ │ │ │ ├── down.mp3 │ │ │ │ ├── kick.mp3 │ │ │ │ ├── pirori-square-wet.mp3 │ │ │ │ ├── pirori-wet.mp3 │ │ │ │ ├── pirori.mp3 │ │ │ │ ├── poi1.mp3 │ │ │ │ ├── poi2.mp3 │ │ │ │ ├── pope1.mp3 │ │ │ │ ├── pope2.mp3 │ │ │ │ ├── popo.mp3 │ │ │ │ ├── queue-jammed.mp3 │ │ │ │ ├── reverved.mp3 │ │ │ │ ├── ryukyu.mp3 │ │ │ │ ├── snare.mp3 │ │ │ │ ├── square-pico.mp3 │ │ │ │ ├── triple.mp3 │ │ │ │ ├── up.mp3 │ │ │ │ └── waon.mp3 │ │ ├── splash.png │ │ ├── splash.svg │ │ ├── transparent.png │ │ ├── user-unknown.png │ │ └── woozy.png │ ├── check_connect.js │ ├── jsconfig.json │ ├── migration │ │ ├── 1000000000000-Init.js │ │ ├── 1556348509290-Pages.js │ │ ├── 1556746559567-UserProfile.js │ │ ├── 1557476068003-PinnedUsers.js │ │ ├── 1557761316509-AddSomeUrls.js │ │ ├── 1557932705754-ObjectStorageSetting.js │ │ ├── 1558072954435-PageLike.js │ │ ├── 1558103093633-UserGroup.js │ │ ├── 1558257926829-UserGroupInvite.js │ │ ├── 1558266512381-UserListJoining.js │ │ ├── 1561706992953-webauthn.js │ │ ├── 1561873850023-ChartIndexes.js │ │ ├── 1562422242907-PasswordLessLogin.js │ │ ├── 1562444565093-PinnedPage.js │ │ ├── 1562448332510-PageTitleHideOption.js │ │ ├── 1562869971568-ModerationLog.js │ │ ├── 1563757595828-UsedUsername.js │ │ ├── 1565634203341-room.js │ │ ├── 1571220798684-CustomEmojiCategory.js │ │ ├── 1572760203493-nodeinfo.js │ │ ├── 1576269851876-TalkFederationId.js │ │ ├── 1576869585998-ProxyRemoteFiles.js │ │ ├── 1579267006611-v12.js │ │ ├── 1579270193251-v12-2.js │ │ ├── 1579282808087-v12-3.js │ │ ├── 1579544426412-v12-4.js │ │ ├── 1579977526288-v12-5.js │ │ ├── 1579993013959-v12-6.js │ │ ├── 1580069531114-v12-7.js │ │ ├── 1580148575182-v12-8.js │ │ ├── 1580154400017-v12-9.js │ │ ├── 1580276619901-v12-10.js │ │ ├── 1580331224276-v12-11.js │ │ ├── 1580508795118-v12-12.js │ │ ├── 1580543501339-v12-13.js │ │ ├── 1580864313253-v12-14.js │ │ ├── 1581526429287-user-group-invitation.js │ │ ├── 1581695816408-user-group-antenna.js │ │ ├── 1581708415836-drive-user-folder-id-index.js │ │ ├── 1581979837262-promo.js │ │ ├── 1582019042083-featured-injecttion.js │ │ ├── 1582210532752-antenna-exclude.js │ │ ├── 1582875306439-note-reaction-length.js │ │ ├── 1585361548360-miauth.js │ │ ├── 1585385921215-custom-notification.js │ │ ├── 1585772678853-ap-url.js │ │ ├── 1586624197029-AddObjectStorageUseProxy.js │ │ ├── 1586641139527-remote-reaction.js │ │ ├── 1586708940386-pageAiScript.js │ │ ├── 1588044505511-hCaptcha.js │ │ ├── 1589023282116-pubRelay.js │ │ ├── 1595075960584-blurhash.js │ │ ├── 1595077605646-blurhash-for-avatar-banner.js │ │ ├── 1595676934834-instance-icon-url.js │ │ ├── 1595771249699-word-mute.js │ │ ├── 1595782306083-word-mute2.js │ │ ├── 1596548170836-channel.js │ │ ├── 1596786425167-channel2.js │ │ ├── 1597230137744-objectStorageSetPublicRead.js │ │ ├── 1597236229720-IncludingNotificationTypes.js │ │ ├── 1597385880794-add-sensitive-index.js │ │ ├── 1597459042300-channel-unread.js │ │ ├── 1597893996136-ChannelNoteIdDescIndex.js │ │ ├── 1600353287890-mutingNotificationTypes.js │ │ ├── 1603094348345-refine-abuse-user-report.js │ │ ├── 1603095701770-refine-abuse-user-report2.js │ │ ├── 1603776877564-instance-theme-color.js │ │ ├── 1603781553011-instance-favicon.js │ │ ├── 1604821689616-delete-auto-watch.js │ │ ├── 1605408848373-clip-description.js │ │ ├── 1605408971051-comments.js │ │ ├── 1605585339718-instance-pinned-pages.js │ │ ├── 1605965516823-instance-images.js │ │ ├── 1606191203881-no-crawle.js │ │ ├── 1607151207216-instance-pinned-clip.js │ │ ├── 1607353487793-isExplorable.js │ │ ├── 1610277136869-registry.js │ │ ├── 1610277585759-registry2.js │ │ ├── 1610283021566-registry3.js │ │ ├── 1611354329133-followersUri.js │ │ ├── 1611397665007-gallery.js │ │ ├── 1611547387175-objectStorageS3ForcePathStyle.js │ │ ├── 1612619156584-announcement-email.js │ │ ├── 1613155914446-emailNotificationTypes.js │ │ ├── 1613181457597-user-lang.js │ │ ├── 1613503367223-use-bigint-for-driveUsage.js │ │ ├── 1615965918224-chart-v2.js │ │ ├── 1615966519402-chart-v2-2.js │ │ ├── 1618637372000-user-last-active-date.js │ │ ├── 1618639857000-user-hide-online-status.js │ │ ├── 1619942102890-password-reset.js │ │ ├── 1620019354680-ad.js │ │ ├── 1620364649428-ad2.js │ │ ├── 1621479946000-add-note-indexes.js │ │ ├── 1622679304522-user-profile-description-length.js │ │ ├── 1622681548499-log-message-length.js │ │ ├── 1626509500668-fix-remote-file-proxy.js │ │ ├── 1626733991004-allowlist-secure-mode.js │ │ ├── 1629004542760-chart-reindex.js │ │ ├── 1629024377804-deepl-integration.js │ │ ├── 1629288472000-fix-channel-userId.js │ │ ├── 1629512953000-user-is-deleted.js │ │ ├── 1629778475000-deepl-integration2.js │ │ ├── 1629833361000-AddShowTLReplies.js │ │ ├── 1629968054000_userInstanceBlocks.js │ │ ├── 1633068642000-email-required-for-signup.js │ │ ├── 1633071909016-user-pending.js │ │ ├── 1634486652000-user-public-reactions.js │ │ ├── 1634902659689-delete-log.js │ │ ├── 1635500777168-note-thread-mute.js │ │ ├── 1636197624383-ff-visibility.js │ │ ├── 1636697408073-remove-via-mobile.js │ │ ├── 1637320813000-forwarded-report.js │ │ ├── 1639325650583-chart-v3.js │ │ ├── 1642611822809-emoji-url.js │ │ ├── 1642613870898-drive-file-webpublic-type.js │ │ ├── 1643963705770-chart-v4.js │ │ ├── 1643966656277-chart-v5.js │ │ ├── 1643967331284-chart-v6.js │ │ ├── 1644010796173-convert-hard-mutes.js │ │ ├── 1644058404077-chart-v7.js │ │ ├── 1644059847460-chart-v8.js │ │ ├── 1644060125705-chart-v9.js │ │ ├── 1644073149413-chart-v10.js │ │ ├── 1644095659741-chart-v11.js │ │ ├── 1644328606241-chart-v12.js │ │ ├── 1644331238153-chart-v13.js │ │ ├── 1644344266289-chart-v14.js │ │ ├── 1644395759931-instance-theme-color.js │ │ ├── 1644481657998-chart-v15.js │ │ ├── 1644551208096-following-indexes.js │ │ ├── 1645340161439-remove-max-note-text-length.js │ │ ├── 1645599900873-federation-chart-pubsub.js │ │ ├── 1646143552768-instance-default-theme.js │ │ ├── 1646387162108-mute-expires-at.js │ │ ├── 1646549089451-poll-ended-notification.js │ │ ├── 1646633030285-chart-federation-active.js │ │ ├── 1646655454495-remove-instance-drive-columns.js │ │ ├── 1646732390560-chart-federation-active-sub-pub.js │ │ ├── 1648548247382-webhook.js │ │ ├── 1648816172177-webhook-2.js │ │ ├── 1651224615271-foreign-key.js │ │ ├── 1652859567549-uniform-themecolor.js │ │ ├── 1655368940105-nsfw-detection.js │ │ ├── 1655371960534-nsfw-detection-2.js │ │ ├── 1655388169582-nsfw-detection-3.js │ │ ├── 1655393015659-nsfw-detection-4.js │ │ ├── 1655813815729-driveCapacityOverrideMb.js │ │ ├── 1655918165614-user-ip.js │ │ ├── 1656122560740-file-ip.js │ │ ├── 1656251734807-nsfw-detection-5.js │ │ ├── 1656328812281-ip-2.js │ │ ├── 1656408772602-nsfw-detection-6.js │ │ ├── 1656772790599-user-moderation-note.js │ │ ├── 1657346559800-active-email-validation.js │ │ ├── 1658203170545firefish.js │ │ ├── 1658656633972-note-replies-function.js │ │ ├── 1658939464003CustomMOTD.js │ │ ├── 1658941974648CustomSplashIcons.js │ │ ├── 1658981842728FixCalckey.js │ │ ├── 1659042130648RecommendedTimeline.js │ │ ├── 1660068273737GuestTimeline.js │ │ ├── 1665091090561-add-renote-muting.js │ │ ├── 1668828368510PageDraft.js │ │ ├── 1668831378728FixCalckeyAgain.js │ │ ├── 1669138716634-whetherPushNotifyToSendReadMessage.js │ │ ├── 1669288094000-AddMovedToAndKnownAs.js │ │ ├── 1671199573000-AddFkAbuseUserReportTargetUserIdToUserId.js │ │ ├── 1671388343000-CalckeyRepoMove.js │ │ ├── 1672882664294-DefaultReaction.js │ │ ├── 1673336077243-PollChoiceLength.js │ │ ├── 1676093997212-AntennaInstances.js │ │ ├── 1677935903517-DriveComment.js │ │ ├── 1678426061773-tweak-varchar-length.js │ │ ├── 1678945242650-add-props-for-custom-emoji.js │ │ ├── 1679269929000-fix-repo.js │ │ ├── 1680375641101-clean-charts.js │ │ ├── 1680426269172-SpeakAsCat.js │ │ ├── 1682753227899-NoteEdit.js │ │ ├── 1682777547198-LibreTranslate.js │ │ ├── 1682891890317-InstanceSilence.js │ │ ├── 1682891891317-AddHiddenPosts.js │ │ ├── 1683682889948-PreventAiLearning.js │ │ ├── 1683980686995-ExperimentalFeatures.js │ │ ├── 1684206886988-remove-showTimelineReplies.js │ │ ├── 1684494870830-EmojiSize.js │ │ ├── 1688280713783-add-meta-options.js │ │ ├── 1688845537045-announcement-popup.js │ │ ├── 1689136347561-donation-link.js │ │ ├── 1689739513827-firefish-repo.js │ │ ├── 1689957674000-firefish-repo.js │ │ ├── 1689957800000-Goblin-start.js │ │ ├── 1689957900000-quote-count.js │ │ ├── 1689957900100-tumblr.js │ │ ├── 1710414776532-unique-user-ids.js │ │ ├── 1712201438090-hashtag-following-and-blocking.js │ │ ├── 1712665566741-note-slug.js │ │ ├── 1713881596237-goblin-repo-move.js │ │ ├── 1716060163114-no-cloned-id-exploit.js │ │ └── 1717142049375-externalPostId.js │ ├── native-utils │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── __test__ │ │ │ └── index.spec.mjs │ │ ├── build.rs │ │ ├── migration │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ └── src │ │ │ │ ├── lib.rs │ │ │ │ ├── m20230531_180824_drop_reversi.rs │ │ │ │ ├── m20230627_185451_index_note_url.rs │ │ │ │ ├── m20230709_000510_move_antenna_to_cache.rs │ │ │ │ ├── main.rs │ │ │ │ └── vec_to_json.rs │ │ ├── npm │ │ │ ├── android-arm-eabi │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── android-arm64 │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── darwin-arm64 │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── darwin-universal │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── darwin-x64 │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── freebsd-x64 │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── linux-arm-gnueabihf │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── linux-arm64-gnu │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── linux-arm64-musl │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── linux-x64-gnu │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── linux-x64-musl │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── win32-arm64-msvc │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── win32-ia32-msvc │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ └── win32-x64-msvc │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ ├── package.json │ │ ├── src │ │ │ ├── database │ │ │ │ ├── error.rs │ │ │ │ └── mod.rs │ │ │ ├── lib.rs │ │ │ ├── macros.rs │ │ │ ├── mastodon_api.rs │ │ │ ├── model │ │ │ │ ├── entity.rs │ │ │ │ ├── entity │ │ │ │ │ ├── abuse_user_report.rs │ │ │ │ │ ├── access_token.rs │ │ │ │ │ ├── ad.rs │ │ │ │ │ ├── announcement.rs │ │ │ │ │ ├── announcement_read.rs │ │ │ │ │ ├── antenna.rs │ │ │ │ │ ├── antenna_note.rs │ │ │ │ │ ├── app.rs │ │ │ │ │ ├── attestation_challenge.rs │ │ │ │ │ ├── auth_session.rs │ │ │ │ │ ├── blocking.rs │ │ │ │ │ ├── channel.rs │ │ │ │ │ ├── channel_following.rs │ │ │ │ │ ├── channel_note_pining.rs │ │ │ │ │ ├── clip.rs │ │ │ │ │ ├── clip_note.rs │ │ │ │ │ ├── drive_file.rs │ │ │ │ │ ├── drive_folder.rs │ │ │ │ │ ├── emoji.rs │ │ │ │ │ ├── follow_request.rs │ │ │ │ │ ├── following.rs │ │ │ │ │ ├── gallery_like.rs │ │ │ │ │ ├── gallery_post.rs │ │ │ │ │ ├── hashtag.rs │ │ │ │ │ ├── instance.rs │ │ │ │ │ ├── messaging_message.rs │ │ │ │ │ ├── meta.rs │ │ │ │ │ ├── migrations.rs │ │ │ │ │ ├── moderation_log.rs │ │ │ │ │ ├── muted_note.rs │ │ │ │ │ ├── muting.rs │ │ │ │ │ ├── newtype │ │ │ │ │ │ ├── macros.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ ├── note.rs │ │ │ │ │ ├── note_edit.rs │ │ │ │ │ ├── note_favorite.rs │ │ │ │ │ ├── note_reaction.rs │ │ │ │ │ ├── note_thread_muting.rs │ │ │ │ │ ├── note_unread.rs │ │ │ │ │ ├── note_watching.rs │ │ │ │ │ ├── notification.rs │ │ │ │ │ ├── page.rs │ │ │ │ │ ├── page_like.rs │ │ │ │ │ ├── password_reset_request.rs │ │ │ │ │ ├── poll.rs │ │ │ │ │ ├── poll_vote.rs │ │ │ │ │ ├── prelude.rs │ │ │ │ │ ├── promo_note.rs │ │ │ │ │ ├── promo_read.rs │ │ │ │ │ ├── registration_ticket.rs │ │ │ │ │ ├── registry_item.rs │ │ │ │ │ ├── relay.rs │ │ │ │ │ ├── renote_muting.rs │ │ │ │ │ ├── sea_orm_active_enums.rs │ │ │ │ │ ├── signin.rs │ │ │ │ │ ├── sw_subscription.rs │ │ │ │ │ ├── used_username.rs │ │ │ │ │ ├── user.rs │ │ │ │ │ ├── user_group.rs │ │ │ │ │ ├── user_group_invitation.rs │ │ │ │ │ ├── user_group_invite.rs │ │ │ │ │ ├── user_group_joining.rs │ │ │ │ │ ├── user_ip.rs │ │ │ │ │ ├── user_keypair.rs │ │ │ │ │ ├── user_list.rs │ │ │ │ │ ├── user_list_joining.rs │ │ │ │ │ ├── user_note_pining.rs │ │ │ │ │ ├── user_pending.rs │ │ │ │ │ ├── user_profile.rs │ │ │ │ │ ├── user_publickey.rs │ │ │ │ │ ├── user_security_key.rs │ │ │ │ │ └── webhook.rs │ │ │ │ ├── error.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── repository.rs │ │ │ │ ├── repository │ │ │ │ │ └── antenna.rs │ │ │ │ ├── schema.rs │ │ │ │ └── schema │ │ │ │ │ ├── antenna.rs │ │ │ │ │ └── app.rs │ │ │ └── util │ │ │ │ ├── id.rs │ │ │ │ ├── mod.rs │ │ │ │ └── random.rs │ │ └── tests │ │ │ ├── common.rs │ │ │ └── model │ │ │ ├── mod.rs │ │ │ ├── repository.rs │ │ │ └── repository │ │ │ └── antenna.rs │ ├── nsfw-model │ │ ├── group1-shard1of6 │ │ ├── group1-shard2of6 │ │ ├── group1-shard3of6 │ │ ├── group1-shard4of6 │ │ ├── group1-shard5of6 │ │ ├── group1-shard6of6 │ │ └── model.json │ ├── ormconfig.js │ ├── package.json │ ├── src │ │ ├── @types │ │ │ ├── hcaptcha.d.ts │ │ │ ├── http-signature.d.ts │ │ │ ├── koa-json-body.d.ts │ │ │ ├── koa-remove-trailing-slashes │ │ │ │ └── index.d.ts │ │ │ ├── koa-slow.d.ts │ │ │ ├── os-utils.d.ts │ │ │ └── package.json.d.ts │ │ ├── boot │ │ │ ├── index.ts │ │ │ ├── master.ts │ │ │ └── worker.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ ├── load.ts │ │ │ └── types.ts │ │ ├── const.ts │ │ ├── daemons │ │ │ ├── janitor.ts │ │ │ ├── queue-stats.ts │ │ │ └── server-stats.ts │ │ ├── db │ │ │ ├── elasticsearch.ts │ │ │ ├── logger.ts │ │ │ ├── meilisearch.ts │ │ │ ├── postgre.ts │ │ │ ├── redis.ts │ │ │ └── sonic.ts │ │ ├── env.ts │ │ ├── global.d.ts │ │ ├── index.ts │ │ ├── mfm │ │ │ ├── from-html.ts │ │ │ └── to-html.ts │ │ ├── misc │ │ │ ├── acct.ts │ │ │ ├── antenna-cache.ts │ │ │ ├── api-permissions.ts │ │ │ ├── app-lock.ts │ │ │ ├── before-shutdown.ts │ │ │ ├── cache.ts │ │ │ ├── captcha.ts │ │ │ ├── check-hit-antenna.ts │ │ │ ├── check-word-mute.ts │ │ │ ├── clone.ts │ │ │ ├── content-disposition.ts │ │ │ ├── convert-host.ts │ │ │ ├── convert-milliseconds.ts │ │ │ ├── count-same-renotes.ts │ │ │ ├── create-temp.ts │ │ │ ├── detect-url-mime.ts │ │ │ ├── download-text-file.ts │ │ │ ├── download-url.ts │ │ │ ├── emoji-meta.ts │ │ │ ├── emoji-regex.ts │ │ │ ├── extract-custom-emojis-from-mfm.ts │ │ │ ├── extract-hashtags.ts │ │ │ ├── extract-mentions.ts │ │ │ ├── fetch-meta.ts │ │ │ ├── fetch-proxy-account.ts │ │ │ ├── fetch.ts │ │ │ ├── gen-id.ts │ │ │ ├── gen-identicon.ts │ │ │ ├── gen-key-pair.ts │ │ │ ├── get-file-info.ts │ │ │ ├── get-ip-hash.ts │ │ │ ├── get-note-summary.ts │ │ │ ├── get-reaction-emoji.ts │ │ │ ├── hard-limits.ts │ │ │ ├── html │ │ │ │ └── index.ts │ │ │ ├── i18n.ts │ │ │ ├── id │ │ │ │ ├── aid.ts │ │ │ │ ├── meid.ts │ │ │ │ ├── meidg.ts │ │ │ │ └── object-id.ts │ │ │ ├── identifiable-error.ts │ │ │ ├── is-duplicate-key-value-error.ts │ │ │ ├── is-instance-muted.ts │ │ │ ├── is-mime-image.ts │ │ │ ├── is-quote.ts │ │ │ ├── is-user-related.ts │ │ │ ├── keypair-store.ts │ │ │ ├── langmap.ts │ │ │ ├── normalize-for-search.ts │ │ │ ├── note │ │ │ │ ├── ancestors.ts │ │ │ │ └── noteSlug.ts │ │ │ ├── nyaize.ts │ │ │ ├── password.ts │ │ │ ├── populate-emojis.ts │ │ │ ├── post.ts │ │ │ ├── process-masto-notes.ts │ │ │ ├── reaction-lib.ts │ │ │ ├── safe-for-sql.ts │ │ │ ├── schema.ts │ │ │ ├── secure-rndstr.ts │ │ │ ├── should-block-instance.ts │ │ │ ├── show-machine-info.ts │ │ │ ├── skipped-instances.ts │ │ │ ├── sql-like-escape.ts │ │ │ ├── truncate.ts │ │ │ └── webhook-cache.ts │ │ ├── models │ │ │ ├── entities │ │ │ │ ├── abuse-user-report.ts │ │ │ │ ├── access-token.ts │ │ │ │ ├── ad.ts │ │ │ │ ├── announcement-read.ts │ │ │ │ ├── announcement.ts │ │ │ │ ├── antenna.ts │ │ │ │ ├── app.ts │ │ │ │ ├── attestation-challenge.ts │ │ │ │ ├── auth-session.ts │ │ │ │ ├── blocking.ts │ │ │ │ ├── channel-following.ts │ │ │ │ ├── channel-note-pining.ts │ │ │ │ ├── channel.ts │ │ │ │ ├── clip-note.ts │ │ │ │ ├── clip.ts │ │ │ │ ├── drive-file.ts │ │ │ │ ├── drive-folder.ts │ │ │ │ ├── emoji.ts │ │ │ │ ├── follow-request.ts │ │ │ │ ├── following.ts │ │ │ │ ├── gallery-like.ts │ │ │ │ ├── gallery-post.ts │ │ │ │ ├── hashtag.ts │ │ │ │ ├── instance.ts │ │ │ │ ├── messaging-message.ts │ │ │ │ ├── meta.ts │ │ │ │ ├── moderation-log.ts │ │ │ │ ├── muted-note.ts │ │ │ │ ├── muting.ts │ │ │ │ ├── note-edit.ts │ │ │ │ ├── note-favorite.ts │ │ │ │ ├── note-reaction.ts │ │ │ │ ├── note-thread-muting.ts │ │ │ │ ├── note-unread.ts │ │ │ │ ├── note-watching.ts │ │ │ │ ├── note.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── page-like.ts │ │ │ │ ├── page.ts │ │ │ │ ├── password-reset-request.ts │ │ │ │ ├── poll-vote.ts │ │ │ │ ├── poll.ts │ │ │ │ ├── promo-note.ts │ │ │ │ ├── promo-read.ts │ │ │ │ ├── registration-tickets.ts │ │ │ │ ├── registry-item.ts │ │ │ │ ├── relay.ts │ │ │ │ ├── renote-muting.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── sw-subscription.ts │ │ │ │ ├── used-username.ts │ │ │ │ ├── user-group-invitation.ts │ │ │ │ ├── user-group-joining.ts │ │ │ │ ├── user-group.ts │ │ │ │ ├── user-ip.ts │ │ │ │ ├── user-keypair.ts │ │ │ │ ├── user-list-joining.ts │ │ │ │ ├── user-list.ts │ │ │ │ ├── user-note-pining.ts │ │ │ │ ├── user-pending.ts │ │ │ │ ├── user-profile.ts │ │ │ │ ├── user-publickey.ts │ │ │ │ ├── user-security-key.ts │ │ │ │ ├── user.ts │ │ │ │ └── webhook.ts │ │ │ ├── id.ts │ │ │ ├── index.ts │ │ │ ├── repositories │ │ │ │ ├── abuse-user-report.ts │ │ │ │ ├── antenna.ts │ │ │ │ ├── app.ts │ │ │ │ ├── auth-session.ts │ │ │ │ ├── blocking.ts │ │ │ │ ├── channel.ts │ │ │ │ ├── clip.ts │ │ │ │ ├── drive-file.ts │ │ │ │ ├── drive-folder.ts │ │ │ │ ├── emoji.ts │ │ │ │ ├── follow-request.ts │ │ │ │ ├── following.ts │ │ │ │ ├── gallery-like.ts │ │ │ │ ├── gallery-post.ts │ │ │ │ ├── hashtag.ts │ │ │ │ ├── instance.ts │ │ │ │ ├── messaging-message.ts │ │ │ │ ├── moderation-logs.ts │ │ │ │ ├── muting.ts │ │ │ │ ├── note-favorite.ts │ │ │ │ ├── note-reaction.ts │ │ │ │ ├── note.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── page-like.ts │ │ │ │ ├── page.ts │ │ │ │ ├── relay.ts │ │ │ │ ├── renote-muting.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── user-group-invitation.ts │ │ │ │ ├── user-group.ts │ │ │ │ ├── user-list.ts │ │ │ │ └── user.ts │ │ │ └── schema │ │ │ │ ├── antenna.ts │ │ │ │ ├── app.ts │ │ │ │ ├── blocking.ts │ │ │ │ ├── channel.ts │ │ │ │ ├── clip.ts │ │ │ │ ├── drive-file.ts │ │ │ │ ├── drive-folder.ts │ │ │ │ ├── emoji.ts │ │ │ │ ├── federation-instance.ts │ │ │ │ ├── following.ts │ │ │ │ ├── gallery-post.ts │ │ │ │ ├── hashtag.ts │ │ │ │ ├── messaging-message.ts │ │ │ │ ├── muting.ts │ │ │ │ ├── note-edit.ts │ │ │ │ ├── note-favorite.ts │ │ │ │ ├── note-reaction.ts │ │ │ │ ├── note.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── page.ts │ │ │ │ ├── queue.ts │ │ │ │ ├── renote-muting.ts │ │ │ │ ├── user-group.ts │ │ │ │ ├── user-list.ts │ │ │ │ └── user.ts │ │ ├── prelude │ │ │ ├── README.md │ │ │ ├── array.ts │ │ │ ├── await-all.ts │ │ │ ├── math.ts │ │ │ ├── maybe.ts │ │ │ ├── relation.ts │ │ │ ├── string.ts │ │ │ ├── symbol.ts │ │ │ ├── time.ts │ │ │ ├── url.ts │ │ │ └── xml.ts │ │ ├── queue │ │ │ ├── get-job-info.ts │ │ │ ├── index.ts │ │ │ ├── initialize.ts │ │ │ ├── logger.ts │ │ │ ├── processors │ │ │ │ ├── background │ │ │ │ │ ├── index-all-notes.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── db │ │ │ │ │ ├── delete-account.ts │ │ │ │ │ ├── delete-drive-files.ts │ │ │ │ │ ├── export-blocking.ts │ │ │ │ │ ├── export-custom-emojis.ts │ │ │ │ │ ├── export-following.ts │ │ │ │ │ ├── export-mute.ts │ │ │ │ │ ├── export-notes.ts │ │ │ │ │ ├── export-user-lists.ts │ │ │ │ │ ├── import-blocking.ts │ │ │ │ │ ├── import-custom-emojis.ts │ │ │ │ │ ├── import-firefish-post.ts │ │ │ │ │ ├── import-following.ts │ │ │ │ │ ├── import-masto-post.ts │ │ │ │ │ ├── import-muting.ts │ │ │ │ │ ├── import-posts.ts │ │ │ │ │ ├── import-user-lists.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── deliver.ts │ │ │ │ ├── ended-poll-notification.ts │ │ │ │ ├── inbox.ts │ │ │ │ ├── object-storage │ │ │ │ │ ├── clean-remote-files.ts │ │ │ │ │ ├── delete-file.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── system │ │ │ │ │ ├── check-expired-mutings.ts │ │ │ │ │ ├── clean-charts.ts │ │ │ │ │ ├── clean.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── local-emoji-size.ts │ │ │ │ │ ├── resync-charts.ts │ │ │ │ │ ├── tick-charts.ts │ │ │ │ │ └── verify-links.ts │ │ │ │ ├── tumblr │ │ │ │ │ ├── fetch.ts │ │ │ │ │ └── index.ts │ │ │ │ └── webhook-deliver.ts │ │ │ ├── queues.ts │ │ │ └── types.ts │ │ ├── remote │ │ │ ├── activitypub │ │ │ │ ├── ap-request.ts │ │ │ │ ├── audience.ts │ │ │ │ ├── check-fetch.ts │ │ │ │ ├── db-resolver.ts │ │ │ │ ├── deliver-manager.ts │ │ │ │ ├── kernel │ │ │ │ │ ├── accept │ │ │ │ │ │ ├── follow.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── add │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── announce │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── note.ts │ │ │ │ │ ├── block │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── create │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── note.ts │ │ │ │ │ ├── delete │ │ │ │ │ │ ├── actor.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── note.ts │ │ │ │ │ ├── flag │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── follow.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── like.ts │ │ │ │ │ ├── move │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── read.ts │ │ │ │ │ ├── reject │ │ │ │ │ │ ├── follow.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── remove │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── undo │ │ │ │ │ │ ├── accept.ts │ │ │ │ │ │ ├── announce.ts │ │ │ │ │ │ ├── block.ts │ │ │ │ │ │ ├── follow.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── like.ts │ │ │ │ │ └── update │ │ │ │ │ │ └── index.ts │ │ │ │ ├── logger.ts │ │ │ │ ├── misc │ │ │ │ │ ├── contexts.ts │ │ │ │ │ ├── get-note-html.ts │ │ │ │ │ ├── html-to-mfm.ts │ │ │ │ │ └── ld-signature.ts │ │ │ │ ├── models │ │ │ │ │ ├── icon.ts │ │ │ │ │ ├── identifier.ts │ │ │ │ │ ├── image.ts │ │ │ │ │ ├── mention.ts │ │ │ │ │ ├── note.ts │ │ │ │ │ ├── person.ts │ │ │ │ │ ├── question.ts │ │ │ │ │ └── tag.ts │ │ │ │ ├── perform.ts │ │ │ │ ├── renderer │ │ │ │ │ ├── accept.ts │ │ │ │ │ ├── add.ts │ │ │ │ │ ├── announce.ts │ │ │ │ │ ├── block.ts │ │ │ │ │ ├── create.ts │ │ │ │ │ ├── delete.ts │ │ │ │ │ ├── document.ts │ │ │ │ │ ├── emoji.ts │ │ │ │ │ ├── flag.ts │ │ │ │ │ ├── follow-relay.ts │ │ │ │ │ ├── follow-user.ts │ │ │ │ │ ├── follow.ts │ │ │ │ │ ├── hashtag.ts │ │ │ │ │ ├── image.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── key.ts │ │ │ │ │ ├── like.ts │ │ │ │ │ ├── mention.ts │ │ │ │ │ ├── note.ts │ │ │ │ │ ├── ordered-collection-page.ts │ │ │ │ │ ├── ordered-collection.ts │ │ │ │ │ ├── person.ts │ │ │ │ │ ├── question.ts │ │ │ │ │ ├── read.ts │ │ │ │ │ ├── reject.ts │ │ │ │ │ ├── remove.ts │ │ │ │ │ ├── tombstone.ts │ │ │ │ │ ├── undo.ts │ │ │ │ │ ├── update.ts │ │ │ │ │ └── vote.ts │ │ │ │ ├── request.ts │ │ │ │ ├── resolver.ts │ │ │ │ └── type.ts │ │ │ ├── logger.ts │ │ │ ├── resolve-user.ts │ │ │ └── webfinger.ts │ │ ├── server │ │ │ ├── activitypub.ts │ │ │ ├── activitypub │ │ │ │ ├── featured.ts │ │ │ │ ├── followers.ts │ │ │ │ ├── following.ts │ │ │ │ └── outbox.ts │ │ │ ├── api │ │ │ │ ├── 2fa.ts │ │ │ │ ├── api-handler.ts │ │ │ │ ├── authenticate.ts │ │ │ │ ├── call.ts │ │ │ │ ├── common │ │ │ │ │ ├── generate-block-query.ts │ │ │ │ │ ├── generate-channel-query.ts │ │ │ │ │ ├── generate-muted-note-query.ts │ │ │ │ │ ├── generate-muted-note-thread-query.ts │ │ │ │ │ ├── generate-muted-user-query.ts │ │ │ │ │ ├── generate-native-user-token.ts │ │ │ │ │ ├── generate-replies-query.ts │ │ │ │ │ ├── generate-visibility-query.ts │ │ │ │ │ ├── generated-muted-renote-query.ts │ │ │ │ │ ├── getters.ts │ │ │ │ │ ├── inject-featured.ts │ │ │ │ │ ├── inject-promo.ts │ │ │ │ │ ├── is-native-token.ts │ │ │ │ │ ├── make-pagination-query.ts │ │ │ │ │ ├── read-messaging-message.ts │ │ │ │ │ ├── read-notification.ts │ │ │ │ │ ├── signin.ts │ │ │ │ │ └── signup.ts │ │ │ │ ├── compatibility.ts │ │ │ │ ├── define.ts │ │ │ │ ├── endpoints.ts │ │ │ │ ├── endpoints │ │ │ │ │ ├── admin │ │ │ │ │ │ ├── abuse-user-reports.ts │ │ │ │ │ │ ├── accounts │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ └── hosted.ts │ │ │ │ │ │ ├── ad │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ ├── announcements │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ ├── delete-account.ts │ │ │ │ │ │ ├── delete-all-files-of-a-user.ts │ │ │ │ │ │ ├── drive-capacity-override.ts │ │ │ │ │ │ ├── drive │ │ │ │ │ │ │ ├── clean-remote-files.ts │ │ │ │ │ │ │ ├── cleanup.ts │ │ │ │ │ │ │ ├── files.ts │ │ │ │ │ │ │ └── show-file.ts │ │ │ │ │ │ ├── emoji │ │ │ │ │ │ │ ├── add-aliases-bulk.ts │ │ │ │ │ │ │ ├── add.ts │ │ │ │ │ │ │ ├── copy.ts │ │ │ │ │ │ │ ├── delete-bulk.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── import-zip.ts │ │ │ │ │ │ │ ├── list-remote.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ ├── remove-aliases-bulk.ts │ │ │ │ │ │ │ ├── set-aliases-bulk.ts │ │ │ │ │ │ │ ├── set-category-bulk.ts │ │ │ │ │ │ │ ├── set-license-bulk.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ ├── federation │ │ │ │ │ │ │ ├── delete-all-files.ts │ │ │ │ │ │ │ ├── refresh-remote-instance-metadata.ts │ │ │ │ │ │ │ ├── remove-all-following.ts │ │ │ │ │ │ │ └── update-instance.ts │ │ │ │ │ │ ├── get-index-stats.ts │ │ │ │ │ │ ├── get-table-stats.ts │ │ │ │ │ │ ├── get-user-ips.ts │ │ │ │ │ │ ├── invite.ts │ │ │ │ │ │ ├── meta.ts │ │ │ │ │ │ ├── moderators │ │ │ │ │ │ │ ├── add.ts │ │ │ │ │ │ │ └── remove.ts │ │ │ │ │ │ ├── promo │ │ │ │ │ │ │ └── create.ts │ │ │ │ │ │ ├── queue │ │ │ │ │ │ │ ├── clear.ts │ │ │ │ │ │ │ ├── deliver-delayed.ts │ │ │ │ │ │ │ ├── inbox-delayed.ts │ │ │ │ │ │ │ └── stats.ts │ │ │ │ │ │ ├── relays │ │ │ │ │ │ │ ├── add.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ └── remove.ts │ │ │ │ │ │ ├── reset-password.ts │ │ │ │ │ │ ├── resolve-abuse-user-report.ts │ │ │ │ │ │ ├── search │ │ │ │ │ │ │ └── index-all.ts │ │ │ │ │ │ ├── send-email.ts │ │ │ │ │ │ ├── send-mod-mail.ts │ │ │ │ │ │ ├── server-info.ts │ │ │ │ │ │ ├── show-moderation-logs.ts │ │ │ │ │ │ ├── show-user.ts │ │ │ │ │ │ ├── show-users.ts │ │ │ │ │ │ ├── silence-user.ts │ │ │ │ │ │ ├── suspend-user.ts │ │ │ │ │ │ ├── unsilence-user.ts │ │ │ │ │ │ ├── unsuspend-user.ts │ │ │ │ │ │ ├── update-meta.ts │ │ │ │ │ │ ├── update-user-note.ts │ │ │ │ │ │ └── vacuum.ts │ │ │ │ │ ├── announcements.ts │ │ │ │ │ ├── antennas │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ ├── markread.ts │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── ap │ │ │ │ │ │ ├── get.ts │ │ │ │ │ │ └── show.ts │ │ │ │ │ ├── app │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ └── show.ts │ │ │ │ │ ├── auth │ │ │ │ │ │ ├── accept.ts │ │ │ │ │ │ └── session │ │ │ │ │ │ │ ├── generate.ts │ │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ │ └── userkey.ts │ │ │ │ │ ├── blocking │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ └── list.ts │ │ │ │ │ ├── channels │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── featured.ts │ │ │ │ │ │ ├── follow.ts │ │ │ │ │ │ ├── followed.ts │ │ │ │ │ │ ├── owned.ts │ │ │ │ │ │ ├── search.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── timeline.ts │ │ │ │ │ │ ├── unfollow.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── charts │ │ │ │ │ │ ├── active-users.ts │ │ │ │ │ │ ├── ap-request.ts │ │ │ │ │ │ ├── drive.ts │ │ │ │ │ │ ├── federation.ts │ │ │ │ │ │ ├── hashtag.ts │ │ │ │ │ │ ├── instance.ts │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ ├── user │ │ │ │ │ │ │ ├── drive.ts │ │ │ │ │ │ │ ├── following.ts │ │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ │ └── reactions.ts │ │ │ │ │ │ └── users.ts │ │ │ │ │ ├── clips │ │ │ │ │ │ ├── add-note.ts │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ ├── remove-note.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── compatibility │ │ │ │ │ │ ├── custom-emojis.ts │ │ │ │ │ │ ├── instance-info.ts │ │ │ │ │ │ └── peers.ts │ │ │ │ │ ├── custom-motd.ts │ │ │ │ │ ├── custom-splash-icons.ts │ │ │ │ │ ├── drive.ts │ │ │ │ │ ├── drive │ │ │ │ │ │ ├── files.ts │ │ │ │ │ │ ├── files │ │ │ │ │ │ │ ├── attached-notes.ts │ │ │ │ │ │ │ ├── caption-image.ts │ │ │ │ │ │ │ ├── check-existence.ts │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── find-by-hash.ts │ │ │ │ │ │ │ ├── find.ts │ │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ │ ├── update.ts │ │ │ │ │ │ │ └── upload-from-url.ts │ │ │ │ │ │ ├── folders.ts │ │ │ │ │ │ ├── folders │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── find.ts │ │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ └── stream.ts │ │ │ │ │ ├── email-address │ │ │ │ │ │ └── available.ts │ │ │ │ │ ├── emoji.ts │ │ │ │ │ ├── endpoint.ts │ │ │ │ │ ├── endpoints.ts │ │ │ │ │ ├── export-custom-emojis.ts │ │ │ │ │ ├── federation │ │ │ │ │ │ ├── followers.ts │ │ │ │ │ │ ├── following.ts │ │ │ │ │ │ ├── instances.ts │ │ │ │ │ │ ├── show-instance.ts │ │ │ │ │ │ ├── stats.ts │ │ │ │ │ │ ├── update-remote-user.ts │ │ │ │ │ │ └── users.ts │ │ │ │ │ ├── following │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── invalidate.ts │ │ │ │ │ │ └── requests │ │ │ │ │ │ │ ├── accept.ts │ │ │ │ │ │ │ ├── cancel.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ └── reject.ts │ │ │ │ │ ├── gallery │ │ │ │ │ │ ├── featured.ts │ │ │ │ │ │ ├── popular.ts │ │ │ │ │ │ ├── posts.ts │ │ │ │ │ │ └── posts │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── like.ts │ │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ │ ├── unlike.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── get-online-users-count.ts │ │ │ │ │ ├── get-sounds.ts │ │ │ │ │ ├── hashtags │ │ │ │ │ │ ├── block.ts │ │ │ │ │ │ ├── blocking.ts │ │ │ │ │ │ ├── follow.ts │ │ │ │ │ │ ├── following.ts │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ ├── search.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── trend.ts │ │ │ │ │ │ ├── unblock.ts │ │ │ │ │ │ ├── unfollow.ts │ │ │ │ │ │ └── users.ts │ │ │ │ │ ├── i.ts │ │ │ │ │ ├── i │ │ │ │ │ │ ├── 2fa │ │ │ │ │ │ │ ├── done.ts │ │ │ │ │ │ │ ├── key-done.ts │ │ │ │ │ │ │ ├── password-less.ts │ │ │ │ │ │ │ ├── register-key.ts │ │ │ │ │ │ │ ├── register.ts │ │ │ │ │ │ │ ├── remove-key.ts │ │ │ │ │ │ │ ├── unregister.ts │ │ │ │ │ │ │ └── update-key.ts │ │ │ │ │ │ ├── apps.ts │ │ │ │ │ │ ├── authorized-apps.ts │ │ │ │ │ │ ├── change-password.ts │ │ │ │ │ │ ├── delete-account.ts │ │ │ │ │ │ ├── export-blocking.ts │ │ │ │ │ │ ├── export-following.ts │ │ │ │ │ │ ├── export-mute.ts │ │ │ │ │ │ ├── export-notes.ts │ │ │ │ │ │ ├── export-user-lists.ts │ │ │ │ │ │ ├── favorites.ts │ │ │ │ │ │ ├── gallery │ │ │ │ │ │ │ ├── likes.ts │ │ │ │ │ │ │ └── posts.ts │ │ │ │ │ │ ├── get-word-muted-notes-count.ts │ │ │ │ │ │ ├── import-blocking.ts │ │ │ │ │ │ ├── import-following.ts │ │ │ │ │ │ ├── import-muting.ts │ │ │ │ │ │ ├── import-posts.ts │ │ │ │ │ │ ├── import-user-lists.ts │ │ │ │ │ │ ├── known-as.ts │ │ │ │ │ │ ├── move.ts │ │ │ │ │ │ ├── notifications.ts │ │ │ │ │ │ ├── page-likes.ts │ │ │ │ │ │ ├── pages.ts │ │ │ │ │ │ ├── pin.ts │ │ │ │ │ │ ├── read-all-messaging-messages.ts │ │ │ │ │ │ ├── read-all-unread-notes.ts │ │ │ │ │ │ ├── read-announcement.ts │ │ │ │ │ │ ├── regenerate-token.ts │ │ │ │ │ │ ├── registry │ │ │ │ │ │ │ ├── get-all.ts │ │ │ │ │ │ │ ├── get-detail.ts │ │ │ │ │ │ │ ├── get-unsecure.ts │ │ │ │ │ │ │ ├── get.ts │ │ │ │ │ │ │ ├── keys-with-type.ts │ │ │ │ │ │ │ ├── keys.ts │ │ │ │ │ │ │ ├── remove.ts │ │ │ │ │ │ │ ├── scopes.ts │ │ │ │ │ │ │ └── set.ts │ │ │ │ │ │ ├── revoke-token.ts │ │ │ │ │ │ ├── signin-history.ts │ │ │ │ │ │ ├── unpin.ts │ │ │ │ │ │ ├── update-email.ts │ │ │ │ │ │ ├── update.ts │ │ │ │ │ │ ├── user-group-invites.ts │ │ │ │ │ │ └── webhooks │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── latest-version.ts │ │ │ │ │ ├── messaging │ │ │ │ │ │ ├── history.ts │ │ │ │ │ │ ├── messages.ts │ │ │ │ │ │ └── messages │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ │ └── read.ts │ │ │ │ │ ├── meta.ts │ │ │ │ │ ├── miauth │ │ │ │ │ │ └── gen-token.ts │ │ │ │ │ ├── mute │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ └── list.ts │ │ │ │ │ ├── my │ │ │ │ │ │ └── apps.ts │ │ │ │ │ ├── notes.ts │ │ │ │ │ ├── notes │ │ │ │ │ │ ├── ancestors.ts │ │ │ │ │ │ ├── children.ts │ │ │ │ │ │ ├── clips.ts │ │ │ │ │ │ ├── conversation.ts │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── edit.ts │ │ │ │ │ │ ├── favorites │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ └── delete.ts │ │ │ │ │ │ ├── featured.ts │ │ │ │ │ │ ├── global-timeline.ts │ │ │ │ │ │ ├── helpers │ │ │ │ │ │ │ └── timeline-enhacers.ts │ │ │ │ │ │ ├── hybrid-timeline.ts │ │ │ │ │ │ ├── local-timeline.ts │ │ │ │ │ │ ├── mentions.ts │ │ │ │ │ │ ├── polls │ │ │ │ │ │ │ ├── recommendation.ts │ │ │ │ │ │ │ └── vote.ts │ │ │ │ │ │ ├── reactions.ts │ │ │ │ │ │ ├── reactions │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ └── delete.ts │ │ │ │ │ │ ├── reblogtrail.ts │ │ │ │ │ │ ├── recommended-timeline.ts │ │ │ │ │ │ ├── renotes.ts │ │ │ │ │ │ ├── replies.ts │ │ │ │ │ │ ├── search-by-tag.ts │ │ │ │ │ │ ├── search.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── state.ts │ │ │ │ │ │ ├── thread-muting │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ └── delete.ts │ │ │ │ │ │ ├── timeline.ts │ │ │ │ │ │ ├── translate.ts │ │ │ │ │ │ ├── tumblr.ts │ │ │ │ │ │ ├── unrenote.ts │ │ │ │ │ │ ├── user-list-timeline.ts │ │ │ │ │ │ └── watching │ │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ │ └── delete.ts │ │ │ │ │ ├── notifications │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── mark-all-as-read.ts │ │ │ │ │ │ └── read.ts │ │ │ │ │ ├── page-push.ts │ │ │ │ │ ├── pages │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── featured.ts │ │ │ │ │ │ ├── like.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── unlike.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ ├── patrons.ts │ │ │ │ │ ├── ping.ts │ │ │ │ │ ├── pinned-users.ts │ │ │ │ │ ├── promo │ │ │ │ │ │ └── read.ts │ │ │ │ │ ├── recommended-instances.ts │ │ │ │ │ ├── release.ts │ │ │ │ │ ├── renote-mute │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ └── list.ts │ │ │ │ │ ├── request-reset-password.ts │ │ │ │ │ ├── reset-db.ts │ │ │ │ │ ├── reset-password.ts │ │ │ │ │ ├── server-info.ts │ │ │ │ │ ├── stats.ts │ │ │ │ │ ├── sw │ │ │ │ │ │ ├── register.ts │ │ │ │ │ │ ├── show-registration.ts │ │ │ │ │ │ ├── unregister.ts │ │ │ │ │ │ └── update-registration.ts │ │ │ │ │ ├── test.ts │ │ │ │ │ ├── username │ │ │ │ │ │ └── available.ts │ │ │ │ │ ├── users.ts │ │ │ │ │ └── users │ │ │ │ │ │ ├── clips.ts │ │ │ │ │ │ ├── followers.ts │ │ │ │ │ │ ├── following.ts │ │ │ │ │ │ ├── gallery │ │ │ │ │ │ └── posts.ts │ │ │ │ │ │ ├── get-frequently-replied-users.ts │ │ │ │ │ │ ├── groups │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── invitations │ │ │ │ │ │ │ ├── accept.ts │ │ │ │ │ │ │ └── reject.ts │ │ │ │ │ │ ├── invite.ts │ │ │ │ │ │ ├── joined.ts │ │ │ │ │ │ ├── leave.ts │ │ │ │ │ │ ├── owned.ts │ │ │ │ │ │ ├── pull.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── transfer.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ ├── lists │ │ │ │ │ │ ├── create.ts │ │ │ │ │ │ ├── delete-all.ts │ │ │ │ │ │ ├── delete.ts │ │ │ │ │ │ ├── list.ts │ │ │ │ │ │ ├── pull.ts │ │ │ │ │ │ ├── push.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ └── update.ts │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ ├── pages.ts │ │ │ │ │ │ ├── reactions.ts │ │ │ │ │ │ ├── recommendation.ts │ │ │ │ │ │ ├── relation.ts │ │ │ │ │ │ ├── report-abuse.ts │ │ │ │ │ │ ├── search-by-username-and-host.ts │ │ │ │ │ │ ├── search.ts │ │ │ │ │ │ ├── show.ts │ │ │ │ │ │ ├── stats.ts │ │ │ │ │ │ └── tumblr.ts │ │ │ │ ├── error.ts │ │ │ │ ├── index.ts │ │ │ │ ├── limiter.ts │ │ │ │ ├── logger.ts │ │ │ │ ├── mastodon │ │ │ │ │ ├── ApiMastodonCompatibleService.ts │ │ │ │ │ ├── converters.ts │ │ │ │ │ └── endpoints │ │ │ │ │ │ ├── account.ts │ │ │ │ │ │ ├── auth.ts │ │ │ │ │ │ ├── filter.ts │ │ │ │ │ │ ├── meta.ts │ │ │ │ │ │ ├── notifications.ts │ │ │ │ │ │ ├── search.ts │ │ │ │ │ │ ├── status.ts │ │ │ │ │ │ └── timeline.ts │ │ │ │ ├── openapi │ │ │ │ │ ├── errors.ts │ │ │ │ │ ├── gen-spec.ts │ │ │ │ │ └── schemas.ts │ │ │ │ ├── private │ │ │ │ │ ├── signin.ts │ │ │ │ │ ├── signup-pending.ts │ │ │ │ │ ├── signup.ts │ │ │ │ │ └── verify-email.ts │ │ │ │ ├── service │ │ │ │ │ ├── discord.ts │ │ │ │ │ ├── github.ts │ │ │ │ │ ├── tumblr.ts │ │ │ │ │ └── twitter.ts │ │ │ │ ├── stream │ │ │ │ │ ├── channel.ts │ │ │ │ │ ├── channels │ │ │ │ │ │ ├── admin.ts │ │ │ │ │ │ ├── antenna.ts │ │ │ │ │ │ ├── channel.ts │ │ │ │ │ │ ├── drive.ts │ │ │ │ │ │ ├── global-timeline.ts │ │ │ │ │ │ ├── hashtag.ts │ │ │ │ │ │ ├── home-timeline.ts │ │ │ │ │ │ ├── hybrid-timeline.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── local-timeline.ts │ │ │ │ │ │ ├── main.ts │ │ │ │ │ │ ├── messaging-index.ts │ │ │ │ │ │ ├── messaging.ts │ │ │ │ │ │ ├── queue-stats.ts │ │ │ │ │ │ ├── recommended-timeline.ts │ │ │ │ │ │ ├── server-stats.ts │ │ │ │ │ │ └── user-list.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ └── streaming.ts │ │ │ ├── file │ │ │ │ ├── assets │ │ │ │ │ ├── bad-egg.png │ │ │ │ │ ├── cache-expired.png │ │ │ │ │ ├── dummy.png │ │ │ │ │ ├── not-an-image.png │ │ │ │ │ ├── thumbnail-not-available.png │ │ │ │ │ └── tombstone.png │ │ │ │ ├── index.ts │ │ │ │ └── send-drive-file.ts │ │ │ ├── index.ts │ │ │ ├── nodeinfo.ts │ │ │ ├── proxy │ │ │ │ ├── index.ts │ │ │ │ └── proxy-media.ts │ │ │ ├── web │ │ │ │ ├── bios.css │ │ │ │ ├── bios.js │ │ │ │ ├── boot.js │ │ │ │ ├── cli.css │ │ │ │ ├── cli.js │ │ │ │ ├── feed.ts │ │ │ │ ├── index.ts │ │ │ │ ├── manifest.json │ │ │ │ ├── manifest.ts │ │ │ │ ├── style.css │ │ │ │ ├── url-preview.ts │ │ │ │ └── views │ │ │ │ │ ├── base.pug │ │ │ │ │ ├── bios.pug │ │ │ │ │ ├── channel.pug │ │ │ │ │ ├── cli.pug │ │ │ │ │ ├── clip.pug │ │ │ │ │ ├── flush.pug │ │ │ │ │ ├── gallery-post.pug │ │ │ │ │ ├── note.pug │ │ │ │ │ ├── page.pug │ │ │ │ │ └── user.pug │ │ │ └── well-known.ts │ │ ├── services │ │ │ ├── add-note-to-antenna.ts │ │ │ ├── blocking │ │ │ │ ├── create.ts │ │ │ │ └── delete.ts │ │ │ ├── chart │ │ │ │ ├── charts │ │ │ │ │ ├── active-users.ts │ │ │ │ │ ├── ap-request.ts │ │ │ │ │ ├── drive.ts │ │ │ │ │ ├── entities │ │ │ │ │ │ ├── active-users.ts │ │ │ │ │ │ ├── ap-request.ts │ │ │ │ │ │ ├── drive.ts │ │ │ │ │ │ ├── federation.ts │ │ │ │ │ │ ├── hashtag.ts │ │ │ │ │ │ ├── instance.ts │ │ │ │ │ │ ├── notes.ts │ │ │ │ │ │ ├── per-user-drive.ts │ │ │ │ │ │ ├── per-user-following.ts │ │ │ │ │ │ ├── per-user-notes.ts │ │ │ │ │ │ ├── per-user-reactions.ts │ │ │ │ │ │ ├── test-grouped.ts │ │ │ │ │ │ ├── test-intersection.ts │ │ │ │ │ │ ├── test-unique.ts │ │ │ │ │ │ ├── test.ts │ │ │ │ │ │ └── users.ts │ │ │ │ │ ├── federation.ts │ │ │ │ │ ├── hashtag.ts │ │ │ │ │ ├── instance.ts │ │ │ │ │ ├── notes.ts │ │ │ │ │ ├── per-user-drive.ts │ │ │ │ │ ├── per-user-following.ts │ │ │ │ │ ├── per-user-notes.ts │ │ │ │ │ ├── per-user-reactions.ts │ │ │ │ │ ├── test-grouped.ts │ │ │ │ │ ├── test-intersection.ts │ │ │ │ │ ├── test-unique.ts │ │ │ │ │ ├── test.ts │ │ │ │ │ └── users.ts │ │ │ │ ├── core.ts │ │ │ │ ├── entities.ts │ │ │ │ └── index.ts │ │ │ ├── create-notification.ts │ │ │ ├── create-system-user.ts │ │ │ ├── delete-account.ts │ │ │ ├── detect-sensitive.ts │ │ │ ├── drive │ │ │ │ ├── add-file.ts │ │ │ │ ├── delete-file.ts │ │ │ │ ├── generate-video-thumbnail.ts │ │ │ │ ├── image-processor.ts │ │ │ │ ├── internal-storage.ts │ │ │ │ ├── logger.ts │ │ │ │ ├── s3.ts │ │ │ │ └── upload-from-url.ts │ │ │ ├── fetch-instance-metadata.ts │ │ │ ├── fetch-rel-me.ts │ │ │ ├── following │ │ │ │ ├── create.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── reject.ts │ │ │ │ └── requests │ │ │ │ │ ├── accept-all.ts │ │ │ │ │ ├── accept.ts │ │ │ │ │ ├── cancel.ts │ │ │ │ │ └── create.ts │ │ │ ├── i │ │ │ │ ├── pin.ts │ │ │ │ └── update.ts │ │ │ ├── insert-moderation-log.ts │ │ │ ├── instance-actor.ts │ │ │ ├── logger.ts │ │ │ ├── messages │ │ │ │ ├── create.ts │ │ │ │ └── delete.ts │ │ │ ├── note │ │ │ │ ├── create.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── polls │ │ │ │ │ ├── update.ts │ │ │ │ │ └── vote.ts │ │ │ │ ├── reaction │ │ │ │ │ ├── create.ts │ │ │ │ │ └── delete.ts │ │ │ │ ├── read.ts │ │ │ │ ├── unread.ts │ │ │ │ ├── unwatch.ts │ │ │ │ └── watch.ts │ │ │ ├── push-notification.ts │ │ │ ├── register-or-fetch-instance-doc.ts │ │ │ ├── relay.ts │ │ │ ├── send-email-notification.ts │ │ │ ├── send-email.ts │ │ │ ├── stream.ts │ │ │ ├── suspend-user.ts │ │ │ ├── tumblr │ │ │ │ └── index.ts │ │ │ ├── unsuspend-user.ts │ │ │ ├── update-hashtag.ts │ │ │ ├── user-cache.ts │ │ │ ├── user-list │ │ │ │ └── push.ts │ │ │ └── validate-email-for-account.ts │ │ └── types.ts │ ├── test │ │ ├── activitypub.ts │ │ ├── ap-request.ts │ │ ├── api-visibility.ts │ │ ├── api.ts │ │ ├── block.ts │ │ ├── chart.ts │ │ ├── docker-compose.yml │ │ ├── e2e │ │ │ └── users.ts │ │ ├── endpoints.ts │ │ ├── extract-mentions.ts │ │ ├── fetch-resource.ts │ │ ├── ff-visibility.ts │ │ ├── get-file-info.ts │ │ ├── loader.js │ │ ├── mfm.ts │ │ ├── misc │ │ │ └── mock-resolver.ts │ │ ├── mute.ts │ │ ├── note.ts │ │ ├── prelude │ │ │ ├── maybe.ts │ │ │ └── url.ts │ │ ├── reaction-lib.ts │ │ ├── resources │ │ │ ├── 25000x25000.png │ │ │ ├── Lenna.jpg │ │ │ ├── Lenna.png │ │ │ ├── anime.gif │ │ │ ├── anime.png │ │ │ ├── emptyfile │ │ │ ├── image.svg │ │ │ ├── rotate.jpg │ │ │ ├── with-alpha.png │ │ │ └── with-xml-def.svg │ │ ├── streaming.ts │ │ ├── thread-mute.ts │ │ ├── tsconfig.json │ │ ├── user-notes.ts │ │ └── utils.ts │ └── tsconfig.json ├── client │ ├── .eslintrc.json │ ├── .prettierrc │ ├── .vscode │ │ └── settings.json │ ├── @types │ │ ├── global.d.ts │ │ ├── theme.d.ts │ │ └── vue.d.ts │ ├── assets │ │ ├── about-icon.png │ │ ├── caesar.svg │ │ ├── dagger.png │ │ ├── dagger2.png │ │ ├── dummy.png │ │ ├── dummy_original.png │ │ ├── label-red.svg │ │ ├── label.svg │ │ ├── misskey.png │ │ ├── misskey.svg │ │ ├── misskeya.svg │ │ ├── npf-bold.svg │ │ ├── npf-color.svg │ │ ├── npf-italic.svg │ │ ├── npf-link.svg │ │ ├── npf-read-more-alt.svg │ │ ├── npf-read-more.svg │ │ ├── npf-small.svg │ │ ├── npf-strikethrough.svg │ │ ├── posts-ask.svg │ │ ├── posts-audio-alt.svg │ │ ├── posts-audio.svg │ │ ├── posts-chat.svg │ │ ├── posts-link-alt.svg │ │ ├── posts-link.svg │ │ ├── posts-photo-alt.svg │ │ ├── posts-photo.svg │ │ ├── posts-poll.svg │ │ ├── posts-quote.svg │ │ ├── posts-text.svg │ │ ├── posts-video-alt.svg │ │ ├── posts-video.svg │ │ ├── reblog-compact.svg │ │ ├── reply-empty.svg │ │ ├── snowman.svg │ │ ├── tagcanvas.min.js │ │ ├── text-font-size.svg │ │ ├── text-indent.svg │ │ ├── text-list-ordered.svg │ │ ├── text-list-unordered.svg │ │ ├── text-lucille.svg │ │ ├── text-quote.svg │ │ ├── title-color.svg │ │ ├── title.svg │ │ └── tumblrFollow.gif │ ├── package.json │ ├── src │ │ ├── account.ts │ │ ├── components │ │ │ ├── ImageViewer │ │ │ │ └── index.vue │ │ │ ├── MkAbuseReport.vue │ │ │ ├── MkAbuseReportWindow.vue │ │ │ ├── MkAnalogClock.vue │ │ │ ├── MkAnnouncement.vue │ │ │ ├── MkAutocomplete.vue │ │ │ ├── MkAvatars.vue │ │ │ ├── MkBlockHashtagButton.vue │ │ │ ├── MkButton.vue │ │ │ ├── MkCaptcha.vue │ │ │ ├── MkChannelFollowButton.vue │ │ │ ├── MkChannelList.vue │ │ │ ├── MkChannelPreview.vue │ │ │ ├── MkChart.vue │ │ │ ├── MkChartTooltip.vue │ │ │ ├── MkChatPreview.vue │ │ │ ├── MkCheatSheetDialog.vue │ │ │ ├── MkCode.core.vue │ │ │ ├── MkCode.vue │ │ │ ├── MkContainer.vue │ │ │ ├── MkContextMenu.vue │ │ │ ├── MkCropperDialog.vue │ │ │ ├── MkCwButton.vue │ │ │ ├── MkDateSeparatedList.vue │ │ │ ├── MkDialog.vue │ │ │ ├── MkDigitalClock.vue │ │ │ ├── MkDrive.file.vue │ │ │ ├── MkDrive.folder.vue │ │ │ ├── MkDrive.navFolder.vue │ │ │ ├── MkDrive.vue │ │ │ ├── MkDriveFileThumbnail.vue │ │ │ ├── MkDriveSelectDialog.vue │ │ │ ├── MkDriveWindow.vue │ │ │ ├── MkEmojiPicker.section.vue │ │ │ ├── MkEmojiPicker.vue │ │ │ ├── MkEmojiPickerDialog.vue │ │ │ ├── MkFeaturedPhotos.vue │ │ │ ├── MkFileListForAdmin.vue │ │ │ ├── MkFileTypeIcon.vue │ │ │ ├── MkFolder.vue │ │ │ ├── MkFollowButton.vue │ │ │ ├── MkFollowHashtagButton.vue │ │ │ ├── MkForgotPassword.vue │ │ │ ├── MkFormDialog.vue │ │ │ ├── MkFormula.vue │ │ │ ├── MkFormulaCore.vue │ │ │ ├── MkGalleryPostPreview.vue │ │ │ ├── MkGoogle.vue │ │ │ ├── MkHashtagSummary.vue │ │ │ ├── MkHeatmap.vue │ │ │ ├── MkImageViewer.vue │ │ │ ├── MkImgWithBlurhash.vue │ │ │ ├── MkInfo.vue │ │ │ ├── MkInstanceCardMini.vue │ │ │ ├── MkInstanceSelectDialog.vue │ │ │ ├── MkInstanceStats.vue │ │ │ ├── MkInstanceTicker.vue │ │ │ ├── MkKeyValue.vue │ │ │ ├── MkLaunchPad.vue │ │ │ ├── MkLink.vue │ │ │ ├── MkManyAnnouncements.vue │ │ │ ├── MkMarquee.vue │ │ │ ├── MkMedia.vue │ │ │ ├── MkMediaBanner.vue │ │ │ ├── MkMediaCaption.vue │ │ │ ├── MkMediaList.vue │ │ │ ├── MkMention.vue │ │ │ ├── MkMenu.child.vue │ │ │ ├── MkMenu.vue │ │ │ ├── MkMiniChart.vue │ │ │ ├── MkModal.vue │ │ │ ├── MkModalPageWindow.vue │ │ │ ├── MkModalWindow.vue │ │ │ ├── MkMoved.vue │ │ │ ├── MkNote.vue │ │ │ ├── MkNoteDetailed.vue │ │ │ ├── MkNoteHeader.vue │ │ │ ├── MkNotePreview.vue │ │ │ ├── MkNoteSimple.vue │ │ │ ├── MkNoteSub.vue │ │ │ ├── MkNotes.vue │ │ │ ├── MkNotification.vue │ │ │ ├── MkNotificationSettingWindow.vue │ │ │ ├── MkNotificationToast.vue │ │ │ ├── MkNotifications.vue │ │ │ ├── MkNumber.vue │ │ │ ├── MkNumberDiff.vue │ │ │ ├── MkObjectView.value.vue │ │ │ ├── MkObjectView.vue │ │ │ ├── MkPagePreview.vue │ │ │ ├── MkPageWindow.vue │ │ │ ├── MkPagination.vue │ │ │ ├── MkPoll.vue │ │ │ ├── MkPollEditor.vue │ │ │ ├── MkPopupMenu.vue │ │ │ ├── MkPostForm.vue │ │ │ ├── MkPostFormAttaches.vue │ │ │ ├── MkPostFormDialog.vue │ │ │ ├── MkPushNotificationAllowButton.vue │ │ │ ├── MkQuoteButton.vue │ │ │ ├── MkReactedUsers.vue │ │ │ ├── MkReactionIcon.vue │ │ │ ├── MkReactionTooltip.vue │ │ │ ├── MkReactionsViewer.details.vue │ │ │ ├── MkReactionsViewer.reaction.vue │ │ │ ├── MkReactionsViewer.vue │ │ │ ├── MkRemoteCaution.vue │ │ │ ├── MkRenoteButton.vue │ │ │ ├── MkRipple.vue │ │ │ ├── MkShowMoreButton.vue │ │ │ ├── MkSignin.vue │ │ │ ├── MkSigninDialog.vue │ │ │ ├── MkSignup.vue │ │ │ ├── MkSignupDialog.vue │ │ │ ├── MkSparkle.vue │ │ │ ├── MkStarButton.vue │ │ │ ├── MkStarButtonNoEmoji.vue │ │ │ ├── MkSuperMenu.vue │ │ │ ├── MkTab.vue │ │ │ ├── MkTagCloud.vue │ │ │ ├── MkTimeline.vue │ │ │ ├── MkToast.vue │ │ │ ├── MkTokenGenerateWindow.vue │ │ │ ├── MkTooltip.vue │ │ │ ├── MkTutorialDialog.vue │ │ │ ├── MkUpdated.vue │ │ │ ├── MkUrlPreview.vue │ │ │ ├── MkUrlPreviewPopup.vue │ │ │ ├── MkUserCardMini.vue │ │ │ ├── MkUserInfo.vue │ │ │ ├── MkUserList.vue │ │ │ ├── MkUserOnlineIndicator.vue │ │ │ ├── MkUserPreview.vue │ │ │ ├── MkUserSelectDialog.vue │ │ │ ├── MkUserSelectLocalDialog.vue │ │ │ ├── MkUsersTooltip.vue │ │ │ ├── MkVisibility.vue │ │ │ ├── MkVisibilityPicker.vue │ │ │ ├── MkWaitingDialog.vue │ │ │ ├── MkWidgets.vue │ │ │ ├── MkWindow.vue │ │ │ ├── editor │ │ │ │ ├── big.ts │ │ │ │ ├── color-gradient.ts │ │ │ │ ├── color-menu.vue │ │ │ │ ├── iframe-module.ts │ │ │ │ ├── image.js │ │ │ │ ├── image.vue │ │ │ │ ├── index.vue │ │ │ │ └── reply.vue │ │ │ ├── form │ │ │ │ ├── checkbox.vue │ │ │ │ ├── folder.vue │ │ │ │ ├── input.vue │ │ │ │ ├── link.vue │ │ │ │ ├── radio.vue │ │ │ │ ├── radios.vue │ │ │ │ ├── range.vue │ │ │ │ ├── section.vue │ │ │ │ ├── select.vue │ │ │ │ ├── slot.vue │ │ │ │ ├── split.vue │ │ │ │ ├── suspense.vue │ │ │ │ ├── switch.vue │ │ │ │ └── textarea.vue │ │ │ ├── global │ │ │ │ ├── MkA.vue │ │ │ │ ├── MkAcct.vue │ │ │ │ ├── MkAd.vue │ │ │ │ ├── MkAvatar.vue │ │ │ │ ├── MkEllipsis.vue │ │ │ │ ├── MkEmoji.vue │ │ │ │ ├── MkError.vue │ │ │ │ ├── MkLoading.vue │ │ │ │ ├── MkMisskeyFlavoredMarkdown.vue │ │ │ │ ├── MkPageHeader.vue │ │ │ │ ├── MkSpacer.vue │ │ │ │ ├── MkStickyContainer.vue │ │ │ │ ├── MkTime.vue │ │ │ │ ├── MkUrl.vue │ │ │ │ ├── MkUserName.vue │ │ │ │ ├── RouterView.vue │ │ │ │ └── i18n.ts │ │ │ ├── icons │ │ │ │ ├── bold.vue │ │ │ │ ├── bullet-list.vue │ │ │ │ ├── caesar.vue │ │ │ │ ├── caret.vue │ │ │ │ ├── color.vue │ │ │ │ ├── italic.vue │ │ │ │ ├── link.vue │ │ │ │ ├── logo.image.vue │ │ │ │ ├── logo.vue │ │ │ │ ├── ordered-list.vue │ │ │ │ ├── photo.vue │ │ │ │ ├── quote.vue │ │ │ │ ├── reblog.vue │ │ │ │ ├── small.vue │ │ │ │ ├── strike.vue │ │ │ │ ├── video.vue │ │ │ │ └── warning.vue │ │ │ ├── index.ts │ │ │ ├── mfm.ts │ │ │ ├── note │ │ │ │ ├── Header.vue │ │ │ │ ├── NoteContent.vue │ │ │ │ ├── NoteImage.vue │ │ │ │ ├── Pfp.vue │ │ │ │ ├── ReblogItem.vue │ │ │ │ ├── Reblogtrail.vue │ │ │ │ └── ReplyView.vue │ │ │ └── page │ │ │ │ ├── page.block.vue │ │ │ │ ├── page.button.vue │ │ │ │ ├── page.canvas.vue │ │ │ │ ├── page.counter.vue │ │ │ │ ├── page.if.vue │ │ │ │ ├── page.image.vue │ │ │ │ ├── page.note.vue │ │ │ │ ├── page.number-input.vue │ │ │ │ ├── page.post.vue │ │ │ │ ├── page.radio-button.vue │ │ │ │ ├── page.section.vue │ │ │ │ ├── page.switch.vue │ │ │ │ ├── page.text-input.vue │ │ │ │ ├── page.text.vue │ │ │ │ ├── page.textarea-input.vue │ │ │ │ ├── page.textarea.vue │ │ │ │ └── page.vue │ │ ├── config.ts │ │ ├── const.ts │ │ ├── directives │ │ │ ├── adaptive-border.ts │ │ │ ├── anim.ts │ │ │ ├── appear.ts │ │ │ ├── click-anime.ts │ │ │ ├── focus.ts │ │ │ ├── follow-append.ts │ │ │ ├── get-size.ts │ │ │ ├── hotkey.ts │ │ │ ├── index.ts │ │ │ ├── panel.ts │ │ │ ├── ripple.ts │ │ │ ├── size.ts │ │ │ ├── tooltip.ts │ │ │ └── user-preview.ts │ │ ├── events.ts │ │ ├── filters.ts │ │ ├── filters │ │ │ ├── bytes.ts │ │ │ ├── note.ts │ │ │ ├── number.ts │ │ │ └── user.ts │ │ ├── helpers │ │ │ ├── features │ │ │ │ └── index.ts │ │ │ └── note │ │ │ │ ├── note-content.ts │ │ │ │ └── parent.ts │ │ ├── i18n.ts │ │ ├── init.ts │ │ ├── instance.ts │ │ ├── navbar.ts │ │ ├── nirax.ts │ │ ├── os.ts │ │ ├── pages │ │ │ ├── _empty_.vue │ │ │ ├── _error_.vue │ │ │ ├── _loading_.vue │ │ │ ├── about.emojis.vue │ │ │ ├── about.federation.vue │ │ │ ├── about.vue │ │ │ ├── admin-file.vue │ │ │ ├── admin │ │ │ │ ├── _header_.vue │ │ │ │ ├── abuses.vue │ │ │ │ ├── announcements.vue │ │ │ │ ├── bot-protection.vue │ │ │ │ ├── custom-css.vue │ │ │ │ ├── database.vue │ │ │ │ ├── email-settings.vue │ │ │ │ ├── emoji-edit-dialog.vue │ │ │ │ ├── emojis.vue │ │ │ │ ├── experiments.vue │ │ │ │ ├── federation.vue │ │ │ │ ├── files.vue │ │ │ │ ├── hashtags.vue │ │ │ │ ├── index.vue │ │ │ │ ├── instance-block.vue │ │ │ │ ├── integrations.discord.vue │ │ │ │ ├── integrations.github.vue │ │ │ │ ├── integrations.vue │ │ │ │ ├── object-storage.vue │ │ │ │ ├── other-settings.vue │ │ │ │ ├── overview.active-users.vue │ │ │ │ ├── overview.ap-requests.vue │ │ │ │ ├── overview.federation.vue │ │ │ │ ├── overview.heatmap.vue │ │ │ │ ├── overview.instances.vue │ │ │ │ ├── overview.metrics.vue │ │ │ │ ├── overview.moderators.vue │ │ │ │ ├── overview.pie.vue │ │ │ │ ├── overview.queue-chart.vue │ │ │ │ ├── overview.queue.chart.vue │ │ │ │ ├── overview.queue.vue │ │ │ │ ├── overview.stats.vue │ │ │ │ ├── overview.user.vue │ │ │ │ ├── overview.users.vue │ │ │ │ ├── overview.vue │ │ │ │ ├── promotions.vue │ │ │ │ ├── proxy-account.vue │ │ │ │ ├── queue.chart.chart.vue │ │ │ │ ├── queue.chart.vue │ │ │ │ ├── queue.vue │ │ │ │ ├── relays.vue │ │ │ │ ├── security.vue │ │ │ │ ├── settings.vue │ │ │ │ └── users.vue │ │ │ ├── announcements.vue │ │ │ ├── antenna-timeline.vue │ │ │ ├── api-console.vue │ │ │ ├── auth.form.vue │ │ │ ├── auth.vue │ │ │ ├── channel-editor.vue │ │ │ ├── channel.vue │ │ │ ├── channels.vue │ │ │ ├── clip.vue │ │ │ ├── drive.vue │ │ │ ├── emojis.emoji.vue │ │ │ ├── explore.featured.vue │ │ │ ├── explore.users.vue │ │ │ ├── explore.vue │ │ │ ├── favorites.vue │ │ │ ├── follow-requests.vue │ │ │ ├── follow.vue │ │ │ ├── gallery │ │ │ │ ├── edit.vue │ │ │ │ ├── index.vue │ │ │ │ └── post.vue │ │ │ ├── hashtags.vue │ │ │ ├── instance-info.vue │ │ │ ├── landing │ │ │ │ ├── featured.vue │ │ │ │ └── index.vue │ │ │ ├── messaging │ │ │ │ ├── index.vue │ │ │ │ ├── messaging-room.form.vue │ │ │ │ ├── messaging-room.message.vue │ │ │ │ └── messaging-room.vue │ │ │ ├── mfm-cheat-sheet.vue │ │ │ ├── miauth.vue │ │ │ ├── my-antennas │ │ │ │ ├── create.vue │ │ │ │ ├── edit.vue │ │ │ │ ├── editor.vue │ │ │ │ └── index.vue │ │ │ ├── my-clips │ │ │ │ └── index.vue │ │ │ ├── my-groups │ │ │ │ ├── group.vue │ │ │ │ └── index.vue │ │ │ ├── my-lists │ │ │ │ ├── index.vue │ │ │ │ └── list.vue │ │ │ ├── no-graze.vue │ │ │ ├── not-found.vue │ │ │ ├── note.vue │ │ │ ├── note │ │ │ │ └── bySlug.vue │ │ │ ├── notifications.vue │ │ │ ├── page-editor │ │ │ │ ├── els │ │ │ │ │ ├── page-editor.el.button.vue │ │ │ │ │ ├── page-editor.el.canvas.vue │ │ │ │ │ ├── page-editor.el.counter.vue │ │ │ │ │ ├── page-editor.el.if.vue │ │ │ │ │ ├── page-editor.el.image.vue │ │ │ │ │ ├── page-editor.el.note.vue │ │ │ │ │ ├── page-editor.el.number-input.vue │ │ │ │ │ ├── page-editor.el.post.vue │ │ │ │ │ ├── page-editor.el.radio-button.vue │ │ │ │ │ ├── page-editor.el.section.vue │ │ │ │ │ ├── page-editor.el.switch.vue │ │ │ │ │ ├── page-editor.el.text-input.vue │ │ │ │ │ ├── page-editor.el.text.vue │ │ │ │ │ ├── page-editor.el.textarea-input.vue │ │ │ │ │ └── page-editor.el.textarea.vue │ │ │ │ ├── page-editor.blocks.vue │ │ │ │ ├── page-editor.container.vue │ │ │ │ ├── page-editor.script-block.vue │ │ │ │ └── page-editor.vue │ │ │ ├── page.vue │ │ │ ├── pages.vue │ │ │ ├── preview.vue │ │ │ ├── registry.keys.vue │ │ │ ├── registry.value.vue │ │ │ ├── registry.vue │ │ │ ├── reset-password.vue │ │ │ ├── scratchpad.vue │ │ │ ├── search.vue │ │ │ ├── settings │ │ │ │ ├── 2fa.qrdialog.vue │ │ │ │ ├── 2fa.vue │ │ │ │ ├── account-info.vue │ │ │ │ ├── accounts.vue │ │ │ │ ├── api.vue │ │ │ │ ├── apps.vue │ │ │ │ ├── custom-css.vue │ │ │ │ ├── custom-katex-macro.vue │ │ │ │ ├── deck.vue │ │ │ │ ├── delete-account.vue │ │ │ │ ├── drive.vue │ │ │ │ ├── email.vue │ │ │ │ ├── general.vue │ │ │ │ ├── import-export.vue │ │ │ │ ├── index.vue │ │ │ │ ├── instance-mute.vue │ │ │ │ ├── integration.vue │ │ │ │ ├── migration.vue │ │ │ │ ├── mute-block.vue │ │ │ │ ├── navbar.vue │ │ │ │ ├── notifications.vue │ │ │ │ ├── other.vue │ │ │ │ ├── preferences-backups.vue │ │ │ │ ├── privacy.vue │ │ │ │ ├── profile.vue │ │ │ │ ├── reaction.vue │ │ │ │ ├── security.vue │ │ │ │ ├── sounds.vue │ │ │ │ ├── statusbar.vue │ │ │ │ ├── theme.install.vue │ │ │ │ ├── theme.manage.vue │ │ │ │ ├── theme.vue │ │ │ │ ├── webhook.edit.vue │ │ │ │ ├── webhook.new.vue │ │ │ │ ├── webhook.vue │ │ │ │ └── word-mute.vue │ │ │ ├── share.vue │ │ │ ├── signup-complete.vue │ │ │ ├── tag.vue │ │ │ ├── theme-editor.vue │ │ │ ├── timeline.vue │ │ │ ├── user-info.vue │ │ │ ├── user-list-timeline.vue │ │ │ ├── user │ │ │ │ ├── clips.vue │ │ │ │ ├── follow-list.vue │ │ │ │ ├── followers.vue │ │ │ │ ├── following.vue │ │ │ │ ├── gallery.vue │ │ │ │ ├── home.vue │ │ │ │ ├── index.activity.vue │ │ │ │ ├── index.photos.vue │ │ │ │ ├── index.timeline.vue │ │ │ │ ├── index.vue │ │ │ │ ├── pages.vue │ │ │ │ └── reactions.vue │ │ │ ├── verify-email.vue │ │ │ ├── welcome.entrance.a.vue │ │ │ ├── welcome.entrance.b.vue │ │ │ ├── welcome.entrance.c.vue │ │ │ ├── welcome.setup.vue │ │ │ ├── welcome.timeline.vue │ │ │ └── welcome.vue │ │ ├── pizzax.ts │ │ ├── router.ts │ │ ├── scripts │ │ │ ├── 2fa.ts │ │ │ ├── aiscript │ │ │ │ └── api.ts │ │ │ ├── array.ts │ │ │ ├── autocomplete.ts │ │ │ ├── chart-vline.ts │ │ │ ├── check-word-mute.ts │ │ │ ├── clone.ts │ │ │ ├── collect-page-vars.ts │ │ │ ├── color.ts │ │ │ ├── contains.ts │ │ │ ├── copy-to-clipboard.ts │ │ │ ├── device-kind.ts │ │ │ ├── emojilist.ts │ │ │ ├── extract-avg-color-from-blurhash.ts │ │ │ ├── extract-mentions.ts │ │ │ ├── extract-mfm.ts │ │ │ ├── extract-url-from-mfm.ts │ │ │ ├── focus.ts │ │ │ ├── form.ts │ │ │ ├── format-time-string.ts │ │ │ ├── gen-search-query.ts │ │ │ ├── get-account-from-id.ts │ │ │ ├── get-note-menu.ts │ │ │ ├── get-note-summary.ts │ │ │ ├── get-static-image-url.ts │ │ │ ├── get-user-menu.ts │ │ │ ├── get-user-name.ts │ │ │ ├── helpMenu.ts │ │ │ ├── hotkey.ts │ │ │ ├── hpml │ │ │ │ ├── block.ts │ │ │ │ ├── evaluator.ts │ │ │ │ ├── expr.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lib.ts │ │ │ │ └── type-checker.ts │ │ │ ├── i18n.ts │ │ │ ├── idb-proxy.ts │ │ │ ├── index-posts.ts │ │ │ ├── init-chart.ts │ │ │ ├── initialize-sw.ts │ │ │ ├── intl-const.ts │ │ │ ├── is-device-darkmode.ts │ │ │ ├── katex-macro.ts │ │ │ ├── keycode.ts │ │ │ ├── langmap.ts │ │ │ ├── login-id.ts │ │ │ ├── lookup-file.ts │ │ │ ├── lookup-instance.ts │ │ │ ├── lookup-user.ts │ │ │ ├── media-proxy.ts │ │ │ ├── mfm-tags.ts │ │ │ ├── page-metadata.ts │ │ │ ├── physics.ts │ │ │ ├── please-login.ts │ │ │ ├── popout.ts │ │ │ ├── popup-position.ts │ │ │ ├── preprocess.ts │ │ │ ├── reaction-picker.ts │ │ │ ├── reduced-motion.ts │ │ │ ├── safe-uri-decode.ts │ │ │ ├── scroll.ts │ │ │ ├── search.ts │ │ │ ├── select-file.ts │ │ │ ├── share-available.ts │ │ │ ├── shuffle.ts │ │ │ ├── sound.ts │ │ │ ├── theme-editor.ts │ │ │ ├── theme.ts │ │ │ ├── time.ts │ │ │ ├── timezones.ts │ │ │ ├── touch.ts │ │ │ ├── twemoji-base.ts │ │ │ ├── unison-reload.ts │ │ │ ├── upload.ts │ │ │ ├── url.ts │ │ │ ├── use-chart-tooltip.ts │ │ │ ├── use-interval.ts │ │ │ ├── use-leave-guard.ts │ │ │ ├── use-note-capture.ts │ │ │ └── use-tooltip.ts │ │ ├── special-events │ │ │ ├── ides │ │ │ │ ├── config.js │ │ │ │ └── index.vue │ │ │ └── index.vue │ │ ├── store.ts │ │ ├── stream.ts │ │ ├── style.scss │ │ ├── theme-store.ts │ │ ├── themes │ │ │ ├── _dark.json5 │ │ │ ├── _light.json5 │ │ │ ├── d-astro.json5 │ │ │ ├── d-botanical.json5 │ │ │ ├── d-catppuccin-frappe.json5 │ │ │ ├── d-catppuccin-mocha.json5 │ │ │ ├── d-cherry.json5 │ │ │ ├── d-dark.json5 │ │ │ ├── d-future.json5 │ │ │ ├── d-goblin.json5 │ │ │ ├── d-green-lime.json5 │ │ │ ├── d-green-orange.json5 │ │ │ ├── d-gruvbox.json5 │ │ │ ├── d-ice.json5 │ │ │ ├── d-nord.json5 │ │ │ ├── d-persimmon.json5 │ │ │ ├── d-rosepine.json5 │ │ │ ├── d-rosepinemoon.json5 │ │ │ ├── d-u0.json5 │ │ │ ├── l-apricot.json5 │ │ │ ├── l-catppuccin-latte.json5 │ │ │ ├── l-cherry.json5 │ │ │ ├── l-coffee.json5 │ │ │ ├── l-goblin.json5 │ │ │ ├── l-gruvbox.json5 │ │ │ ├── l-light.json5 │ │ │ ├── l-nord.json5 │ │ │ ├── l-rainy.json5 │ │ │ ├── l-rosepinedawn.json5 │ │ │ ├── l-sushi.json5 │ │ │ ├── l-u0.json5 │ │ │ └── l-vivid.json5 │ │ ├── types │ │ │ └── menu.ts │ │ ├── ui │ │ │ ├── _common_ │ │ │ │ ├── common.vue │ │ │ │ ├── navbar-for-mobile.vue │ │ │ │ ├── navbar.vue │ │ │ │ ├── statusbar-federation.vue │ │ │ │ ├── statusbar-rss.vue │ │ │ │ ├── statusbar-user-list.vue │ │ │ │ ├── stream-indicator.vue │ │ │ │ ├── sw-inject.ts │ │ │ │ └── upload.vue │ │ │ ├── deck.vue │ │ │ ├── deck │ │ │ │ ├── antenna-column.vue │ │ │ │ ├── channel-column.vue │ │ │ │ ├── column-core.vue │ │ │ │ ├── column.vue │ │ │ │ ├── deck-store.ts │ │ │ │ ├── direct-column.vue │ │ │ │ ├── list-column.vue │ │ │ │ ├── main-column.vue │ │ │ │ ├── mentions-column.vue │ │ │ │ ├── notifications-column.vue │ │ │ │ ├── tl-column.vue │ │ │ │ └── widgets-column.vue │ │ │ ├── universal.vue │ │ │ ├── universal.widgets.vue │ │ │ ├── visitor.vue │ │ │ ├── visitor │ │ │ │ ├── a.vue │ │ │ │ ├── b.vue │ │ │ │ ├── header.vue │ │ │ │ ├── kanban.vue │ │ │ │ └── login.vue │ │ │ └── zen.vue │ │ └── widgets │ │ │ ├── activity.calendar.vue │ │ │ ├── activity.chart.vue │ │ │ ├── activity.vue │ │ │ ├── aiscript.vue │ │ │ ├── button.vue │ │ │ ├── calendar.vue │ │ │ ├── clock.vue │ │ │ ├── digital-clock.vue │ │ │ ├── federation.vue │ │ │ ├── index.ts │ │ │ ├── instance-cloud.vue │ │ │ ├── job-queue.vue │ │ │ ├── memo.vue │ │ │ ├── notifications.vue │ │ │ ├── online-users.vue │ │ │ ├── photos.vue │ │ │ ├── post-form.vue │ │ │ ├── server-info.vue │ │ │ ├── server-metric │ │ │ ├── cpu-mem.vue │ │ │ ├── cpu.vue │ │ │ ├── disk.vue │ │ │ ├── index.vue │ │ │ ├── meilisearch.vue │ │ │ ├── mem.vue │ │ │ ├── net.vue │ │ │ └── pie.vue │ │ │ ├── slideshow.vue │ │ │ ├── timeline.vue │ │ │ ├── trends.vue │ │ │ ├── unix-clock.vue │ │ │ ├── user-list.vue │ │ │ └── widget.ts │ ├── tsconfig.json │ ├── vite.config.ts │ └── vite.json5.ts ├── firefish-js │ ├── .editorconfig │ ├── .gitignore │ ├── .swcrc │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── api-extractor.json │ ├── codecov.yml │ ├── etc │ │ ├── firefish-js.api.json │ │ ├── firefish-js.api.md │ │ └── misskey-js.api.md │ ├── jest.config.ts │ ├── markdown │ │ ├── firefish-js.acct.md │ │ ├── firefish-js.api.apiclient._constructor_.md │ │ ├── firefish-js.api.apiclient.credential.md │ │ ├── firefish-js.api.apiclient.fetch.md │ │ ├── firefish-js.api.apiclient.md │ │ ├── firefish-js.api.apiclient.origin.md │ │ ├── firefish-js.api.apiclient.request.md │ │ ├── firefish-js.api.apierror.md │ │ ├── firefish-js.api.fetchlike.md │ │ ├── firefish-js.api.isapierror.md │ │ ├── firefish-js.api.md │ │ ├── firefish-js.channelconnection._constructor_.md │ │ ├── firefish-js.channelconnection.channel.md │ │ ├── firefish-js.channelconnection.dispose.md │ │ ├── firefish-js.channelconnection.id.md │ │ ├── firefish-js.channelconnection.incount.md │ │ ├── firefish-js.channelconnection.md │ │ ├── firefish-js.channelconnection.name.md │ │ ├── firefish-js.channelconnection.outcount.md │ │ ├── firefish-js.channelconnection.send.md │ │ ├── firefish-js.channelconnection.stream.md │ │ ├── firefish-js.channels.md │ │ ├── firefish-js.endpoints.md │ │ ├── firefish-js.entities.ad.md │ │ ├── firefish-js.entities.announcement.md │ │ ├── firefish-js.entities.antenna.md │ │ ├── firefish-js.entities.app.md │ │ ├── firefish-js.entities.authsession.md │ │ ├── firefish-js.entities.blocking.md │ │ ├── firefish-js.entities.channel.md │ │ ├── firefish-js.entities.clip.md │ │ ├── firefish-js.entities.customemoji.md │ │ ├── firefish-js.entities.datestring.md │ │ ├── firefish-js.entities.detailedinstancemetadata.md │ │ ├── firefish-js.entities.drivefile.md │ │ ├── firefish-js.entities.drivefolder.md │ │ ├── firefish-js.entities.following.md │ │ ├── firefish-js.entities.followingfolloweepopulated.md │ │ ├── firefish-js.entities.followingfollowerpopulated.md │ │ ├── firefish-js.entities.followrequest.md │ │ ├── firefish-js.entities.gallerypost.md │ │ ├── firefish-js.entities.id.md │ │ ├── firefish-js.entities.instance.md │ │ ├── firefish-js.entities.instancemetadata.md │ │ ├── firefish-js.entities.liteinstancemetadata.md │ │ ├── firefish-js.entities.md │ │ ├── firefish-js.entities.medetailed.md │ │ ├── firefish-js.entities.messagingmessage.md │ │ ├── firefish-js.entities.note.md │ │ ├── firefish-js.entities.notefavorite.md │ │ ├── firefish-js.entities.notereaction.md │ │ ├── firefish-js.entities.notification.md │ │ ├── firefish-js.entities.origintype.md │ │ ├── firefish-js.entities.page.md │ │ ├── firefish-js.entities.pageevent.md │ │ ├── firefish-js.entities.serverinfo.md │ │ ├── firefish-js.entities.signin.md │ │ ├── firefish-js.entities.stats.md │ │ ├── firefish-js.entities.user.md │ │ ├── firefish-js.entities.userdetailed.md │ │ ├── firefish-js.entities.usergroup.md │ │ ├── firefish-js.entities.userlist.md │ │ ├── firefish-js.entities.userlite.md │ │ ├── firefish-js.entities.usersorting.md │ │ ├── firefish-js.ffvisibility.md │ │ ├── firefish-js.md │ │ ├── firefish-js.mutednotereasons.md │ │ ├── firefish-js.notevisibilities.md │ │ ├── firefish-js.notificationtypes.md │ │ ├── firefish-js.permissions.md │ │ ├── firefish-js.stream._constructor_.md │ │ ├── firefish-js.stream.close.md │ │ ├── firefish-js.stream.disconnecttochannel.md │ │ ├── firefish-js.stream.md │ │ ├── firefish-js.stream.removesharedconnection.md │ │ ├── firefish-js.stream.removesharedconnectionpool.md │ │ ├── firefish-js.stream.send.md │ │ ├── firefish-js.stream.state.md │ │ ├── firefish-js.stream.usechannel.md │ │ └── index.md │ ├── package.json │ ├── src │ │ ├── acct.ts │ │ ├── api.ts │ │ ├── api.types.ts │ │ ├── consts.ts │ │ ├── entities.ts │ │ ├── index.ts │ │ ├── streaming.ts │ │ └── streaming.types.ts │ ├── test-d │ │ ├── api.ts │ │ └── streaming.ts │ ├── test │ │ ├── api.ts │ │ └── streaming.ts │ └── tsconfig.json ├── megalodon │ ├── package.json │ ├── src │ │ ├── axios.d.ts │ │ ├── cancel.ts │ │ ├── converter.ts │ │ ├── default.ts │ │ ├── entities │ │ │ ├── account.ts │ │ │ ├── activity.ts │ │ │ ├── announcement.ts │ │ │ ├── application.ts │ │ │ ├── async_attachment.ts │ │ │ ├── attachment.ts │ │ │ ├── card.ts │ │ │ ├── context.ts │ │ │ ├── conversation.ts │ │ │ ├── emoji.ts │ │ │ ├── featured_tag.ts │ │ │ ├── field.ts │ │ │ ├── filter.ts │ │ │ ├── history.ts │ │ │ ├── identity_proof.ts │ │ │ ├── instance.ts │ │ │ ├── list.ts │ │ │ ├── marker.ts │ │ │ ├── mention.ts │ │ │ ├── notification.ts │ │ │ ├── poll.ts │ │ │ ├── poll_option.ts │ │ │ ├── preferences.ts │ │ │ ├── push_subscription.ts │ │ │ ├── reaction.ts │ │ │ ├── relationship.ts │ │ │ ├── report.ts │ │ │ ├── results.ts │ │ │ ├── scheduled_status.ts │ │ │ ├── source.ts │ │ │ ├── stats.ts │ │ │ ├── status.ts │ │ │ ├── status_edit.ts │ │ │ ├── status_params.ts │ │ │ ├── tag.ts │ │ │ ├── token.ts │ │ │ └── urls.ts │ │ ├── entity.ts │ │ ├── filter_context.ts │ │ ├── index.ts │ │ ├── megalodon.ts │ │ ├── misskey.ts │ │ ├── misskey │ │ │ ├── api_client.ts │ │ │ ├── entities │ │ │ │ ├── GetAll.ts │ │ │ │ ├── announcement.ts │ │ │ │ ├── app.ts │ │ │ │ ├── blocking.ts │ │ │ │ ├── createdNote.ts │ │ │ │ ├── emoji.ts │ │ │ │ ├── favorite.ts │ │ │ │ ├── field.ts │ │ │ │ ├── file.ts │ │ │ │ ├── followRequest.ts │ │ │ │ ├── follower.ts │ │ │ │ ├── following.ts │ │ │ │ ├── hashtag.ts │ │ │ │ ├── list.ts │ │ │ │ ├── meta.ts │ │ │ │ ├── mute.ts │ │ │ │ ├── note.ts │ │ │ │ ├── notification.ts │ │ │ │ ├── poll.ts │ │ │ │ ├── reaction.ts │ │ │ │ ├── relation.ts │ │ │ │ ├── session.ts │ │ │ │ ├── state.ts │ │ │ │ ├── stats.ts │ │ │ │ ├── user.ts │ │ │ │ ├── userDetail.ts │ │ │ │ ├── userDetailMe.ts │ │ │ │ └── userkey.ts │ │ │ ├── entity.ts │ │ │ ├── notification.ts │ │ │ └── web_socket.ts │ │ ├── notification.ts │ │ ├── oauth.ts │ │ ├── parser.ts │ │ ├── proxy_config.ts │ │ └── response.ts │ ├── test │ │ ├── integration │ │ │ ├── megalodon.spec.ts │ │ │ └── misskey.spec.ts │ │ └── unit │ │ │ ├── misskey │ │ │ └── api_client.spec.ts │ │ │ └── parser.spec.ts │ └── tsconfig.json ├── meta.json └── sw │ ├── .swcrc │ ├── package.json │ ├── src │ ├── @types │ │ └── global.d.ts │ ├── scripts │ │ ├── create-notification.ts │ │ ├── get-account-from-id.ts │ │ ├── get-user-name.ts │ │ ├── i18n.ts │ │ ├── lang.ts │ │ ├── login-id.ts │ │ ├── notification-read.ts │ │ ├── operations.ts │ │ └── twemoji-base.ts │ ├── sw.ts │ └── types.ts │ ├── tsconfig.json │ └── webpack.config.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── release.json ├── rome.json ├── scripts ├── build-greet.js ├── clean-all.js ├── clean.js ├── dev.js ├── goblin.logrotate.conf ├── goblin.service └── goblin.start.sh ├── title-color.svg ├── title.svg └── title.svg.png /.config/docker_example.env: -------------------------------------------------------------------------------- 1 | # db settings 2 | POSTGRES_PASSWORD=example-firefish-pass 3 | POSTGRES_USER=example-firefish-user 4 | POSTGRES_DB=firefish 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 2 6 | charset = utf-8 7 | insert_final_newline = true 8 | 9 | [*.yml] 10 | indent_style = space 11 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" 3 | fi 4 | use flake . --impure 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.svg -diff -text 2 | *.psd -diff -text 3 | *.ai -diff -text 4 | *.mqo -diff -text 5 | *.glb -diff -text 6 | *.blend -diff -text 7 | *.afdesign -diff -text 8 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v18.16.0 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | use-lockfile-v6=true 2 | -------------------------------------------------------------------------------- /.vsls.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/vsls", 3 | "gitignore": "exclude" 4 | } 5 | -------------------------------------------------------------------------------- /.weblate: -------------------------------------------------------------------------------- 1 | [weblate] 2 | url = https://hosted.weblate.org/api/ 3 | translation = firefish/locales 4 | -------------------------------------------------------------------------------- /.woodpecker/dockerHubRelease.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | publish-docker-latest: 3 | image: plugins/kaniko 4 | settings: 5 | repo: thatonecalculator/firefish 6 | tags: latest 7 | dockerfile: Dockerfile 8 | username: 9 | # Secret 'docker_username' needs to be set in the CI settings 10 | from_secret: docker_username 11 | password: 12 | # Secret 'docker_password' needs to be set in the CI settings 13 | from_secret: docker_password 14 | 15 | branches: main 16 | -------------------------------------------------------------------------------- /.woodpecker/dockerHubReleaseCandidate.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | publish-docker-latest: 3 | image: plugins/kaniko 4 | settings: 5 | repo: thatonecalculator/firefish 6 | tags: rc 7 | dockerfile: Dockerfile 8 | username: 9 | # Secret 'docker_username' needs to be set in the CI settings 10 | from_secret: docker_username 11 | password: 12 | # Secret 'docker_password' needs to be set in the CI settings 13 | from_secret: docker_password 14 | branches: beta 15 | -------------------------------------------------------------------------------- /.woodpecker/testDocker.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | docker-build: 3 | image: plugins/kaniko 4 | settings: 5 | repo: thatonecalculator/firefish 6 | tags: test 7 | dockerfile: Dockerfile 8 | no_push: true 9 | 10 | branches: 11 | include: [ main, develop, beta ] 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | tbd -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | TBD -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | TBD -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: NODE_ENV=production npm start 2 | -------------------------------------------------------------------------------- /custom/assets/badges/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/custom/assets/badges/error.png -------------------------------------------------------------------------------- /custom/assets/badges/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/custom/assets/badges/info.png -------------------------------------------------------------------------------- /custom/assets/badges/not-found.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/custom/assets/badges/not-found.png -------------------------------------------------------------------------------- /custom/assets/icons/npf-bold.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/npf-italic.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/npf-read-more.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /custom/assets/icons/posts-quote.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/reblog-compact.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/reply-empty.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/snowman.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/text-indent.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/icons/text-list-unordered.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /custom/assets/instance.css: -------------------------------------------------------------------------------- 1 | /* 2 | * !!! WARNING !!! 3 | * Editing this file may cause your instance to break for EVERYONE. 4 | * Please know what you're doing and test it out with regular user custom CSS. 5 | * With that said, GLHF! 6 | * This may eventuallly be replaced with a function in the admin panel. 7 | */ 8 | -------------------------------------------------------------------------------- /custom/locales/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/custom/locales/.gitkeep -------------------------------------------------------------------------------- /goblin.apache.conf: -------------------------------------------------------------------------------- 1 | # Replace example.tld with your domain 2 | 3 | 4 | ServerName example.tld 5 | # For WebSocket 6 | ProxyPass "/streaming" "ws://127.0.0.1:3000/streaming/" 7 | # Proxy to Node 8 | ProxyPass "/" "http://127.0.0.1:3000/" 9 | ProxyPassReverse "/" "http://127.0.0.1:3000/" 10 | ProxyPreserveHost On 11 | # For files proxy 12 | AllowEncodedSlashes On 13 | -------------------------------------------------------------------------------- /locales/README.md: -------------------------------------------------------------------------------- 1 | # **DO NOT edit locale files** except `ja-JP.yml`. 2 | 3 | When you add text to the ja-JP file (of misskey-dev/misskey), it will automatically be applied to other language files. 4 | Translations added in ja-JP file should contain the original Japanese strings. 5 | 6 | Please see [Contribution guide](../CONTRIBUTING.md) for more information. 7 | -------------------------------------------------------------------------------- /locales/bul_BG.yml: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /locales/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const locales: { [lang: string]: any }; 2 | 3 | export = locales; 4 | -------------------------------------------------------------------------------- /locales/ug-CN.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _lang_: "ياپونچە" 3 | search: "ئىزدەش" 4 | searchByGoogle: "ئىزدەش" 5 | _mfm: 6 | search: "ئىزدەش" 7 | -------------------------------------------------------------------------------- /packages/backend/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /packages/backend/.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension": ["ts","js","cjs","mjs"], 3 | "node-option": [ 4 | "experimental-specifier-resolution=node", 5 | "loader=./test/loader.js" 6 | ], 7 | "slow": 1000, 8 | "timeout": 30000, 9 | "exit": true 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules\\typescript\\lib", 3 | "path-intellisense.mappings": { 4 | "@": "${workspaceRoot}/packages/backend/src/" 5 | }, 6 | "editor.formatOnSave": true, 7 | "editor.codeActionsOnSave": { 8 | "source.fixAll": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/assets/api-doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/api-doc.png -------------------------------------------------------------------------------- /packages/backend/assets/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/apple-touch-icon.png -------------------------------------------------------------------------------- /packages/backend/assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/avatar.png -------------------------------------------------------------------------------- /packages/backend/assets/badges/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/badges/error.png -------------------------------------------------------------------------------- /packages/backend/assets/badges/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/badges/info.png -------------------------------------------------------------------------------- /packages/backend/assets/badges/not-found.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/badges/not-found.png -------------------------------------------------------------------------------- /packages/backend/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/favicon.ico -------------------------------------------------------------------------------- /packages/backend/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/favicon.png -------------------------------------------------------------------------------- /packages/backend/assets/icons/192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/icons/192.png -------------------------------------------------------------------------------- /packages/backend/assets/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/icons/512.png -------------------------------------------------------------------------------- /packages/backend/assets/icons/maskable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/icons/maskable.png -------------------------------------------------------------------------------- /packages/backend/assets/icons/monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/icons/monochrome.png -------------------------------------------------------------------------------- /packages/backend/assets/icons/npf-bold.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/npf-italic.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/npf-read-more.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/posts-quote.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/reblog-compact.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/reply-empty.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/snowman.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/text-indent.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/icons/text-list-unordered.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/backend/assets/instance.css: -------------------------------------------------------------------------------- 1 | /* 2 | * !!! WARNING !!! 3 | * Editing this file may cause your instance to break for EVERYONE. 4 | * Please know what you're doing and test it out with regular user custom CSS. 5 | * With that said, GLHF! 6 | * This may eventuallly be replaced with a function in the admin panel. 7 | */ 8 | -------------------------------------------------------------------------------- /packages/backend/assets/mi-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/mi-white.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/at.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/at.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/check.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/clipboard-check-solid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/clipboard-check-solid.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/clock.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/comments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/comments.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/id-card-alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/id-card-alt.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/null.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/null.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/plus.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/poll-h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/poll-h.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/quote-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/quote-right.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/reply.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/retweet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/retweet.png -------------------------------------------------------------------------------- /packages/backend/assets/notification-badges/user-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/notification-badges/user-plus.png -------------------------------------------------------------------------------- /packages/backend/assets/screenshots/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/screenshots/1.webp -------------------------------------------------------------------------------- /packages/backend/assets/screenshots/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/screenshots/2.webp -------------------------------------------------------------------------------- /packages/backend/assets/sounds/aisha/1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/aisha/1.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/aisha/2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/aisha/2.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/aisha/3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/aisha/3.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/noizenecio/kick_gaba.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/noizenecio/kick_gaba.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/noizenecio/kick_gaba2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/noizenecio/kick_gaba2.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/down.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/down.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/kick.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/kick.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/pirori-square-wet.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/pirori-square-wet.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/pirori-wet.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/pirori-wet.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/pirori.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/pirori.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/poi1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/poi1.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/poi2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/poi2.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/pope1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/pope1.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/pope2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/pope2.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/popo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/popo.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/queue-jammed.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/queue-jammed.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/reverved.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/reverved.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/ryukyu.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/ryukyu.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/snare.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/snare.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/square-pico.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/square-pico.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/triple.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/triple.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/up.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/up.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/sounds/syuilo/waon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/sounds/syuilo/waon.mp3 -------------------------------------------------------------------------------- /packages/backend/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/splash.png -------------------------------------------------------------------------------- /packages/backend/assets/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/transparent.png -------------------------------------------------------------------------------- /packages/backend/assets/user-unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/user-unknown.png -------------------------------------------------------------------------------- /packages/backend/assets/woozy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/assets/woozy.png -------------------------------------------------------------------------------- /packages/backend/check_connect.js: -------------------------------------------------------------------------------- 1 | import { loadConfig } from "./built/config.js"; 2 | import { createRedisConnection } from "./built/redis.js"; 3 | 4 | const config = loadConfig(); 5 | const redis = createRedisConnection(config); 6 | 7 | redis.on("connect", () => redis.disconnect()); 8 | redis.on("error", (e) => { 9 | throw e; 10 | }); 11 | -------------------------------------------------------------------------------- /packages/backend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "allowSyntheticDefaultImports": true 6 | }, 7 | "exclude": ["node_modules", "jspm_packages", "tmp", "temp"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/backend/migration/1557476068003-PinnedUsers.js: -------------------------------------------------------------------------------- 1 | export class PinnedUsers1557476068003 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "meta" ADD "pinnedUsers" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedUsers"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1558266512381-UserListJoining.js: -------------------------------------------------------------------------------- 1 | export class UserListJoining1558266512381 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON "user_list_joining" ("userId", "userListId") `, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`DROP INDEX "IDX_90f7da835e4c10aca6853621e1"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1562422242907-PasswordLessLogin.js: -------------------------------------------------------------------------------- 1 | export class PasswordLessLogin1562422242907 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "user_profile" ADD COLUMN "usePasswordLessLogin" boolean DEFAULT false NOT NULL`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query( 9 | `ALTER TABLE "user_profile" DROP COLUMN "usePasswordLessLogin"`, 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/backend/migration/1562448332510-PageTitleHideOption.js: -------------------------------------------------------------------------------- 1 | export class PageTitleHideOption1562448332510 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "page" ADD "hideTitleWhenPinned" boolean NOT NULL DEFAULT false`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query( 9 | `ALTER TABLE "page" DROP COLUMN "hideTitleWhenPinned"`, 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/backend/migration/1563757595828-UsedUsername.js: -------------------------------------------------------------------------------- 1 | export class UsedUsername1563757595828 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `CREATE TABLE "used_username" ("username" character varying(128) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT "PK_78fd79d2d24c6ac2f4cc9a31a5d" PRIMARY KEY ("username"))`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`DROP TABLE "used_username"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1565634203341-room.js: -------------------------------------------------------------------------------- 1 | export class room1565634203341 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "user_profile" ADD "room" jsonb NOT NULL DEFAULT '{}'`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "room"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1571220798684-CustomEmojiCategory.js: -------------------------------------------------------------------------------- 1 | export class CustomEmojiCategory1571220798684 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "emoji" ADD "category" character varying(128)`, 5 | undefined, 6 | ); 7 | } 8 | async down(queryRunner) { 9 | await queryRunner.query( 10 | `ALTER TABLE "emoji" DROP COLUMN "category"`, 11 | undefined, 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/migration/1576269851876-TalkFederationId.js: -------------------------------------------------------------------------------- 1 | export class TalkFederationId1576269851876 { 2 | constructor() { 3 | this.name = "TalkFederationId1576269851876"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "messaging_message" ADD "uri" character varying(512)`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "messaging_message" DROP COLUMN "uri"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1576869585998-ProxyRemoteFiles.js: -------------------------------------------------------------------------------- 1 | export class ProxyRemoteFiles1576869585998 { 2 | constructor() { 3 | this.name = "ProxyRemoteFiles1576869585998"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1579270193251-v12-2.js: -------------------------------------------------------------------------------- 1 | export class v1221579270193251 { 2 | constructor() { 3 | this.name = "v1221579270193251"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "announcement_read" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "announcement_read" DROP COLUMN "createdAt"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1579282808087-v12-3.js: -------------------------------------------------------------------------------- 1 | export class v1231579282808087 { 2 | constructor() { 3 | this.name = "v1231579282808087"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "announcement" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "announcement" DROP COLUMN "updatedAt"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1580154400017-v12-9.js: -------------------------------------------------------------------------------- 1 | export class v1291580154400017 { 2 | constructor() { 3 | this.name = "v1291580154400017"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "antenna" ADD "withReplies" boolean NOT NULL DEFAULT false`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "antenna" DROP COLUMN "withReplies"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1580543501339-v12-13.js: -------------------------------------------------------------------------------- 1 | export class v12131580543501339 { 2 | constructor() { 3 | this.name = "v12131580543501339"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `CREATE INDEX "IDX_NOTE_TAGS" ON "note" USING gin ("tags")`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query(`DROP INDEX "IDX_NOTE_TAGS"`, undefined); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/migration/1582210532752-antenna-exclude.js: -------------------------------------------------------------------------------- 1 | export class antennaExclude1582210532752 { 2 | constructor() { 3 | this.name = "antennaExclude1582210532752"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "antenna" ADD "excludeKeywords" jsonb NOT NULL DEFAULT '[]'`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "antenna" DROP COLUMN "excludeKeywords"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1585772678853-ap-url.js: -------------------------------------------------------------------------------- 1 | export class apUrl1585772678853 { 2 | constructor() { 3 | this.name = "apUrl1585772678853"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "note" ADD "url" character varying(512)`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "url"`, undefined); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/migration/1586708940386-pageAiScript.js: -------------------------------------------------------------------------------- 1 | export class pageAiScript1586708940386 { 2 | constructor() { 3 | this.name = "pageAiScript1586708940386"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "page" ADD "script" character varying(16384) NOT NULL DEFAULT ''`, 8 | undefined, 9 | ); 10 | } 11 | async down(queryRunner) { 12 | await queryRunner.query( 13 | `ALTER TABLE "page" DROP COLUMN "script"`, 14 | undefined, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/migration/1595075960584-blurhash.js: -------------------------------------------------------------------------------- 1 | export class blurhash1595075960584 { 2 | constructor() { 3 | this.name = "blurhash1595075960584"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "drive_file" ADD "blurhash" character varying(128)`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "blurhash"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1595676934834-instance-icon-url.js: -------------------------------------------------------------------------------- 1 | export class instanceIconUrl1595676934834 { 2 | constructor() { 3 | this.name = "instanceIconUrl1595676934834"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "instance" ADD "iconUrl" character varying(256) DEFAULT null`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "iconUrl"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1596786425167-channel2.js: -------------------------------------------------------------------------------- 1 | export class channel21596786425167 { 2 | constructor() { 3 | this.name = "channel21596786425167"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "channel_following" DROP COLUMN "readCursor"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1597230137744-objectStorageSetPublicRead.js: -------------------------------------------------------------------------------- 1 | export class objectStorageSetPublicRead1597230137744 { 2 | constructor() { 3 | this.name = "objectStorageSetPublicRead1597230137744"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "objectStorageSetPublicRead" boolean NOT NULL DEFAULT false`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1597385880794-add-sensitive-index.js: -------------------------------------------------------------------------------- 1 | export class addSensitiveIndex1597385880794 { 2 | constructor() { 3 | this.name = "addSensitiveIndex1597385880794"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `CREATE INDEX "IDX_a7eba67f8b3fa27271e85d2e26" ON "drive_file" ("isSensitive") `, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`DROP INDEX "IDX_a7eba67f8b3fa27271e85d2e26"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1603776877564-instance-theme-color.js: -------------------------------------------------------------------------------- 1 | export class instanceThemeColor1603776877564 { 2 | constructor() { 3 | this.name = "instanceThemeColor1603776877564"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "instance" ADD "themeColor" character varying(64) DEFAULT null`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1603781553011-instance-favicon.js: -------------------------------------------------------------------------------- 1 | export class instanceFavicon1603781553011 { 2 | constructor() { 3 | this.name = "instanceFavicon1603781553011"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "instance" ADD "faviconUrl" character varying(256) DEFAULT null`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1604821689616-delete-auto-watch.js: -------------------------------------------------------------------------------- 1 | export class deleteAutoWatch1604821689616 { 2 | constructor() { 3 | this.name = "deleteAutoWatch1604821689616"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "user_profile" DROP COLUMN "autoWatch"`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user_profile" ADD "autoWatch" boolean NOT NULL DEFAULT false`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1605408848373-clip-description.js: -------------------------------------------------------------------------------- 1 | export class clipDescription1605408848373 { 2 | constructor() { 3 | this.name = "clipDescription1605408848373"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "clip" ADD "description" character varying(2048) DEFAULT null`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "clip" DROP COLUMN "description"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1607151207216-instance-pinned-clip.js: -------------------------------------------------------------------------------- 1 | export class instancePinnedClip1607151207216 { 2 | constructor() { 3 | this.name = "instancePinnedClip1607151207216"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "pinnedClipId" character varying(32)`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedClipId"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1610283021566-registry3.js: -------------------------------------------------------------------------------- 1 | export class registry31610283021566 { 2 | constructor() { 3 | this.name = "registry31610283021566"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "registry_item" ALTER COLUMN "value" DROP NOT NULL`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "registry_item" ALTER COLUMN "value" SET NOT NULL`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1612619156584-announcement-email.js: -------------------------------------------------------------------------------- 1 | export class announcementEmail1612619156584 { 2 | constructor() { 3 | this.name = "announcementEmail1612619156584"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "user_profile" ADD "receiveAnnouncementEmail" boolean NOT NULL DEFAULT true`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user_profile" DROP COLUMN "receiveAnnouncementEmail"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1613181457597-user-lang.js: -------------------------------------------------------------------------------- 1 | export class userLang1613181457597 { 2 | constructor() { 3 | this.name = "userLang1613181457597"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "user_profile" ADD "lang" character varying(32)`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1618639857000-user-hide-online-status.js: -------------------------------------------------------------------------------- 1 | export class userHideOnlineStatus1618639857000 { 2 | constructor() { 3 | this.name = "userHideOnlineStatus1618639857000"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "user" ADD "hideOnlineStatus" boolean NOT NULL DEFAULT false`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user" DROP COLUMN "hideOnlineStatus"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1620364649428-ad2.js: -------------------------------------------------------------------------------- 1 | export class ad21620364649428 { 2 | constructor() { 3 | this.name = "ad21620364649428"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "ad" ADD "ratio" integer NOT NULL DEFAULT '1'`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1629024377804-deepl-integration.js: -------------------------------------------------------------------------------- 1 | export class deeplIntegration1629024377804 { 2 | constructor() { 3 | this.name = "deeplIntegration1629024377804"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "deeplAuthKey" character varying(128)`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1629288472000-fix-channel-userId.js: -------------------------------------------------------------------------------- 1 | export class fixChannelUserId1629288472000 { 2 | constructor() { 3 | this.name = "fixChannelUserId1629288472000"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "channel" ALTER COLUMN "userId" DROP NOT NULL;`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1629778475000-deepl-integration2.js: -------------------------------------------------------------------------------- 1 | export class deeplIntegration21629778475000 { 2 | constructor() { 3 | this.name = "deeplIntegration21629778475000"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "deeplIsPro" boolean NOT NULL DEFAULT false`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplIsPro"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1633068642000-email-required-for-signup.js: -------------------------------------------------------------------------------- 1 | export class emailRequiredForSignup1633068642000 { 2 | constructor() { 3 | this.name = "emailRequiredForSignup1633068642000"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "meta" ADD "emailRequiredForSignup" boolean NOT NULL DEFAULT false`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" DROP COLUMN "emailRequiredForSignup"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1634486652000-user-public-reactions.js: -------------------------------------------------------------------------------- 1 | export class userPublicReactions1634486652000 { 2 | constructor() { 3 | this.name = "userPublicReactions1634486652000"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "user_profile" ADD "publicReactions" boolean NOT NULL DEFAULT false`, 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user_profile" DROP COLUMN "publicReactions"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1634902659689-delete-log.js: -------------------------------------------------------------------------------- 1 | export class deleteLog1634902659689 { 2 | constructor() { 3 | this.name = "deleteLog1634902659689"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query(`DROP TABLE "log"`); 7 | } 8 | async down(queryRunner) {} 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/migration/1636697408073-remove-via-mobile.js: -------------------------------------------------------------------------------- 1 | export class removeViaMobile1636697408073 { 2 | name = "removeViaMobile1636697408073"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "viaMobile"`); 6 | } 7 | 8 | async down(queryRunner) { 9 | await queryRunner.query( 10 | `ALTER TABLE "note" ADD "viaMobile" boolean NOT NULL DEFAULT false`, 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1637320813000-forwarded-report.js: -------------------------------------------------------------------------------- 1 | export class forwardedReport1637320813000 { 2 | name = "forwardedReport1637320813000"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "abuse_user_report" ADD "forwarded" boolean NOT NULL DEFAULT false`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "abuse_user_report" DROP COLUMN "forwarded"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1642613870898-drive-file-webpublic-type.js: -------------------------------------------------------------------------------- 1 | export class driveFileWebpublicType1642613870898 { 2 | name = "driveFileWebpublicType1642613870898"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "drive_file" ADD "webpublicType" character varying(128)`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "drive_file" DROP COLUMN "webpublicType"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1644395759931-instance-theme-color.js: -------------------------------------------------------------------------------- 1 | export class instanceThemeColor1644395759931 { 2 | name = "instanceThemeColor1644395759931"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ADD "themeColor" character varying(512)`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "themeColor"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1645340161439-remove-max-note-text-length.js: -------------------------------------------------------------------------------- 1 | export class removeMaxNoteTextLength1645340161439 { 2 | name = "removeMaxNoteTextLength1645340161439"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" DROP COLUMN "maxNoteTextLength"`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" ADD "maxNoteTextLength" integer NOT NULL DEFAULT '500'`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1656408772602-nsfw-detection-6.js: -------------------------------------------------------------------------------- 1 | export class nsfwDetection61656408772602 { 2 | name = "nsfwDetection61656408772602"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ADD "enableSensitiveMediaDetectionForVideos" boolean NOT NULL DEFAULT false`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" DROP COLUMN "enableSensitiveMediaDetectionForVideos"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1656772790599-user-moderation-note.js: -------------------------------------------------------------------------------- 1 | export class userModerationNote1656772790599 { 2 | name = "userModerationNote1656772790599"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "user_profile" ADD "moderationNote" character varying(8192) NOT NULL DEFAULT ''`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user_profile" DROP COLUMN "moderationNote"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1657346559800-active-email-validation.js: -------------------------------------------------------------------------------- 1 | export class activeEmailValidation1657346559800 { 2 | name = "activeEmailValidation1657346559800"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ADD "enableActiveEmailValidation" boolean NOT NULL DEFAULT true`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" DROP COLUMN "enableActiveEmailValidation"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1658939464003CustomMOTD.js: -------------------------------------------------------------------------------- 1 | export class CustomMOTD1658939464003 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "meta" ADD "customMOTD" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "customMOTD"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1658941974648CustomSplashIcons.js: -------------------------------------------------------------------------------- 1 | export class CustomSplashIcons1658941974648 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "meta" ADD "customSplashIcons" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query( 9 | `ALTER TABLE "meta" DROP COLUMN "customSplashIcons"`, 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/backend/migration/1660068273737GuestTimeline.js: -------------------------------------------------------------------------------- 1 | export class GuestTimeline1660068273737 { 2 | name = "GuestTimeline1660068273737"; 3 | async up(queryRunner) { 4 | await queryRunner.query( 5 | `ALTER TABLE "meta" ADD "enableGuestTimeline" boolean NOT NULL DEFAULT false`, 6 | ); 7 | } 8 | async down(queryRunner) { 9 | await queryRunner.query( 10 | `ALTER TABLE "meta" DROP COLUMN "enableGuestTimeline"`, 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1668828368510PageDraft.js: -------------------------------------------------------------------------------- 1 | export class Page1668828368510 { 2 | async up(queryRunner) { 3 | await queryRunner.query( 4 | `ALTER TABLE "page" ADD "isPublic" boolean NOT NULL DEFAULT true`, 5 | ); 6 | } 7 | async down(queryRunner) { 8 | await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "isPublic"`); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/migration/1668831378728FixCalckeyAgain.js: -------------------------------------------------------------------------------- 1 | export class FixFirefishAgain1668831378728 { 2 | name = "FixFirefishAgain1668831378728"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `UPDATE "meta" SET "useStarForReactionFallback" = TRUE`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `UPDATE "meta" SET "useStarForReactionFallback" = FALSE`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js: -------------------------------------------------------------------------------- 1 | export class whetherPushNotifyToSendReadMessage1669138716634 { 2 | name = "whetherPushNotifyToSendReadMessage1669138716634"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "sw_subscription" ADD "sendReadMessage" boolean NOT NULL DEFAULT false`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "sw_subscription" DROP COLUMN "sendReadMessage"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1673336077243-PollChoiceLength.js: -------------------------------------------------------------------------------- 1 | export class PollChoiceLength1673336077243 { 2 | name = "PollChoiceLength1673336077243"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(256) array`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "poll" ALTER COLUMN "choices" TYPE character varying(128) array`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1677935903517-DriveComment.js: -------------------------------------------------------------------------------- 1 | export class DriveComment1677935903517 { 2 | name = "DriveComment1677935903517"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(8192)`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "drive_file" ALTER "comment" TYPE character varying(512)`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1678426061773-tweak-varchar-length.js: -------------------------------------------------------------------------------- 1 | export class tweakVarcharLength1678426061773 { 2 | name = "tweakVarcharLength1678426061773"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ALTER COLUMN "smtpUser" TYPE character varying(1024)`, 7 | undefined, 8 | ); 9 | await queryRunner.query( 10 | `ALTER TABLE "meta" ALTER COLUMN "smtpPass" TYPE character varying(1024)`, 11 | undefined, 12 | ); 13 | } 14 | 15 | async down(queryRunner) {} 16 | } 17 | -------------------------------------------------------------------------------- /packages/backend/migration/1678945242650-add-props-for-custom-emoji.js: -------------------------------------------------------------------------------- 1 | export class addPropsForCustomEmoji1678945242650 { 2 | name = "addPropsForCustomEmoji1678945242650"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "emoji" ADD "license" character varying(1024)`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "license"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1682891890317-InstanceSilence.js: -------------------------------------------------------------------------------- 1 | export class InstanceSilence1682891890317 { 2 | name = "InstanceSilence1682891890317"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ADD "silencedHosts" character varying(256) array NOT NULL DEFAULT '{}'`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "silencedHosts"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1682891891317-AddHiddenPosts.js: -------------------------------------------------------------------------------- 1 | export class AddHiddenPosts1682891891317 { 2 | name = "AddHiddenPosts1682891891317"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TYPE note_visibility_enum ADD VALUE IF NOT EXISTS 'hidden'`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TYPE note_visibility_enum REMOVE VALUE IF EXISTS 'hidden'`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1683682889948-PreventAiLearning.js: -------------------------------------------------------------------------------- 1 | export class PreventAiLearning1683682889948 { 2 | name = "PreventAiLearning1683682889948"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "user_profile" ADD "preventAiLearning" boolean NOT NULL DEFAULT true`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user_profile" DROP COLUMN "preventAiLearning"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1683980686995-ExperimentalFeatures.js: -------------------------------------------------------------------------------- 1 | export class ExperimentalFeatures1683980686995 { 2 | name = "ExperimentalFeatures1683980686995"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query(` 6 | ALTER TABLE "meta" 7 | ADD "experimentalFeatures" jsonb NOT NULL DEFAULT '{}' 8 | `); 9 | } 10 | 11 | async down(queryRunner) { 12 | await queryRunner.query(` 13 | ALTER TABLE "meta" DROP COLUMN "experimentalFeatures" 14 | `); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/backend/migration/1684206886988-remove-showTimelineReplies.js: -------------------------------------------------------------------------------- 1 | export class RemoveShowTimelineReplies1684206886988 { 2 | name = "RemoveShowTimelineReplies1684206886988"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1689136347561-donation-link.js: -------------------------------------------------------------------------------- 1 | export class DonationLink1689136347561 { 2 | name = "DonationLink1689136347561"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "meta" ADD "donationLink" character varying(256)`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query( 12 | `ALTER TABLE "meta" DROP COLUMN "DonationLink1689136347561"`, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/migration/1689957800000-Goblin-start.js: -------------------------------------------------------------------------------- 1 | export class Goblin1689957800000 { 2 | name = "Goblin1689957800000"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "note" ADD "reblogtrail" json NULL default '{}'::json`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "reblogtrail"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1689957900000-quote-count.js: -------------------------------------------------------------------------------- 1 | export class Quote1689957900000 { 2 | name = "Quote1689957900000"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "note" ADD "quoteCount" smallint NULL default 0`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "quoteCount"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1712665566741-note-slug.js: -------------------------------------------------------------------------------- 1 | export class NoteSlug1712665566741 { 2 | name = "NoteSlug1712665566741"; 3 | 4 | async up(queryRunner) { 5 | await queryRunner.query( 6 | `ALTER TABLE "note" ADD "slug" character varying(128) NULL`, 7 | ); 8 | } 9 | 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "slug"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/migration/1717142049375-externalPostId.js: -------------------------------------------------------------------------------- 1 | export class externalPostId1717142049375 { 2 | constructor() { 3 | this.name = "externalPostId1717142049375"; 4 | } 5 | async up(queryRunner) { 6 | await queryRunner.query( 7 | `ALTER TABLE "note" ADD "externalId" character varying(32) NULL` 8 | ); 9 | } 10 | async down(queryRunner) { 11 | await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "externalId"`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/native-utils/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-unknown-linux-musl] 2 | linker = "aarch64-linux-musl-gcc" 3 | rustflags = ["-C", "target-feature=-crt-static"] -------------------------------------------------------------------------------- /packages/backend/native-utils/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.rs] 2 | indent_style = space 3 | indent_size = 4 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/.npmignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .cargo 4 | .github 5 | npm 6 | .eslintrc 7 | .prettierignore 8 | rustfmt.toml 9 | yarn.lock 10 | *.node 11 | .yarn 12 | __test__ 13 | renovate.json 14 | -------------------------------------------------------------------------------- /packages/backend/native-utils/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | napi_build::setup(); 5 | } 6 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/android-arm-eabi/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-android-arm-eabi` 2 | 3 | This is the **armv7-linux-androideabi** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/android-arm-eabi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-android-arm-eabi", 3 | "version": "0.0.0", 4 | "os": [ 5 | "android" 6 | ], 7 | "cpu": [ 8 | "arm" 9 | ], 10 | "main": "native-utils.android-arm-eabi.node", 11 | "files": [ 12 | "native-utils.android-arm-eabi.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/android-arm64/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-android-arm64` 2 | 3 | This is the **aarch64-linux-android** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/android-arm64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-android-arm64", 3 | "version": "0.0.0", 4 | "os": [ 5 | "android" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "native-utils.android-arm64.node", 11 | "files": [ 12 | "native-utils.android-arm64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-arm64/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-darwin-arm64` 2 | 3 | This is the **aarch64-apple-darwin** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-arm64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-darwin-arm64", 3 | "version": "0.0.0", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "native-utils.darwin-arm64.node", 11 | "files": [ 12 | "native-utils.darwin-arm64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-universal/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-darwin-universal` 2 | 3 | This is the **universal-apple-darwin** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-universal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-darwin-universal", 3 | "version": "0.0.0", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "main": "native-utils.darwin-universal.node", 8 | "files": [ 9 | "native-utils.darwin-universal.node" 10 | ], 11 | "license": "MIT", 12 | "engines": { 13 | "node": ">= 10" 14 | } 15 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-x64/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-darwin-x64` 2 | 3 | This is the **x86_64-apple-darwin** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/darwin-x64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-darwin-x64", 3 | "version": "0.0.0", 4 | "os": [ 5 | "darwin" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "native-utils.darwin-x64.node", 11 | "files": [ 12 | "native-utils.darwin-x64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/freebsd-x64/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-freebsd-x64` 2 | 3 | This is the **x86_64-unknown-freebsd** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/freebsd-x64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-freebsd-x64", 3 | "version": "0.0.0", 4 | "os": [ 5 | "freebsd" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "native-utils.freebsd-x64.node", 11 | "files": [ 12 | "native-utils.freebsd-x64.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm-gnueabihf/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-linux-arm-gnueabihf` 2 | 3 | This is the **armv7-unknown-linux-gnueabihf** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm-gnueabihf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-linux-arm-gnueabihf", 3 | "version": "0.0.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm" 9 | ], 10 | "main": "native-utils.linux-arm-gnueabihf.node", 11 | "files": [ 12 | "native-utils.linux-arm-gnueabihf.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-linux-arm64-gnu` 2 | 3 | This is the **aarch64-unknown-linux-gnu** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-linux-arm64-gnu", 3 | "version": "0.0.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "native-utils.linux-arm64-gnu.node", 11 | "files": [ 12 | "native-utils.linux-arm64-gnu.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "glibc" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm64-musl/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-linux-arm64-musl` 2 | 3 | This is the **aarch64-unknown-linux-musl** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-arm64-musl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-linux-arm64-musl", 3 | "version": "0.0.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "native-utils.linux-arm64-musl.node", 11 | "files": [ 12 | "native-utils.linux-arm64-musl.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "musl" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-x64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-linux-x64-gnu` 2 | 3 | This is the **x86_64-unknown-linux-gnu** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-x64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-linux-x64-gnu", 3 | "version": "0.0.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "native-utils.linux-x64-gnu.node", 11 | "files": [ 12 | "native-utils.linux-x64-gnu.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "glibc" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-x64-musl/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-linux-x64-musl` 2 | 3 | This is the **x86_64-unknown-linux-musl** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/linux-x64-musl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-linux-x64-musl", 3 | "version": "0.0.0", 4 | "os": [ 5 | "linux" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "native-utils.linux-x64-musl.node", 11 | "files": [ 12 | "native-utils.linux-x64-musl.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | }, 18 | "libc": [ 19 | "musl" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-arm64-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-win32-arm64-msvc` 2 | 3 | This is the **aarch64-pc-windows-msvc** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-arm64-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-win32-arm64-msvc", 3 | "version": "0.0.0", 4 | "os": [ 5 | "win32" 6 | ], 7 | "cpu": [ 8 | "arm64" 9 | ], 10 | "main": "native-utils.win32-arm64-msvc.node", 11 | "files": [ 12 | "native-utils.win32-arm64-msvc.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-ia32-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-win32-ia32-msvc` 2 | 3 | This is the **i686-pc-windows-msvc** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-ia32-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-win32-ia32-msvc", 3 | "version": "0.0.0", 4 | "os": [ 5 | "win32" 6 | ], 7 | "cpu": [ 8 | "ia32" 9 | ], 10 | "main": "native-utils.win32-ia32-msvc.node", 11 | "files": [ 12 | "native-utils.win32-ia32-msvc.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-x64-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `native-utils-win32-x64-msvc` 2 | 3 | This is the **x86_64-pc-windows-msvc** binary for `native-utils` 4 | -------------------------------------------------------------------------------- /packages/backend/native-utils/npm/win32-x64-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "native-utils-win32-x64-msvc", 3 | "version": "0.0.0", 4 | "os": [ 5 | "win32" 6 | ], 7 | "cpu": [ 8 | "x64" 9 | ], 10 | "main": "native-utils.win32-x64-msvc.node", 11 | "files": [ 12 | "native-utils.win32-x64-msvc.node" 13 | ], 14 | "license": "MIT", 15 | "engines": { 16 | "node": ">= 10" 17 | } 18 | } -------------------------------------------------------------------------------- /packages/backend/native-utils/src/database/error.rs: -------------------------------------------------------------------------------- 1 | use sea_orm::error::DbErr; 2 | 3 | use crate::impl_into_napi_error; 4 | 5 | #[derive(thiserror::Error, Debug, PartialEq, Eq)] 6 | pub enum Error { 7 | #[error("The database connections have not been initialized yet")] 8 | Uninitialized, 9 | #[error("ORM error: {0}")] 10 | OrmError(#[from] DbErr), 11 | } 12 | 13 | impl_into_napi_error!(Error); 14 | -------------------------------------------------------------------------------- /packages/backend/native-utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod database; 2 | pub mod macros; 3 | pub mod model; 4 | pub mod util; 5 | 6 | #[cfg(feature = "napi")] 7 | pub mod mastodon_api; 8 | -------------------------------------------------------------------------------- /packages/backend/native-utils/src/macros.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! impl_into_napi_error { 3 | ($a:ty) => { 4 | #[cfg(feature = "napi")] 5 | impl Into for $a { 6 | fn into(self) -> napi::Error { 7 | napi::Error::from_reason(self.to_string()) 8 | } 9 | } 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/backend/native-utils/src/model/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod entity; 2 | pub mod error; 3 | pub mod repository; 4 | pub mod schema; 5 | -------------------------------------------------------------------------------- /packages/backend/native-utils/src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod id; 2 | pub mod random; 3 | -------------------------------------------------------------------------------- /packages/backend/native-utils/tests/model/mod.rs: -------------------------------------------------------------------------------- 1 | mod repository; 2 | -------------------------------------------------------------------------------- /packages/backend/native-utils/tests/model/repository.rs: -------------------------------------------------------------------------------- 1 | mod antenna; 2 | -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard1of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard1of6 -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard2of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard2of6 -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard3of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard3of6 -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard4of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard4of6 -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard5of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard5of6 -------------------------------------------------------------------------------- /packages/backend/nsfw-model/group1-shard6of6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/nsfw-model/group1-shard6of6 -------------------------------------------------------------------------------- /packages/backend/ormconfig.js: -------------------------------------------------------------------------------- 1 | import { DataSource } from "typeorm"; 2 | import config from "./built/config/index.js"; 3 | import { entities } from "./built/db/postgre.js"; 4 | 5 | export default new DataSource({ 6 | type: "postgres", 7 | host: config.db.host, 8 | port: config.db.port, 9 | username: config.db.user, 10 | password: config.db.pass, 11 | database: config.db.db, 12 | extra: config.db.extra, 13 | entities: entities, 14 | migrations: ["migration/*.js"], 15 | }); 16 | -------------------------------------------------------------------------------- /packages/backend/src/@types/hcaptcha.d.ts: -------------------------------------------------------------------------------- 1 | declare module "hcaptcha" { 2 | interface IVerifyResponse { 3 | success: boolean; 4 | challenge_ts: string; 5 | hostname: string; 6 | credit?: boolean; 7 | "error-codes"?: unknown[]; 8 | } 9 | 10 | export function verify( 11 | secret: string, 12 | token: string, 13 | ): Promise; 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/@types/koa-json-body.d.ts: -------------------------------------------------------------------------------- 1 | declare module "koa-json-body" { 2 | import type { Middleware } from "koa"; 3 | 4 | interface IKoaJsonBodyOptions { 5 | strict: boolean; 6 | limit: string; 7 | fallback: boolean; 8 | } 9 | 10 | function koaJsonBody(opt?: IKoaJsonBodyOptions): Middleware; 11 | 12 | namespace koaJsonBody {} // Hack 13 | 14 | export = koaJsonBody; 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/src/@types/koa-remove-trailing-slashes/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "koa-remove-trailing-slashes"; 2 | -------------------------------------------------------------------------------- /packages/backend/src/@types/koa-slow.d.ts: -------------------------------------------------------------------------------- 1 | declare module "koa-slow" { 2 | import type { Middleware } from "koa"; 3 | 4 | interface ISlowOptions { 5 | url?: RegExp; 6 | delay?: number; 7 | } 8 | 9 | function slow(options?: ISlowOptions): Middleware; 10 | 11 | namespace slow {} // Hack 12 | 13 | export = slow; 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/@types/package.json.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*/package.json" { 2 | interface IRepository { 3 | type: string; 4 | url: string; 5 | } 6 | 7 | export const name: string; 8 | export const version: string; 9 | export const repository: IRepository; 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/src/config/index.ts: -------------------------------------------------------------------------------- 1 | import load from "./load.js"; 2 | 3 | export default load(); 4 | -------------------------------------------------------------------------------- /packages/backend/src/daemons/janitor.ts: -------------------------------------------------------------------------------- 1 | // TODO: 消したい 2 | 3 | const interval = 30 * 60 * 1000; 4 | import { AttestationChallenges } from "@/models/index.js"; 5 | import { LessThan } from "typeorm"; 6 | 7 | /** 8 | * Clean up database occasionally 9 | */ 10 | export default function () { 11 | async function tick() { 12 | await AttestationChallenges.delete({ 13 | createdAt: LessThan(new Date(new Date().getTime() - 5 * 60 * 1000)), 14 | }); 15 | } 16 | 17 | tick(); 18 | 19 | setInterval(tick, interval); 20 | } 21 | -------------------------------------------------------------------------------- /packages/backend/src/db/logger.ts: -------------------------------------------------------------------------------- 1 | import Logger from "@/services/logger.js"; 2 | 3 | export const dbLogger = new Logger("db"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/global.d.ts: -------------------------------------------------------------------------------- 1 | // rome-ignore lint/suspicious/noExplicitAny: i have no idea 2 | type FIXME = any; 3 | -------------------------------------------------------------------------------- /packages/backend/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Misskey Entry Point! 3 | */ 4 | 5 | import { EventEmitter } from "node:events"; 6 | import boot from "./boot/index.js"; 7 | 8 | Error.stackTraceLimit = Infinity; 9 | EventEmitter.defaultMaxListeners = 128; 10 | 11 | boot().catch((err) => { 12 | console.error(err); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/backend/src/misc/acct.ts: -------------------------------------------------------------------------------- 1 | export type Acct = { 2 | username: string; 3 | host: string | null; 4 | }; 5 | 6 | export function parse(acct: string): Acct { 7 | if (acct.startsWith("@")) acct = acct.slice(1); 8 | const split = acct.split("@", 2); 9 | return { username: split[0], host: split[1] || null }; 10 | } 11 | 12 | export function toString(acct: Acct): string { 13 | return acct.host == null ? acct.username : `${acct.username}@${acct.host}`; 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/misc/content-disposition.ts: -------------------------------------------------------------------------------- 1 | import cd from "content-disposition"; 2 | 3 | export function contentDisposition( 4 | type: "inline" | "attachment", 5 | filename: string, 6 | ): string { 7 | const fallback = filename.replace(/[^\w.-]/g, "_"); 8 | return cd(filename, { type, fallback }); 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/src/misc/detect-url-mime.ts: -------------------------------------------------------------------------------- 1 | import { createTemp } from "./create-temp.js"; 2 | import { downloadUrl } from "./download-url.js"; 3 | import { detectType } from "./get-file-info.js"; 4 | 5 | export async function detectUrlMime(url: string) { 6 | const [path, cleanup] = await createTemp(); 7 | 8 | try { 9 | await downloadUrl(url, path); 10 | const { mime } = await detectType(path); 11 | return mime; 12 | } finally { 13 | cleanup(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/src/misc/emoji-regex.ts: -------------------------------------------------------------------------------- 1 | import twemoji from "twemoji-parser/dist/lib/regex.js"; 2 | const twemojiRegex = twemoji.default; 3 | 4 | export const emojiRegex = new RegExp(`(${twemojiRegex.source})`); 5 | export const emojiRegexAtStartToEnd = new RegExp(`^(${twemojiRegex.source})$`); 6 | -------------------------------------------------------------------------------- /packages/backend/src/misc/extract-custom-emojis-from-mfm.ts: -------------------------------------------------------------------------------- 1 | import * as mfm from "mfm-js"; 2 | import { unique } from "@/prelude/array.js"; 3 | 4 | export function extractCustomEmojisFromMfm(nodes: mfm.MfmNode[]): string[] { 5 | const emojiNodes = mfm.extract(nodes, (node) => { 6 | return node.type === "emojiCode" && node.props.name.length <= 100; 7 | }); 8 | 9 | return unique(emojiNodes.map((x) => x.props.name)); 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/src/misc/extract-hashtags.ts: -------------------------------------------------------------------------------- 1 | import * as mfm from "mfm-js"; 2 | import { unique } from "@/prelude/array.js"; 3 | 4 | export function extractHashtags(nodes: mfm.MfmNode[]): string[] { 5 | const hashtagNodes = mfm.extract(nodes, (node) => node.type === "hashtag"); 6 | const hashtags = unique(hashtagNodes.map((x) => x.props.hashtag)); 7 | 8 | return hashtags; 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/src/misc/extract-mentions.ts: -------------------------------------------------------------------------------- 1 | // test is located in test/extract-mentions 2 | 3 | import * as mfm from "mfm-js"; 4 | 5 | export function extractMentions( 6 | nodes: mfm.MfmNode[], 7 | ): mfm.MfmMention["props"][] { 8 | // TODO: 重複を削除 9 | const mentionNodes = mfm.extract(nodes, (node) => node.type === "mention"); 10 | const mentions = mentionNodes.map((x) => x.props); 11 | 12 | return mentions; 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/src/misc/fetch-proxy-account.ts: -------------------------------------------------------------------------------- 1 | import { fetchMeta } from "./fetch-meta.js"; 2 | import type { ILocalUser } from "@/models/entities/user.js"; 3 | import { Users } from "@/models/index.js"; 4 | 5 | export async function fetchProxyAccount(): Promise { 6 | const meta = await fetchMeta(); 7 | if (meta.proxyAccountId == null) return null; 8 | return (await Users.findOneByOrFail({ 9 | id: meta.proxyAccountId, 10 | })) as ILocalUser; 11 | } 12 | -------------------------------------------------------------------------------- /packages/backend/src/misc/identifiable-error.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ID付きエラー 3 | */ 4 | export class IdentifiableError extends Error { 5 | public message: string; 6 | public id: string; 7 | 8 | constructor(id: string, message?: string) { 9 | super(message); 10 | this.message = message || ""; 11 | this.id = id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/backend/src/misc/is-duplicate-key-value-error.ts: -------------------------------------------------------------------------------- 1 | export function isDuplicateKeyValueError(e: unknown | Error): boolean { 2 | const nodeError = e as NodeJS.ErrnoException; 3 | return nodeError.code === "23505"; 4 | } 5 | -------------------------------------------------------------------------------- /packages/backend/src/misc/is-mime-image.ts: -------------------------------------------------------------------------------- 1 | import { FILE_TYPE_BROWSERSAFE } from "@/const.js"; 2 | 3 | const dictionary = { 4 | "safe-file": FILE_TYPE_BROWSERSAFE, 5 | "sharp-convertible-image": [ 6 | "image/jpeg", 7 | "image/png", 8 | "image/gif", 9 | "image/apng", 10 | "image/vnd.mozilla.apng", 11 | "image/webp", 12 | "image/svg+xml", 13 | "image/avif", 14 | ], 15 | }; 16 | 17 | export const isMimeImage = ( 18 | mime: string, 19 | type: keyof typeof dictionary, 20 | ): boolean => dictionary[type].includes(mime); 21 | -------------------------------------------------------------------------------- /packages/backend/src/misc/is-quote.ts: -------------------------------------------------------------------------------- 1 | import type { Note } from "@/models/entities/note.js"; 2 | 3 | export default function (note: Note): boolean { 4 | return ( 5 | note.renoteId != null && 6 | (note.text != null || 7 | note.hasPoll || 8 | (note.fileIds != null && note.fileIds.length > 0)) 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/src/misc/is-user-related.ts: -------------------------------------------------------------------------------- 1 | export function isUserRelated(note: any, ids: Set): boolean { 2 | if (ids.has(note.userId)) return true; // note author is muted 3 | if (note.mentions?.some((user: string) => ids.has(user))) return true; // any of mentioned users are muted 4 | if (note.reply && isUserRelated(note.reply, ids)) return true; // also check reply target 5 | if (note.renote && isUserRelated(note.renote, ids)) return true; // also check renote target 6 | return false; 7 | } 8 | -------------------------------------------------------------------------------- /packages/backend/src/misc/normalize-for-search.ts: -------------------------------------------------------------------------------- 1 | export function normalizeForSearch(tag: string): string { 2 | // ref. 3 | // - https://analytics-note.xyz/programming/unicode-normalization-forms/ 4 | // - https://maku77.github.io/js/string/normalize.html 5 | return tag.normalize("NFKC").toLowerCase(); 6 | } 7 | -------------------------------------------------------------------------------- /packages/backend/src/misc/post.ts: -------------------------------------------------------------------------------- 1 | export type Post = { 2 | text: string | null; 3 | cw: string | null; 4 | localOnly: boolean; 5 | createdAt: Date; 6 | }; 7 | 8 | export function parse(acct: any): Post { 9 | return { 10 | text: acct.text, 11 | cw: acct.cw, 12 | localOnly: acct.localOnly, 13 | createdAt: new Date(acct.createdAt), 14 | }; 15 | } 16 | 17 | export function toJson(acct: Post): string { 18 | return { text: acct.text, cw: acct.cw, localOnly: acct.localOnly }.toString(); 19 | } 20 | -------------------------------------------------------------------------------- /packages/backend/src/misc/safe-for-sql.ts: -------------------------------------------------------------------------------- 1 | export function safeForSql(text: string): boolean { 2 | return !/[\0\x08\x09\x1a\n\r"'\\\%]/g.test(text); 3 | } 4 | -------------------------------------------------------------------------------- /packages/backend/src/misc/secure-rndstr.ts: -------------------------------------------------------------------------------- 1 | import { nativeRandomStr } from "native-utils/built/index.js"; 2 | 3 | export function secureRndstr(length = 32, _ = true): string { 4 | return nativeRandomStr(length); 5 | } 6 | -------------------------------------------------------------------------------- /packages/backend/src/misc/sql-like-escape.ts: -------------------------------------------------------------------------------- 1 | export function sqlLikeEscape(s: string) { 2 | return s.replace(/([%_])/g, "\\$1"); 3 | } 4 | -------------------------------------------------------------------------------- /packages/backend/src/misc/truncate.ts: -------------------------------------------------------------------------------- 1 | import { substring } from "stringz"; 2 | 3 | export function truncate(input: string, size: number): string; 4 | export function truncate( 5 | input: string | undefined, 6 | size: number, 7 | ): string | undefined; 8 | export function truncate( 9 | input: string | undefined, 10 | size: number, 11 | ): string | undefined { 12 | if (!input) { 13 | return input; 14 | } else { 15 | return substring(input, 0, size); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/src/models/entities/registration-tickets.ts: -------------------------------------------------------------------------------- 1 | import { PrimaryColumn, Entity, Index, Column } from "typeorm"; 2 | import { id } from "../id.js"; 3 | 4 | @Entity() 5 | export class RegistrationTicket { 6 | @PrimaryColumn(id()) 7 | public id: string; 8 | 9 | @Column("timestamp with time zone") 10 | public createdAt: Date; 11 | 12 | @Index({ unique: true }) 13 | @Column("varchar", { 14 | length: 64, 15 | }) 16 | public code: string; 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/src/models/entities/relay.ts: -------------------------------------------------------------------------------- 1 | import { PrimaryColumn, Entity, Index, Column } from "typeorm"; 2 | import { id } from "../id.js"; 3 | 4 | @Entity() 5 | export class Relay { 6 | @PrimaryColumn(id()) 7 | public id: string; 8 | 9 | @Index({ unique: true }) 10 | @Column("varchar", { 11 | length: 512, 12 | nullable: false, 13 | }) 14 | public inbox: string; 15 | 16 | @Column("enum", { 17 | enum: ["requesting", "accepted", "rejected"], 18 | }) 19 | public status: "requesting" | "accepted" | "rejected"; 20 | } 21 | -------------------------------------------------------------------------------- /packages/backend/src/models/entities/used-username.ts: -------------------------------------------------------------------------------- 1 | import { PrimaryColumn, Entity, Column } from "typeorm"; 2 | 3 | @Entity() 4 | export class UsedUsername { 5 | @PrimaryColumn("varchar", { 6 | length: 128, 7 | }) 8 | public username: string; 9 | 10 | @Column("timestamp with time zone") 11 | public createdAt: Date; 12 | 13 | constructor(data: Partial) { 14 | if (data == null) return; 15 | 16 | for (const [k, v] of Object.entries(data)) { 17 | (this as any)[k] = v; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/backend/src/models/id.ts: -------------------------------------------------------------------------------- 1 | export const id = () => ({ 2 | type: "varchar" as const, 3 | length: 32, 4 | }); 5 | -------------------------------------------------------------------------------- /packages/backend/src/models/repositories/antenna.ts: -------------------------------------------------------------------------------- 1 | import { db } from "@/db/postgre.js"; 2 | import { Antenna } from "@/models/entities/antenna.js"; 3 | import { 4 | NativeAntennaSchema, 5 | nativePackAntennaById, 6 | } from "native-utils/built/index.js"; 7 | 8 | export const AntennaRepository = db.getRepository(Antenna).extend({ 9 | async pack(src: Antenna["id"] | Antenna): Promise { 10 | const id = typeof src === "object" ? src.id : src; 11 | 12 | return await nativePackAntennaById(id); 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /packages/backend/src/models/repositories/relay.ts: -------------------------------------------------------------------------------- 1 | import { db } from "@/db/postgre.js"; 2 | import { Relay } from "@/models/entities/relay.js"; 3 | 4 | export const RelayRepository = db.getRepository(Relay).extend({}); 5 | -------------------------------------------------------------------------------- /packages/backend/src/models/repositories/signin.ts: -------------------------------------------------------------------------------- 1 | import { db } from "@/db/postgre.js"; 2 | import { Signin } from "@/models/entities/signin.js"; 3 | 4 | export const SigninRepository = db.getRepository(Signin).extend({ 5 | async pack(src: Signin) { 6 | return src; 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/README.md: -------------------------------------------------------------------------------- 1 | # Prelude 2 | このディレクトリのコードはJavaScriptの表現能力を補うためのコードです。 3 | Misskey固有の処理とは独立したコードの集まりですが、Misskeyのコードを読みやすくすることを目的としています。 4 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/math.ts: -------------------------------------------------------------------------------- 1 | export function gcd(a: number, b: number): number { 2 | return b === 0 ? a : gcd(b, a % b); 3 | } 4 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/maybe.ts: -------------------------------------------------------------------------------- 1 | export interface IMaybe { 2 | isJust(): this is IJust; 3 | } 4 | 5 | export interface IJust extends IMaybe { 6 | get(): T; 7 | } 8 | 9 | export function just(value: T): IJust { 10 | return { 11 | isJust: () => true, 12 | get: () => value, 13 | }; 14 | } 15 | 16 | export function nothing(): IMaybe { 17 | return { 18 | isJust: () => false, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/relation.ts: -------------------------------------------------------------------------------- 1 | export type Predicate = (a: T) => boolean; 2 | 3 | export type Relation = (a: T, b: U) => boolean; 4 | 5 | export type EndoRelation = Relation; 6 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/string.ts: -------------------------------------------------------------------------------- 1 | export function concat(xs: string[]): string { 2 | return xs.join(""); 3 | } 4 | 5 | export function capitalize(s: string): string { 6 | return toUpperCase(s.charAt(0)) + toLowerCase(s.slice(1)); 7 | } 8 | 9 | export function toUpperCase(s: string): string { 10 | return s.toUpperCase(); 11 | } 12 | 13 | export function toLowerCase(s: string): string { 14 | return s.toLowerCase(); 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/src/prelude/symbol.ts: -------------------------------------------------------------------------------- 1 | export const fallback = Symbol("fallback"); 2 | -------------------------------------------------------------------------------- /packages/backend/src/queue/logger.ts: -------------------------------------------------------------------------------- 1 | import Logger from "@/services/logger.js"; 2 | 3 | export const queueLogger = new Logger("queue", "orange"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/queue/processors/background/index.ts: -------------------------------------------------------------------------------- 1 | import type Bull from "bull"; 2 | import indexAllNotes from "./index-all-notes.js"; 3 | 4 | const jobs = { 5 | indexAllNotes, 6 | } as Record>>; 7 | 8 | export default function (q: Bull.Queue) { 9 | for (const [k, v] of Object.entries(jobs)) { 10 | q.process(k, 16, v); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/backend/src/queue/processors/object-storage/delete-file.ts: -------------------------------------------------------------------------------- 1 | import type { ObjectStorageFileJobData } from "@/queue/types.js"; 2 | import type Bull from "bull"; 3 | import { deleteObjectStorageFile } from "@/services/drive/delete-file.js"; 4 | 5 | export default async (job: Bull.Job) => { 6 | const key: string = job.data.key; 7 | 8 | await deleteObjectStorageFile(key); 9 | 10 | return "Success"; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/backend/src/queue/processors/tumblr/index.ts: -------------------------------------------------------------------------------- 1 | import type Bull from "bull"; 2 | import { fetchTumblrFeeds } from "./fetch.js"; 3 | 4 | const jobs = { 5 | fetchTumblrFeeds, 6 | } as Record>>; 7 | 8 | export default function (q: Bull.Queue) { 9 | for (const [k, v] of Object.entries(jobs)) { 10 | q.process(k, 1, v); 11 | } 12 | } -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/logger.ts: -------------------------------------------------------------------------------- 1 | import { remoteLogger } from "../logger.js"; 2 | 3 | export const apLogger = remoteLogger.createSubLogger("ap", "magenta"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/misc/get-note-html.ts: -------------------------------------------------------------------------------- 1 | import * as mfm from "mfm-js"; 2 | import type { Note } from "@/models/entities/note.js"; 3 | import { toHtml } from "../../../mfm/to-html.js"; 4 | 5 | export default function (note: Note) { 6 | if (!note.text) return ""; 7 | return toHtml(mfm.parse(note.text), JSON.parse(note.mentionedRemoteUsers)); 8 | } 9 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/misc/html-to-mfm.ts: -------------------------------------------------------------------------------- 1 | import type { IObject } from "../type.js"; 2 | import { extractApHashtagObjects } from "../models/tag.js"; 3 | import { fromHtml } from "../../../mfm/from-html.js"; 4 | 5 | export function htmlToMfm(html: string, tag?: IObject | IObject[]) { 6 | const hashtagNames = extractApHashtagObjects(tag) 7 | .map((x) => x.name) 8 | .filter((x): x is string => x != null); 9 | 10 | return fromHtml(html, hashtagNames); 11 | } 12 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/models/icon.ts: -------------------------------------------------------------------------------- 1 | export type IIcon = { 2 | type: string; 3 | mediaType?: string; 4 | url?: string; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/models/identifier.ts: -------------------------------------------------------------------------------- 1 | export type IIdentifier = { 2 | type: string; 3 | name: string; 4 | value: string; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/accept.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { User } from "@/models/entities/user.js"; 3 | 4 | export default (object: any, user: { id: User["id"]; host: null }) => ({ 5 | type: "Accept", 6 | actor: `${config.url}/users/${user.id}`, 7 | object, 8 | }); 9 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/add.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { ILocalUser } from "@/models/entities/user.js"; 3 | 4 | export default (user: ILocalUser, target: any, object: any) => ({ 5 | type: "Add", 6 | actor: `${config.url}/users/${user.id}`, 7 | target, 8 | object, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/delete.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { User } from "@/models/entities/user.js"; 3 | 4 | export default (object: any, user: { id: User["id"]; host: null }) => ({ 5 | type: "Delete", 6 | actor: `${config.url}/users/${user.id}`, 7 | object, 8 | published: new Date().toISOString(), 9 | }); 10 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/document.ts: -------------------------------------------------------------------------------- 1 | import type { DriveFile } from "@/models/entities/drive-file.js"; 2 | import { DriveFiles } from "@/models/index.js"; 3 | 4 | export default (file: DriveFile) => ({ 5 | type: "Document", 6 | mediaType: file.type, 7 | url: DriveFiles.getPublicUrl(file), 8 | name: file.comment, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/hashtag.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | 3 | export default (tag: string) => ({ 4 | type: "Hashtag", 5 | href: `${config.url}/tags/${encodeURIComponent(tag)}`, 6 | name: `#${tag}`, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/image.ts: -------------------------------------------------------------------------------- 1 | import type { DriveFile } from "@/models/entities/drive-file.js"; 2 | import { DriveFiles } from "@/models/index.js"; 3 | 4 | export default (file: DriveFile) => ({ 5 | type: "Image", 6 | url: DriveFiles.getPublicUrl(file), 7 | sensitive: file.isSensitive, 8 | name: file.comment, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/read.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { User } from "@/models/entities/user.js"; 3 | import type { MessagingMessage } from "@/models/entities/messaging-message.js"; 4 | 5 | export const renderReadActivity = ( 6 | user: { id: User["id"] }, 7 | message: MessagingMessage, 8 | ) => ({ 9 | type: "Read", 10 | actor: `${config.url}/users/${user.id}`, 11 | object: message.uri, 12 | }); 13 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/reject.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { User } from "@/models/entities/user.js"; 3 | 4 | export default (object: any, user: { id: User["id"] }) => ({ 5 | type: "Reject", 6 | actor: `${config.url}/users/${user.id}`, 7 | object, 8 | }); 9 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/remove.ts: -------------------------------------------------------------------------------- 1 | import config from "@/config/index.js"; 2 | import type { User } from "@/models/entities/user.js"; 3 | 4 | export default (user: { id: User["id"] }, target: any, object: any) => ({ 5 | type: "Remove", 6 | actor: `${config.url}/users/${user.id}`, 7 | target, 8 | object, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/backend/src/remote/activitypub/renderer/tombstone.ts: -------------------------------------------------------------------------------- 1 | export default (id: string) => ({ 2 | id, 3 | type: "Tombstone", 4 | }); 5 | -------------------------------------------------------------------------------- /packages/backend/src/remote/logger.ts: -------------------------------------------------------------------------------- 1 | import Logger from "@/services/logger.js"; 2 | 3 | export const remoteLogger = new Logger("remote", "cyan"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/common/generate-native-user-token.ts: -------------------------------------------------------------------------------- 1 | import { secureRndstr } from "@/misc/secure-rndstr.js"; 2 | 3 | export default () => secureRndstr(16, true); 4 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/common/is-native-token.ts: -------------------------------------------------------------------------------- 1 | export default (token: string) => token.length === 16; 2 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts: -------------------------------------------------------------------------------- 1 | import define from "../../../define.js"; 2 | import { createCleanRemoteFilesJob } from "@/queue/index.js"; 3 | 4 | export const meta = { 5 | tags: ["admin"], 6 | 7 | requireCredential: true, 8 | requireModerator: true, 9 | } as const; 10 | 11 | export const paramDef = { 12 | type: "object", 13 | properties: {}, 14 | required: [], 15 | } as const; 16 | 17 | export default define(meta, paramDef, async (ps, me) => { 18 | createCleanRemoteFilesJob(); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/logger.ts: -------------------------------------------------------------------------------- 1 | import Logger from "@/services/logger.js"; 2 | 3 | export const apiLogger = new Logger("api"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/stream/channels/admin.ts: -------------------------------------------------------------------------------- 1 | import Channel from "../channel.js"; 2 | 3 | export default class extends Channel { 4 | public readonly chName = "admin"; 5 | public static shouldShare = true; 6 | public static requireCredential = true; 7 | 8 | public async init(params: any) { 9 | // Subscribe admin stream 10 | this.subscriber.on(`adminStream:${this.user!.id}`, (data) => { 11 | this.send(data); 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/stream/channels/drive.ts: -------------------------------------------------------------------------------- 1 | import Channel from "../channel.js"; 2 | 3 | export default class extends Channel { 4 | public readonly chName = "drive"; 5 | public static shouldShare = true; 6 | public static requireCredential = true; 7 | 8 | public async init(params: any) { 9 | // Subscribe drive stream 10 | this.subscriber.on(`driveStream:${this.user!.id}`, (data) => { 11 | this.send(data); 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/server/api/stream/channels/messaging-index.ts: -------------------------------------------------------------------------------- 1 | import Channel from "../channel.js"; 2 | 3 | export default class extends Channel { 4 | public readonly chName = "messagingIndex"; 5 | public static shouldShare = true; 6 | public static requireCredential = true; 7 | 8 | public async init(params: any) { 9 | // Subscribe messaging index stream 10 | this.subscriber.on(`messagingIndexStream:${this.user!.id}`, (data) => { 11 | this.send(data); 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/bad-egg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/bad-egg.png -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/cache-expired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/cache-expired.png -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/dummy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/dummy.png -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/not-an-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/not-an-image.png -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/thumbnail-not-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/thumbnail-not-available.png -------------------------------------------------------------------------------- /packages/backend/src/server/file/assets/tombstone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/src/server/file/assets/tombstone.png -------------------------------------------------------------------------------- /packages/backend/src/server/web/views/bios.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | 5 | head 6 | meta(charset='utf-8') 7 | meta(name='application-name' content='Firefish') 8 | meta(name='viewport' content='width=device-width, initial-scale=1.0') 9 | title Firefish Repair Tool 10 | style 11 | include ../bios.css 12 | script 13 | include ../bios.js 14 | 15 | body 16 | header 17 | h1 Firefish Repair Tool v#{version} 18 | main 19 | div.tabs 20 | button#ls Edit local storage 21 | div#content 22 | -------------------------------------------------------------------------------- /packages/backend/src/server/web/views/cli.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | 3 | html 4 | 5 | head 6 | meta(charset='utf-8') 7 | meta(name='application-name' content='Firefish') 8 | meta(name='viewport' content='width=device-width, initial-scale=1.0') 9 | title Firefish Cli 10 | style 11 | include ../cli.css 12 | script 13 | include ../cli.js 14 | 15 | body 16 | header 17 | h1 Firefish Simple Client v#{version} 18 | main 19 | div#form 20 | textarea#text 21 | br 22 | button#submit Post 23 | div#tl 24 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/ap-request.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "apRequest"; 4 | 5 | export const schema = { 6 | deliverFailed: {}, 7 | deliverSucceeded: {}, 8 | inboxReceived: {}, 9 | } as const; 10 | 11 | export const entity = Chart.schemaToEntity(name, schema); 12 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/drive.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "drive"; 4 | 5 | export const schema = { 6 | "local.incCount": {}, 7 | "local.incSize": {}, // in kilobyte 8 | "local.decCount": {}, 9 | "local.decSize": {}, // in kilobyte 10 | "remote.incCount": {}, 11 | "remote.incSize": {}, // in kilobyte 12 | "remote.decCount": {}, 13 | "remote.decSize": {}, // in kilobyte 14 | } as const; 15 | 16 | export const entity = Chart.schemaToEntity(name, schema); 17 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/hashtag.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "hashtag"; 4 | 5 | export const schema = { 6 | "local.users": { uniqueIncrement: true }, 7 | "remote.users": { uniqueIncrement: true }, 8 | } as const; 9 | 10 | export const entity = Chart.schemaToEntity(name, schema, true); 11 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/per-user-drive.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "perUserDrive"; 4 | 5 | export const schema = { 6 | totalCount: { accumulate: true }, 7 | totalSize: { accumulate: true }, // in kilobyte 8 | incCount: { range: "small" }, 9 | incSize: {}, // in kilobyte 10 | decCount: { range: "small" }, 11 | decSize: {}, // in kilobyte 12 | } as const; 13 | 14 | export const entity = Chart.schemaToEntity(name, schema, true); 15 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/per-user-notes.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "perUserNotes"; 4 | 5 | export const schema = { 6 | total: { accumulate: true }, 7 | inc: { range: "small" }, 8 | dec: { range: "small" }, 9 | "diffs.normal": { range: "small" }, 10 | "diffs.reply": { range: "small" }, 11 | "diffs.renote": { range: "small" }, 12 | "diffs.withFile": { range: "small" }, 13 | } as const; 14 | 15 | export const entity = Chart.schemaToEntity(name, schema, true); 16 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/per-user-reactions.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "perUserReaction"; 4 | 5 | export const schema = { 6 | "local.count": { range: "small" }, 7 | "remote.count": { range: "small" }, 8 | } as const; 9 | 10 | export const entity = Chart.schemaToEntity(name, schema, true); 11 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/test-grouped.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "testGrouped"; 4 | 5 | export const schema = { 6 | "foo.total": { accumulate: true }, 7 | "foo.inc": {}, 8 | "foo.dec": {}, 9 | } as const; 10 | 11 | export const entity = Chart.schemaToEntity(name, schema, true); 12 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/test-intersection.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "testIntersection"; 4 | 5 | export const schema = { 6 | a: { uniqueIncrement: true }, 7 | b: { uniqueIncrement: true }, 8 | aAndB: { intersection: ["a", "b"] }, 9 | } as const; 10 | 11 | export const entity = Chart.schemaToEntity(name, schema); 12 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/test-unique.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "testUnique"; 4 | 5 | export const schema = { 6 | foo: { uniqueIncrement: true }, 7 | } as const; 8 | 9 | export const entity = Chart.schemaToEntity(name, schema); 10 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/test.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "test"; 4 | 5 | export const schema = { 6 | "foo.total": { accumulate: true }, 7 | "foo.inc": {}, 8 | "foo.dec": {}, 9 | } as const; 10 | 11 | export const entity = Chart.schemaToEntity(name, schema); 12 | -------------------------------------------------------------------------------- /packages/backend/src/services/chart/charts/entities/users.ts: -------------------------------------------------------------------------------- 1 | import Chart from "../../core.js"; 2 | 3 | export const name = "users"; 4 | 5 | export const schema = { 6 | "local.total": { accumulate: true }, 7 | "local.inc": { range: "small" }, 8 | "local.dec": { range: "small" }, 9 | "remote.total": { accumulate: true }, 10 | "remote.inc": { range: "small" }, 11 | "remote.dec": { range: "small" }, 12 | } as const; 13 | 14 | export const entity = Chart.schemaToEntity(name, schema); 15 | -------------------------------------------------------------------------------- /packages/backend/src/services/drive/logger.ts: -------------------------------------------------------------------------------- 1 | import Logger from "../logger.js"; 2 | 3 | export const driveLogger = new Logger("drive", "blue"); 4 | -------------------------------------------------------------------------------- /packages/backend/src/services/insert-moderation-log.ts: -------------------------------------------------------------------------------- 1 | import { ModerationLogs } from "@/models/index.js"; 2 | import { genId } from "@/misc/gen-id.js"; 3 | import type { User } from "@/models/entities/user.js"; 4 | 5 | export async function insertModerationLog( 6 | moderator: { id: User["id"] }, 7 | type: string, 8 | info?: Record, 9 | ) { 10 | await ModerationLogs.insert({ 11 | id: genId(), 12 | createdAt: new Date(), 13 | userId: moderator.id, 14 | type: type, 15 | info: info || {}, 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/backend/src/services/note/unwatch.ts: -------------------------------------------------------------------------------- 1 | import type { User } from "@/models/entities/user.js"; 2 | import { NoteWatchings } from "@/models/index.js"; 3 | import type { Note } from "@/models/entities/note.js"; 4 | 5 | export default async (me: User["id"], note: Note) => { 6 | await NoteWatchings.delete({ 7 | noteId: note.id, 8 | userId: me, 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/backend/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | redistest: 5 | image: redis:6 6 | ports: 7 | - "127.0.0.1:56312:6379" 8 | 9 | dbtest: 10 | image: postgres:13 11 | ports: 12 | - "127.0.0.1:54312:5432" 13 | environment: 14 | POSTGRES_DB: "test-misskey" 15 | POSTGRES_HOST_AUTH_METHOD: trust 16 | -------------------------------------------------------------------------------- /packages/backend/test/prelude/maybe.ts: -------------------------------------------------------------------------------- 1 | import * as assert from "assert"; 2 | import { just, nothing } from "../../src/prelude/maybe.js"; 3 | 4 | describe("just", () => { 5 | it("has a value", () => { 6 | assert.deepStrictEqual(just(3).isJust(), true); 7 | }); 8 | 9 | it("has the inverse called get", () => { 10 | assert.deepStrictEqual(just(3).get(), 3); 11 | }); 12 | }); 13 | 14 | describe("nothing", () => { 15 | it("has no value", () => { 16 | assert.deepStrictEqual(nothing().isJust(), false); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/backend/test/prelude/url.ts: -------------------------------------------------------------------------------- 1 | import * as assert from "assert"; 2 | import { query } from "../../src/prelude/url.js"; 3 | 4 | describe("url", () => { 5 | it("query", () => { 6 | const s = query({ 7 | foo: "ふぅ", 8 | bar: "b a r", 9 | baz: undefined, 10 | }); 11 | assert.deepStrictEqual(s, "foo=%E3%81%B5%E3%81%85&bar=b%20a%20r"); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/backend/test/resources/25000x25000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/25000x25000.png -------------------------------------------------------------------------------- /packages/backend/test/resources/Lenna.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/Lenna.jpg -------------------------------------------------------------------------------- /packages/backend/test/resources/Lenna.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/Lenna.png -------------------------------------------------------------------------------- /packages/backend/test/resources/anime.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/anime.gif -------------------------------------------------------------------------------- /packages/backend/test/resources/anime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/anime.png -------------------------------------------------------------------------------- /packages/backend/test/resources/emptyfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/emptyfile -------------------------------------------------------------------------------- /packages/backend/test/resources/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/backend/test/resources/rotate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/rotate.jpg -------------------------------------------------------------------------------- /packages/backend/test/resources/with-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/backend/test/resources/with-alpha.png -------------------------------------------------------------------------------- /packages/backend/test/resources/with-xml-def.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@eslint-sets/vue3", "@eslint-sets/vue3-ts"], 3 | "plugins": ["file-progress", "prettier"], 4 | "rules": { 5 | "file-progress/activate": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true, 4 | "singleQuote": false, 5 | "vueIndentScriptAndStyle": false, 6 | "plugins": ["vue"], 7 | "overrides": [ 8 | { 9 | "files": "*.vue", 10 | "options": { 11 | "parser": "vue" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/client/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "path-intellisense.mappings": { 4 | "@": "${workspaceRoot}/packages/client/src/" 5 | }, 6 | "files.exclude": { 7 | "**/.git": true, 8 | "**/.svn": true, 9 | "**/.hg": true, 10 | "**/CVS": true, 11 | "**/.DS_Store": true, 12 | "**/Thumbs.db": true, 13 | "**/_client_dist_": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/client/@types/global.d.ts: -------------------------------------------------------------------------------- 1 | type FIXME = any; 2 | 3 | declare const _LANGS_: string[][]; 4 | declare const _VERSION_: string; 5 | declare const _ENV_: string; 6 | declare const _DEV_: boolean; 7 | declare const _PERF_PREFIX_: string; 8 | declare const _DATA_TRANSFER_DRIVE_FILE_: string; 9 | declare const _DATA_TRANSFER_DRIVE_FOLDER_: string; 10 | declare const _DATA_TRANSFER_DECK_COLUMN_: string; 11 | -------------------------------------------------------------------------------- /packages/client/@types/theme.d.ts: -------------------------------------------------------------------------------- 1 | declare module "@/themes/*.json5" { 2 | import { Theme } from "@/scripts/theme"; 3 | 4 | const theme: Theme; 5 | 6 | export default theme; 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/@types/vue.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/assets/about-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/about-icon.png -------------------------------------------------------------------------------- /packages/client/assets/dagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/dagger.png -------------------------------------------------------------------------------- /packages/client/assets/dagger2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/dagger2.png -------------------------------------------------------------------------------- /packages/client/assets/dummy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/dummy.png -------------------------------------------------------------------------------- /packages/client/assets/dummy_original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/dummy_original.png -------------------------------------------------------------------------------- /packages/client/assets/label-red.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/assets/label.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/assets/misskey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/misskey.png -------------------------------------------------------------------------------- /packages/client/assets/npf-bold.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/npf-italic.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/npf-read-more.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /packages/client/assets/posts-quote.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/reblog-compact.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/reply-empty.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/snowman.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/text-indent.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/text-list-unordered.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/assets/tumblrFollow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/packages/client/assets/tumblrFollow.gif -------------------------------------------------------------------------------- /packages/client/src/components/MkCode.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | -------------------------------------------------------------------------------- /packages/client/src/components/MkFileTypeIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | -------------------------------------------------------------------------------- /packages/client/src/components/MkObjectView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /packages/client/src/components/MkReactionIcon.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/bold.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/bullet-list.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/caret.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/italic.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/logo.image.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/quote.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/reblog.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/src/components/icons/warning.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/client/src/directives/focus.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | mounted: (el) => el.focus(), 3 | }; 4 | -------------------------------------------------------------------------------- /packages/client/src/directives/ripple.ts: -------------------------------------------------------------------------------- 1 | import Ripple from "@/components/MkRipple.vue"; 2 | import { popup } from "@/os"; 3 | 4 | export default { 5 | mounted(el, binding, vn) { 6 | // 明示的に false であればバインドしない 7 | if (binding.value === false) return; 8 | 9 | el.addEventListener("click", () => { 10 | const rect = el.getBoundingClientRect(); 11 | 12 | const x = rect.left + el.offsetWidth / 2; 13 | const y = rect.top + el.offsetHeight / 2; 14 | 15 | popup(Ripple, { x, y }, {}, "end"); 16 | }); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/client/src/events.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "eventemitter3"; 2 | 3 | // TODO: 型付け 4 | export const globalEvents = new EventEmitter(); 5 | -------------------------------------------------------------------------------- /packages/client/src/filters.ts: -------------------------------------------------------------------------------- 1 | const filters = { 2 | onlyText(content) { 3 | let regex = /(<([^>]+)>)/gi; 4 | return content.replace(regex, ""); 5 | }, 6 | }; 7 | export default filters; 8 | -------------------------------------------------------------------------------- /packages/client/src/filters/bytes.ts: -------------------------------------------------------------------------------- 1 | export default (v, digits = 0) => { 2 | if (v == null) return "?"; 3 | const sizes = ["B", "KB", "MB", "GB", "TB"]; 4 | if (v === 0) return "0"; 5 | const isMinus = v < 0; 6 | if (isMinus) v = -v; 7 | const i = Math.floor(Math.log(v) / Math.log(1024)); 8 | return ( 9 | (isMinus ? "-" : "") + 10 | (v / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, "") + 11 | sizes[i] 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/client/src/filters/note.ts: -------------------------------------------------------------------------------- 1 | export const notePage = (note) => { 2 | return `/notes/${note.id}`; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/client/src/filters/number.ts: -------------------------------------------------------------------------------- 1 | export default (n) => (n == null ? "N/A" : n.toLocaleString()); 2 | -------------------------------------------------------------------------------- /packages/client/src/filters/user.ts: -------------------------------------------------------------------------------- 1 | import * as misskey from "firefish-js"; 2 | import * as Acct from "firefish-js/built/acct"; 3 | import { url } from "@/config"; 4 | 5 | export const acct = (user: misskey.Acct) => { 6 | return Acct.toString(user); 7 | }; 8 | 9 | export const userName = (user: misskey.entities.User) => { 10 | return user.name || user.username; 11 | }; 12 | 13 | export const userPage = (user: misskey.Acct, path?, absolute = false) => { 14 | return `${absolute ? url : ""}/@${acct(user)}${path ? `/${path}` : ""}`; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/client/src/helpers/features/index.ts: -------------------------------------------------------------------------------- 1 | export const getFeatures = () => { 2 | const experimentalFeatures = localStorage.getItem('experimental'); 3 | if( experimentalFeatures ) { 4 | return JSON.parse( experimentalFeatures ) 5 | } 6 | return {} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /packages/client/src/i18n.ts: -------------------------------------------------------------------------------- 1 | import { markRaw } from "vue"; 2 | import { locale } from "@/config"; 3 | import { I18n } from "@/scripts/i18n"; 4 | 5 | export const i18n = markRaw(new I18n(locale)); 6 | 7 | // このファイルに書きたくないけどここに書かないと何故かVeturが認識しない 8 | declare module "@vue/runtime-core" { 9 | interface ComponentCustomProperties { 10 | $t: typeof i18n["t"]; 11 | $ts: typeof i18n["locale"]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/client/src/pages/_empty_.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /packages/client/src/pages/_loading_.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/client/src/scripts/color.ts: -------------------------------------------------------------------------------- 1 | export const alpha = (hex: string, a: number): string => { 2 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)!; 3 | const r = parseInt(result[1], 16); 4 | const g = parseInt(result[2], 16); 5 | const b = parseInt(result[3], 16); 6 | return `rgba(${r}, ${g}, ${b}, ${a})`; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/client/src/scripts/contains.ts: -------------------------------------------------------------------------------- 1 | export default (parent, child, checkSame = true) => { 2 | if (checkSame && parent === child) return true; 3 | let node = child.parentNode; 4 | while (node) { 5 | if (node === parent) return true; 6 | node = node.parentNode; 7 | } 8 | return false; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/client/src/scripts/device-kind.ts: -------------------------------------------------------------------------------- 1 | import { defaultStore } from "@/store"; 2 | 3 | const ua = navigator.userAgent.toLowerCase(); 4 | const isTablet = 5 | /ipad/.test(ua) || 6 | (/mobile|iphone|android/.test(ua) && window.innerWidth > 700); 7 | const isSmartphone = !isTablet && /mobile|iphone|android/.test(ua); 8 | 9 | export const deviceKind = defaultStore.state.overridedDeviceKind 10 | ? defaultStore.state.overridedDeviceKind 11 | : isSmartphone 12 | ? "smartphone" 13 | : isTablet 14 | ? "tablet" 15 | : "desktop"; 16 | -------------------------------------------------------------------------------- /packages/client/src/scripts/extract-avg-color-from-blurhash.ts: -------------------------------------------------------------------------------- 1 | import { getBlurHashAverageColor } from "fast-blurhash"; 2 | 3 | function rgbToHex(rgb: number[]): string { 4 | return `#${rgb 5 | .map((x) => { 6 | const hex = x.toString(16); 7 | return hex.length === 1 ? `0${hex}` : hex; 8 | }) 9 | .join("")}`; 10 | } 11 | 12 | export function extractAvgColorFromBlurhash(hash: string) { 13 | return typeof hash === "string" 14 | ? rgbToHex(getBlurHashAverageColor(hash)) 15 | : undefined; 16 | } 17 | -------------------------------------------------------------------------------- /packages/client/src/scripts/extract-mentions.ts: -------------------------------------------------------------------------------- 1 | // test is located in test/extract-mentions 2 | 3 | import * as mfm from "mfm-js"; 4 | 5 | export function extractMentions( 6 | nodes: mfm.MfmNode[], 7 | ): mfm.MfmMention["props"][] { 8 | // TODO: 重複を削除 9 | const mentionNodes = mfm.extract(nodes, (node) => node.type === "mention"); 10 | const mentions = mentionNodes.map((x) => x.props); 11 | 12 | return mentions; 13 | } 14 | -------------------------------------------------------------------------------- /packages/client/src/scripts/get-account-from-id.ts: -------------------------------------------------------------------------------- 1 | import { get } from "@/scripts/idb-proxy"; 2 | 3 | export async function getAccountFromId(id: string) { 4 | const accounts = (await get("accounts")) as { token: string; id: string }[]; 5 | if (!accounts) console.log("Accounts are not recorded"); 6 | return accounts.find((account) => account.id === id); 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/src/scripts/get-user-name.ts: -------------------------------------------------------------------------------- 1 | export default function (user: { 2 | name?: string | null; 3 | username: string; 4 | }): string { 5 | return user.name || user.username; 6 | } 7 | -------------------------------------------------------------------------------- /packages/client/src/scripts/initialize-sw.ts: -------------------------------------------------------------------------------- 1 | import { lang } from "@/config"; 2 | 3 | export async function initializeSw() { 4 | if (!("serviceWorker" in navigator)) return; 5 | 6 | navigator.serviceWorker.register("/sw.js", { scope: "/", type: "classic" }); 7 | navigator.serviceWorker.ready.then((registration) => { 8 | registration.active?.postMessage({ 9 | msg: "initialize", 10 | lang, 11 | }); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /packages/client/src/scripts/intl-const.ts: -------------------------------------------------------------------------------- 1 | import { lang } from "@/config"; 2 | 3 | export const versatileLang = (lang ?? "ja-JP").replace("ja-KS", "ja-JP"); 4 | export const dateTimeFormat = new Intl.DateTimeFormat(versatileLang, { 5 | year: "numeric", 6 | month: "numeric", 7 | day: "numeric", 8 | hour: "numeric", 9 | minute: "numeric", 10 | second: "numeric", 11 | }); 12 | export const numberFormat = new Intl.NumberFormat(versatileLang); 13 | -------------------------------------------------------------------------------- /packages/client/src/scripts/is-device-darkmode.ts: -------------------------------------------------------------------------------- 1 | export function isDeviceDarkmode() { 2 | return window.matchMedia("(prefers-color-scheme: dark)").matches; 3 | } 4 | -------------------------------------------------------------------------------- /packages/client/src/scripts/login-id.ts: -------------------------------------------------------------------------------- 1 | export function getUrlWithLoginId(url: string, loginId: string) { 2 | const u = new URL(url, origin); 3 | u.searchParams.append("loginId", loginId); 4 | return u.toString(); 5 | } 6 | 7 | export function getUrlWithoutLoginId(url: string) { 8 | const u = new URL(url); 9 | u.searchParams.delete("loginId"); 10 | return u.toString(); 11 | } 12 | -------------------------------------------------------------------------------- /packages/client/src/scripts/mfm-tags.ts: -------------------------------------------------------------------------------- 1 | export const MFM_TAGS = [ 2 | "tada", 3 | "jelly", 4 | "twitch", 5 | "shake", 6 | "spin", 7 | "jump", 8 | "bounce", 9 | "flip", 10 | "x2", 11 | "x3", 12 | "x4", 13 | "scale", 14 | "position", 15 | "crop", 16 | "fg", 17 | "bg", 18 | "font", 19 | "blur", 20 | "rainbow", 21 | "sparkle", 22 | "rotate", 23 | "fade", 24 | ]; 25 | -------------------------------------------------------------------------------- /packages/client/src/scripts/reduced-motion.ts: -------------------------------------------------------------------------------- 1 | export function reducedMotion(): boolean { 2 | return window.matchMedia("(prefers-reduced-motion: reduce)").matches; 3 | } 4 | -------------------------------------------------------------------------------- /packages/client/src/scripts/safe-uri-decode.ts: -------------------------------------------------------------------------------- 1 | export function safeURIDecode(str: string): string { 2 | try { 3 | return decodeURIComponent(str); 4 | } catch { 5 | return str; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/src/scripts/share-available.ts: -------------------------------------------------------------------------------- 1 | export function shareAvailable(): boolean { 2 | if (navigator.share) { 3 | return true; 4 | } 5 | return false; 6 | } 7 | -------------------------------------------------------------------------------- /packages/client/src/scripts/twemoji-base.ts: -------------------------------------------------------------------------------- 1 | export const twemojiSvgBase = "/twemoji"; 2 | 3 | export function char2fileName(char: string): string { 4 | let codes = Array.from(char).map((x) => x.codePointAt(0)?.toString(16)); 5 | if (!codes.includes("200d")) codes = codes.filter((x) => x !== "fe0f"); 6 | codes = codes.filter((x) => x?.length); 7 | return codes.join("-"); 8 | } 9 | 10 | export function char2filePath(char: string): string { 11 | return `${twemojiSvgBase}/${char2fileName(char)}.svg`; 12 | } 13 | -------------------------------------------------------------------------------- /packages/client/src/scripts/unison-reload.ts: -------------------------------------------------------------------------------- 1 | // SafariがBroadcastChannel未実装なのでライブラリを使う 2 | import { BroadcastChannel } from "broadcast-channel"; 3 | 4 | export const reloadChannel = new BroadcastChannel("reload"); 5 | 6 | // BroadcastChannelを用いて、クライアントが一斉にreloadするようにします。 7 | export function unisonReload(path?: string) { 8 | if (path !== undefined) { 9 | reloadChannel.postMessage(path); 10 | location.href = path; 11 | } else { 12 | reloadChannel.postMessage(null); 13 | location.reload(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/client/src/special-events/ides/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | isActive: () => { 3 | const today = new Date(); 4 | return today.getMonth() === 2 && today.getDate() >= 13 && today.getDate() <= 15 ; 5 | } 6 | } -------------------------------------------------------------------------------- /packages/client/src/special-events/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /packages/client/src/themes/d-cherry.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: '679b3b87-a4e9-4789-8696-b56c15cc33b0', 3 | 4 | name: 'Mi Cherry Dark', 5 | author: 'syuilo', 6 | 7 | base: 'dark', 8 | 9 | props: { 10 | accent: 'rgb(255, 89, 117)', 11 | bg: 'rgb(28, 28, 37)', 12 | fg: 'rgb(236, 239, 244)', 13 | panel: 'rgb(35, 35, 47)', 14 | renote: '@accent', 15 | link: '@accent', 16 | mention: '@accent', 17 | hashtag: '@accent', 18 | divider: 'rgb(63, 63, 80)', 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /packages/client/src/themes/d-ice.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: '66e7e5a9-cd43-42cd-837d-12f47841fa34', 3 | 4 | name: 'Mi Ice Dark', 5 | author: 'syuilo', 6 | 7 | base: 'dark', 8 | 9 | props: { 10 | accent: '#47BFE8', 11 | bg: '#212526', 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /packages/client/src/themes/l-coffee.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: '6ed80faa-74f0-42c2-98e4-a64d9e138eab', 3 | 4 | name: 'Mi Coffee Light', 5 | author: 'syuilo', 6 | 7 | base: 'light', 8 | 9 | props: { 10 | accent: '#9f8989', 11 | bg: '#f5f3f3', 12 | fg: '#7f6666', 13 | panel: '#fff', 14 | divider: 'rgba(87, 68, 68, 0.1)', 15 | renote: 'rgb(160, 172, 125)', 16 | link: 'rgb(137, 151, 159)', 17 | mention: '@accent', 18 | mentionMe: 'rgb(170, 149, 98)', 19 | hashtag: '@accent', 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /packages/client/src/themes/l-light.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: '4eea646f-7afa-4645-83e9-83af0333cd37', 3 | 4 | name: 'Mi Light', 5 | author: 'syuilo', 6 | desc: 'Default light theme', 7 | 8 | base: 'light', 9 | 10 | props: { 11 | bg: '#f9f9f9', 12 | fg: '#676767', 13 | divider: '#e8e8e8', 14 | header: ':alpha<0.7<@panel', 15 | navBg: '#fff', 16 | panel: '#fff', 17 | panelHeaderDivider: '@divider', 18 | mentionMe: 'rgb(0, 179, 70)', 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /packages/client/src/themes/l-rainy.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: 'a58a0abb-ff8c-476a-8dec-0ad7837e7e96', 3 | 4 | name: 'Mi Rainy Light', 5 | author: 'syuilo', 6 | 7 | base: 'light', 8 | 9 | props: { 10 | accent: '#5db0da', 11 | bg: 'rgb(246 248 249)', 12 | fg: '#636b71', 13 | panel: '#fff', 14 | divider: 'rgb(230 233 234)', 15 | panelHeaderDivider: '@divider', 16 | renote: '@accent', 17 | link: '@accent', 18 | mention: '@accent', 19 | hashtag: '@accent', 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /packages/client/src/themes/l-sushi.json5: -------------------------------------------------------------------------------- 1 | { 2 | id: '213273e5-7d20-d5f0-6e36-1b6a4f67115c', 3 | 4 | name: 'Mi Sushi Light', 5 | author: 'syuilo', 6 | 7 | base: 'light', 8 | 9 | props: { 10 | accent: '#e36749', 11 | bg: '#f0eee9', 12 | fg: '#5f5f5f', 13 | renote: '@accent', 14 | link: '@accent', 15 | mention: '@accent', 16 | hashtag: '#229e82', 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /packages/client/src/ui/visitor.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | -------------------------------------------------------------------------------- /packages/firefish-js/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 2 6 | charset = utf-8 7 | insert_final_newline = true 8 | -------------------------------------------------------------------------------- /packages/firefish-js/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript", 6 | "dynamicImport": true, 7 | "decorators": true 8 | }, 9 | "transform": { 10 | "legacyDecorator": true, 11 | "decoratorMetadata": true 12 | }, 13 | "target": "es2022" 14 | }, 15 | "minify": false, 16 | "module": { 17 | "type": "commonjs", 18 | "strict": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/firefish-js/README.md: -------------------------------------------------------------------------------- 1 | # Firefish.js 2 | 3 | Fork of Misskey.js for Firefish 4 | 5 | https://www.npmjs.com/package/firefish-js 6 | 7 | To fully build, run `pnpm i && pnpm run render`. 8 | 9 | ![Parody of the Javascript logo with "CK" instead of "JS"](https://codeberg.org/repo-avatars/80771-4d86135f67b9a460cdd1be9e91648e5f) 10 | -------------------------------------------------------------------------------- /packages/firefish-js/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | token: d55e1270-f20a-4727-aa05-2bd57793315a 3 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.acct.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [Acct](./firefish-js.acct.md) 4 | 5 | ## Acct type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type Acct = { 11 | username: string; 12 | host: string | null; 13 | }; 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.api.apiclient.credential.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [api](./firefish-js.api.md) > [APIClient](./firefish-js.api.apiclient.md) > [credential](./firefish-js.api.apiclient.credential.md) 4 | 5 | ## api.APIClient.credential property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | credential: string | null | undefined; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.api.apiclient.fetch.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [api](./firefish-js.api.md) > [APIClient](./firefish-js.api.apiclient.md) > [fetch](./firefish-js.api.apiclient.fetch.md) 4 | 5 | ## api.APIClient.fetch property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | fetch: FetchLike; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.api.apiclient.origin.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [api](./firefish-js.api.md) > [APIClient](./firefish-js.api.apiclient.md) > [origin](./firefish-js.api.apiclient.origin.md) 4 | 5 | ## api.APIClient.origin property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | origin: string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.channel.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [channel](./firefish-js.channelconnection.channel.md) 4 | 5 | ## ChannelConnection.channel property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | channel: string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.dispose.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [dispose](./firefish-js.channelconnection.dispose.md) 4 | 5 | ## ChannelConnection.dispose() method 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | abstract dispose(): void; 11 | ``` 12 | **Returns:** 13 | 14 | void 15 | 16 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.id.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [id](./firefish-js.channelconnection.id.md) 4 | 5 | ## ChannelConnection.id property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | abstract id: string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.incount.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [inCount](./firefish-js.channelconnection.incount.md) 4 | 5 | ## ChannelConnection.inCount property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | inCount: number; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.name.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [name](./firefish-js.channelconnection.name.md) 4 | 5 | ## ChannelConnection.name property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | name?: string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.outcount.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [outCount](./firefish-js.channelconnection.outcount.md) 4 | 5 | ## ChannelConnection.outCount property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | outCount: number; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.channelconnection.stream.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ChannelConnection](./firefish-js.channelconnection.md) > [stream](./firefish-js.channelconnection.stream.md) 4 | 5 | ## ChannelConnection.stream property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | protected stream: Stream; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.ad.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [Ad](./firefish-js.entities.ad.md) 4 | 5 | ## entities.Ad type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type Ad = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.app.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [App](./firefish-js.entities.app.md) 4 | 5 | ## entities.App type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type App = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.channel.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [Channel](./firefish-js.entities.channel.md) 4 | 5 | ## entities.Channel type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type Channel = { 11 | id: ID; 12 | }; 13 | ``` 14 | **References:** [ID](./firefish-js.entities.id.md) 15 | 16 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.clip.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [Clip](./firefish-js.entities.clip.md) 4 | 5 | ## entities.Clip type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type Clip = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.datestring.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [DateString](./firefish-js.entities.datestring.md) 4 | 5 | ## entities.DateString type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type DateString = string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.drivefolder.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [DriveFolder](./firefish-js.entities.drivefolder.md) 4 | 5 | ## entities.DriveFolder type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type DriveFolder = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.gallerypost.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [GalleryPost](./firefish-js.entities.gallerypost.md) 4 | 5 | ## entities.GalleryPost type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type GalleryPost = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.id.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [ID](./firefish-js.entities.id.md) 4 | 5 | ## entities.ID type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type ID = string; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.origintype.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [OriginType](./firefish-js.entities.origintype.md) 4 | 5 | ## entities.OriginType type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type OriginType = "combined" | "local" | "remote"; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.entities.usergroup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [entities](./firefish-js.entities.md) > [UserGroup](./firefish-js.entities.usergroup.md) 4 | 5 | ## entities.UserGroup type 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | export declare type UserGroup = TODO; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.ffvisibility.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [ffVisibility](./firefish-js.ffvisibility.md) 4 | 5 | ## ffVisibility variable 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | ffVisibility: readonly ["public", "followers", "private"] 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.mutednotereasons.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [mutedNoteReasons](./firefish-js.mutednotereasons.md) 4 | 5 | ## mutedNoteReasons variable 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | mutedNoteReasons: readonly [ 11 | "word", 12 | "manual", 13 | "spam", 14 | "other", 15 | ] 16 | ``` 17 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.notevisibilities.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [noteVisibilities](./firefish-js.notevisibilities.md) 4 | 5 | ## noteVisibilities variable 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | noteVisibilities: readonly [ 11 | "public", 12 | "home", 13 | "followers", 14 | "specified", 15 | ] 16 | ``` 17 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.permissions.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [permissions](./firefish-js.permissions.md) 4 | 5 | ## permissions variable 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | permissions: string[] 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.stream.close.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [Stream](./firefish-js.stream.md) > [close](./firefish-js.stream.close.md) 4 | 5 | ## Stream.close() method 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | close(): void; 11 | ``` 12 | **Returns:** 13 | 14 | void 15 | 16 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/firefish-js.stream.state.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) > [firefish-js](./firefish-js.md) > [Stream](./firefish-js.stream.md) > [state](./firefish-js.stream.state.md) 4 | 5 | ## Stream.state property 6 | 7 | **Signature:** 8 | 9 | ```typescript 10 | state: "initializing" | "reconnecting" | "connected"; 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/firefish-js/markdown/index.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [Home](./index.md) 4 | 5 | ## API Reference 6 | 7 | ## Packages 8 | 9 | | Package | Description | 10 | | --- | --- | 11 | | [firefish-js](./firefish-js.md) | | 12 | 13 | -------------------------------------------------------------------------------- /packages/firefish-js/src/acct.ts: -------------------------------------------------------------------------------- 1 | export type Acct = { 2 | username: string; 3 | host: string | null; 4 | }; 5 | 6 | export function parse(acct: string): Acct { 7 | if (acct.startsWith("@")) acct = acct.slice(1); 8 | const split = acct.split("@", 2); 9 | return { username: split[0], host: split[1] || null }; 10 | } 11 | 12 | export function toString(acct: Acct): string { 13 | return acct.host == null ? acct.username : `${acct.username}@${acct.host}`; 14 | } 15 | -------------------------------------------------------------------------------- /packages/megalodon/src/axios.d.ts: -------------------------------------------------------------------------------- 1 | declare module "axios/lib/adapters/http"; 2 | -------------------------------------------------------------------------------- /packages/megalodon/src/cancel.ts: -------------------------------------------------------------------------------- 1 | export class RequestCanceledError extends Error { 2 | public isCancel: boolean; 3 | 4 | constructor(msg: string) { 5 | super(msg); 6 | this.isCancel = true; 7 | Object.setPrototypeOf(this, RequestCanceledError); 8 | } 9 | } 10 | 11 | export const isCancel = (value: any): boolean => { 12 | return value && value.isCancel; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/megalodon/src/converter.ts: -------------------------------------------------------------------------------- 1 | import MisskeyAPI from "./misskey/api_client"; 2 | 3 | export default MisskeyAPI.Converter; 4 | -------------------------------------------------------------------------------- /packages/megalodon/src/default.ts: -------------------------------------------------------------------------------- 1 | export const NO_REDIRECT = "urn:ietf:wg:oauth:2.0:oob"; 2 | export const DEFAULT_SCOPE = ["read", "write", "follow"]; 3 | export const DEFAULT_UA = "megalodon"; 4 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/activity.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Activity = { 3 | week: string; 4 | statuses: string; 5 | logins: string; 6 | registrations: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/application.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Application = { 3 | name: string; 4 | website?: string | null; 5 | vapid_key?: string | null; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/async_attachment.ts: -------------------------------------------------------------------------------- 1 | /// 2 | namespace Entity { 3 | export type AsyncAttachment = { 4 | id: string; 5 | type: "unknown" | "image" | "gifv" | "video" | "audio"; 6 | url: string | null; 7 | remote_url: string | null; 8 | preview_url: string; 9 | text_url: string | null; 10 | meta: Meta | null; 11 | description: string | null; 12 | blurhash: string | null; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/card.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Card = { 3 | url: string; 4 | title: string; 5 | description: string; 6 | type: "link" | "photo" | "video" | "rich"; 7 | image?: string; 8 | author_name?: string; 9 | author_url?: string; 10 | provider_name?: string; 11 | provider_url?: string; 12 | html?: string; 13 | width?: number; 14 | height?: number; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/context.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Entity { 4 | export type Context = { 5 | ancestors: Array; 6 | descendants: Array; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/conversation.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | namespace Entity { 5 | export type Conversation = { 6 | id: string; 7 | accounts: Array; 8 | last_status: Status | null; 9 | unread: boolean; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/emoji.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Emoji = { 3 | shortcode: string; 4 | static_url: string; 5 | url: string; 6 | visible_in_picker: boolean; 7 | category: string; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/featured_tag.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type FeaturedTag = { 3 | id: string; 4 | name: string; 5 | statuses_count: number; 6 | last_status_at: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/field.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Field = { 3 | name: string; 4 | value: string; 5 | verified_at: string | null; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/filter.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Filter = { 3 | id: string; 4 | phrase: string; 5 | context: Array; 6 | expires_at: string | null; 7 | irreversible: boolean; 8 | whole_word: boolean; 9 | }; 10 | 11 | export type FilterContext = string; 12 | } 13 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/history.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type History = { 3 | day: string; 4 | uses: number; 5 | accounts: number; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/identity_proof.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type IdentityProof = { 3 | provider: string; 4 | provider_username: string; 5 | updated_at: string; 6 | proof_url: string; 7 | profile_url: string; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/list.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type List = { 3 | id: string; 4 | title: string; 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/marker.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Marker = { 3 | home?: { 4 | last_read_id: string; 5 | version: number; 6 | updated_at: string; 7 | }; 8 | notifications?: { 9 | last_read_id: string; 10 | version: number; 11 | updated_at: string; 12 | unread_count?: number; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/mention.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Mention = { 3 | id: string; 4 | username: string; 5 | url: string; 6 | acct: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/notification.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | namespace Entity { 5 | export type Notification = { 6 | account: Account; 7 | created_at: string; 8 | id: string; 9 | status?: Status; 10 | emoji?: string; 11 | type: NotificationType; 12 | }; 13 | 14 | export type NotificationType = string; 15 | } 16 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/poll.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Entity { 4 | export type Poll = { 5 | id: string; 6 | expires_at: string | null; 7 | expired: boolean; 8 | multiple: boolean; 9 | votes_count: number; 10 | options: Array; 11 | voted: boolean; 12 | own_votes: Array; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/poll_option.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type PollOption = { 3 | title: string; 4 | votes_count: number | null; 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/preferences.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Preferences = { 3 | "posting:default:visibility": "public" | "unlisted" | "private" | "direct"; 4 | "posting:default:sensitive": boolean; 5 | "posting:default:language": string | null; 6 | "reading:expand:media": "default" | "show_all" | "hide_all"; 7 | "reading:expand:spoilers": boolean; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/push_subscription.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Alerts = { 3 | follow: boolean; 4 | favourite: boolean; 5 | mention: boolean; 6 | reblog: boolean; 7 | poll: boolean; 8 | }; 9 | 10 | export type PushSubscription = { 11 | id: string; 12 | endpoint: string; 13 | server_key: string; 14 | alerts: Alerts; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/reaction.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Entity { 4 | export type Reaction = { 5 | count: number; 6 | me: boolean; 7 | name: string; 8 | url?: string; 9 | accounts?: Array; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/relationship.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Relationship = { 3 | id: string; 4 | following: boolean; 5 | followed_by: boolean; 6 | delivery_following?: boolean; 7 | blocking: boolean; 8 | blocked_by: boolean; 9 | muting: boolean; 10 | muting_notifications: boolean; 11 | requested: boolean; 12 | domain_blocking: boolean; 13 | showing_reblogs: boolean; 14 | endorsed: boolean; 15 | notifying: boolean; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/report.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Report = { 3 | id: string; 4 | action_taken: string; 5 | comment: string; 6 | account_id: string; 7 | status_ids: Array; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/results.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | namespace Entity { 6 | export type Results = { 7 | accounts: Array; 8 | statuses: Array; 9 | hashtags: Array; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/scheduled_status.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | namespace Entity { 4 | export type ScheduledStatus = { 5 | id: string; 6 | scheduled_at: string; 7 | params: StatusParams; 8 | media_attachments: Array; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/source.ts: -------------------------------------------------------------------------------- 1 | /// 2 | namespace Entity { 3 | export type Source = { 4 | privacy: string | null; 5 | sensitive: boolean | null; 6 | language: string | null; 7 | note: string; 8 | fields: Array; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/stats.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Stats = { 3 | user_count: number; 4 | status_count: number; 5 | domain_count: number; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/status_params.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type StatusParams = { 3 | text: string; 4 | in_reply_to_id: string | null; 5 | media_ids: Array | null; 6 | sensitive: boolean | null; 7 | spoiler_text: string | null; 8 | visibility: "public" | "unlisted" | "private" | "direct"; 9 | scheduled_at: string | null; 10 | application_id: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/tag.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace Entity { 4 | export type Tag = { 5 | name: string; 6 | url: string; 7 | history: Array | null; 8 | following?: boolean; 9 | blocking?: boolean; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/token.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type Token = { 3 | access_token: string; 4 | token_type: string; 5 | scope: string; 6 | created_at: number; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/entities/urls.ts: -------------------------------------------------------------------------------- 1 | namespace Entity { 2 | export type URLs = { 3 | streaming_api: string; 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /packages/megalodon/src/filter_context.ts: -------------------------------------------------------------------------------- 1 | import Entity from "./entity"; 2 | 3 | namespace FilterContext { 4 | export const Home: Entity.FilterContext = "home"; 5 | export const Notifications: Entity.FilterContext = "notifications"; 6 | export const Public: Entity.FilterContext = "public"; 7 | export const Thread: Entity.FilterContext = "thread"; 8 | export const Account: Entity.FilterContext = "account"; 9 | } 10 | 11 | export default FilterContext; 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/GetAll.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type GetAll = { 3 | tutorial: number 4 | defaultNoteVisibility: 'public' | 'home' | 'followers' | 'specified' 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/announcement.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Announcement = { 3 | id: string 4 | createdAt: string 5 | updatedAt: string 6 | text: string 7 | title: string 8 | isRead?: boolean 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/app.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type App = { 3 | id: string 4 | name: string 5 | callbackUrl: string 6 | permission: Array 7 | secret: string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/blocking.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Blocking = { 5 | id: string 6 | createdAt: string 7 | blockeeId: string 8 | blockee: UserDetail 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/createdNote.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type CreatedNote = { 5 | createdNote: Note 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/emoji.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Emoji = { 3 | name: string 4 | host: string | null 5 | url: string 6 | aliases: Array 7 | category: string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/favorite.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Favorite = { 5 | id: string 6 | createdAt: string 7 | noteId: string 8 | note: Note 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/field.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Field = { 3 | name: string 4 | value: string 5 | verified?: string 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/file.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type File = { 3 | id: string 4 | createdAt: string 5 | name: string 6 | type: string 7 | md5: string 8 | size: number 9 | isSensitive: boolean 10 | properties: { 11 | width: number 12 | height: number 13 | avgColor: string 14 | } 15 | url: string 16 | thumbnailUrl: string 17 | comment: string 18 | blurhash: string 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/followRequest.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type FollowRequest = { 5 | id: string 6 | follower: User 7 | followee: User 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/follower.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Follower = { 5 | id: string 6 | createdAt: string 7 | followeeId: string 8 | followerId: string 9 | follower: UserDetail 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/following.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Following = { 5 | id: string 6 | createdAt: string 7 | followeeId: string 8 | followerId: string 9 | followee: UserDetail 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/hashtag.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Hashtag = { 3 | tag: string 4 | chart: Array 5 | usersCount: number 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/list.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type List = { 3 | id: string 4 | createdAt: string 5 | name: string 6 | userIds: Array 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/meta.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Meta = { 5 | maintainerName: string 6 | maintainerEmail: string 7 | name: string 8 | version: string 9 | uri: string 10 | description: string 11 | langs: Array 12 | disableRegistration: boolean 13 | disableLocalTimeline: boolean 14 | bannerUrl: string 15 | maxNoteTextLength: 300000 16 | emojis: Array 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/mute.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Mute = { 5 | id: string 6 | createdAt: string 7 | muteeId: string 8 | mutee: UserDetail 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/poll.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Choice = { 3 | text: string 4 | votes: number 5 | isVoted: boolean 6 | } 7 | 8 | export type Poll = { 9 | multiple: boolean 10 | expiresAt: string 11 | choices: Array 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/reaction.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type Reaction = { 5 | id: string 6 | createdAt: string 7 | user: User 8 | url?: string 9 | type: string 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/relation.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Relation = { 3 | id: string 4 | isFollowing: boolean 5 | hasPendingFollowRequestFromYou: boolean 6 | hasPendingFollowRequestToYou: boolean 7 | isFollowed: boolean 8 | isBlocking: boolean 9 | isBlocked: boolean 10 | isMuted: boolean 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/session.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Session = { 3 | token: string 4 | url: string 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/state.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type State = { 3 | isFavorited: boolean 4 | isMutedThread: boolean 5 | isWatching: boolean 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/stats.ts: -------------------------------------------------------------------------------- 1 | namespace MisskeyEntity { 2 | export type Stats = { 3 | notesCount: number 4 | originalNotesCount: number 5 | usersCount: number 6 | originalUsersCount: number 7 | instances: number 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/user.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type User = { 5 | id: string 6 | name: string 7 | username: string 8 | host: string | null 9 | avatarUrl: string 10 | avatarColor: string 11 | emojis: Array 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/megalodon/src/misskey/entities/userkey.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | namespace MisskeyEntity { 4 | export type UserKey = { 5 | accessToken: string 6 | user: User 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/megalodon/src/response.ts: -------------------------------------------------------------------------------- 1 | type Response = { 2 | data: T; 3 | status: number; 4 | statusText: string; 5 | headers: any; 6 | }; 7 | 8 | export default Response; 9 | -------------------------------------------------------------------------------- /packages/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "unknown" 3 | } 4 | -------------------------------------------------------------------------------- /packages/sw/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "jsc": { 4 | "parser": { 5 | "syntax": "typescript", 6 | "dynamicImport": true, 7 | "decorators": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true 11 | }, 12 | "experimental": { 13 | "keepImportAssertions": true 14 | }, 15 | "baseUrl": ".", 16 | "paths": { 17 | "@/*": [ 18 | "./src/*" 19 | ] 20 | }, 21 | "target": "es2022" 22 | }, 23 | "minify": false 24 | } 25 | -------------------------------------------------------------------------------- /packages/sw/src/@types/global.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 2 | type FIXME = any; 3 | 4 | declare const _LANGS_: string[][]; 5 | declare const _VERSION_: string; 6 | declare const _ENV_: string; 7 | declare const _DEV_: boolean; 8 | declare const _PERF_PREFIX_: string; 9 | -------------------------------------------------------------------------------- /packages/sw/src/scripts/get-account-from-id.ts: -------------------------------------------------------------------------------- 1 | import { get } from "idb-keyval"; 2 | 3 | export async function getAccountFromId( 4 | id: string, 5 | ): Promise<{ token: string; id: string } | void> { 6 | const accounts = await get<{ token: string; id: string }[]>("accounts"); 7 | if (!accounts) { 8 | console.log("Accounts are not recorded"); 9 | return; 10 | } 11 | return accounts.find((e) => e.id === id); 12 | } 13 | -------------------------------------------------------------------------------- /packages/sw/src/scripts/get-user-name.ts: -------------------------------------------------------------------------------- 1 | export function getUserName(user: { 2 | name?: string | null; 3 | username: string; 4 | }): string { 5 | return user.name === "" ? user.username : user.name ?? user.username; 6 | } 7 | -------------------------------------------------------------------------------- /packages/sw/src/scripts/login-id.ts: -------------------------------------------------------------------------------- 1 | export function getUrlWithLoginId(url: string, loginId: string): string { 2 | const u = new URL(url, origin); 3 | u.searchParams.set("loginId", loginId); 4 | return u.toString(); 5 | } 6 | -------------------------------------------------------------------------------- /packages/sw/src/scripts/twemoji-base.ts: -------------------------------------------------------------------------------- 1 | export function char2fileName(char: string): string { 2 | let codes = Array.from(char) 3 | .map((x) => x.codePointAt(0)?.toString(16)) 4 | .filter((x: T | undefined): x is T => x !== undefined); 5 | if (!codes.includes("200d")) codes = codes.filter((x) => x !== "fe0f"); 6 | codes = codes.filter((x) => x.length !== 0); 7 | return codes.join("-"); 8 | } 9 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/backend' 3 | - 'packages/client' 4 | - 'packages/sw' 5 | - 'packages/firefish-js' 6 | - 'packages/megalodon' 7 | -------------------------------------------------------------------------------- /release.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.1", 3 | "notes": "Welcome to Goblin!", 4 | "screenshots": [] 5 | } 6 | -------------------------------------------------------------------------------- /scripts/goblin.logrotate.conf: -------------------------------------------------------------------------------- 1 | /var/log/goblin/log.error { 2 | rotate 12 3 | monthly 4 | compress 5 | missingok 6 | notifempty 7 | } 8 | 9 | /var/log/goblin/log.txt { 10 | rotate 12 11 | daily 12 | compress 13 | missingok 14 | notifempty 15 | } 16 | -------------------------------------------------------------------------------- /scripts/goblin.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Fediverse server based on Tumblr 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/etc/goblin/scripts/goblin.start.sh 7 | PIDFile=/run/goblin/goblin.pid 8 | Restart=always 9 | User=goblin 10 | Group=goblin 11 | StandardOutput=file:/var/log/goblin/log.txt 12 | StandardError=file:/var/log/goblin/log.error 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /scripts/goblin.start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /etc/goblin 3 | NODE_ENV=production pnpm start -------------------------------------------------------------------------------- /title.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnHackworth/goblin/86b43a280869bc265b45af9845e4d5b66b2800bf/title.svg.png --------------------------------------------------------------------------------