From 5335e68bde94e960632db3042d5f47fa86b79b5a Mon Sep 17 00:00:00 2001 From: mattyatea Date: Thu, 2 Nov 2023 16:51:03 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=E3=82=B4=E3=83=AA=E3=83=A9=E3=83=A2?= =?UTF-8?q?=E3=83=BC=E3=83=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 2 + locales/ja-JP.yml | 2 + .../backend/src/core/NoteCreateService.ts | 1 + .../src/core/entities/UserEntityService.ts | 1 + packages/backend/src/models/User.ts | 6 +++ .../backend/src/models/json-schema/user.ts | 4 ++ .../src/server/api/endpoints/i/update.ts | 8 +++- .../global/MkMisskeyFlavoredMarkdown.ts | 43 +++++++++++++++++-- .../frontend/src/pages/settings/profile.vue | 8 +++- packages/frontend/src/scripts/achievements.ts | 5 +++ packages/frontend/src/scripts/uhoize.ts | 28 ++++++++++++ packages/misskey-js/etc/misskey-js.api.md | 6 ++- packages/misskey-js/src/entities.ts | 2 + 13 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 packages/frontend/src/scripts/uhoize.ts diff --git a/locales/index.d.ts b/locales/index.d.ts index 77cce21f84..f13b8c7712 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -175,7 +175,9 @@ export interface Locale { "flagAsBot": string; "flagAsBotDescription": string; "flagAsCat": string; + "flagAsGorilla": string; "flagAsCatDescription": string; + "flagAsGorillaDescription": string; "flagShowTimelineReplies": string; "showMediaTimeline": string; "showMediaTimelineInfo": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e884b44382..3500c6b1b1 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -172,7 +172,9 @@ cacheRemoteSensitiveFilesDescription: "この設定を無効にすると、リ flagAsBot: "Botとして設定" flagAsBotDescription: "このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。" flagAsCat: "にゃああああああああああああああ!!!!!!!!!!!!" +flagAsGorilla: "ウホウホウホホウホウホウホウホホホ!!!!!!!!!!!" flagAsCatDescription: "にゃにゃにゃ??" +flagAsGorillaDescription: "ウホウホウホ??" flagShowTimelineReplies: "タイムラインにノートへの返信を表示する" showMediaTimeline: "メディアタイムラインを表示する" showMediaTimelineInfo: "オンにするとメディアタイムラインを上のバーに表示します。 オフにすると表示しなくなります。" diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index acd11a9fa7..37dad286a7 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -224,6 +224,7 @@ export class NoteCreateService implements OnApplicationShutdown { host: MiUser['host']; isBot: MiUser['isBot']; isCat: MiUser['isCat']; + isGorilla: MiUser['isGorilla']; }, data: Option, silent = false): Promise { // チャンネル外にリプライしたら対象のスコープに合わせる // (クライアントサイドでやっても良い処理だと思うけどとりあえずサーバーサイドで) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 17e7988176..328786e837 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -366,6 +366,7 @@ export class UserEntityService implements OnModuleInit { }))) : [], isBot: user.isBot, isCat: user.isCat, + isGorilla: user.isGorilla, instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? { name: instance.name, softwareName: instance.softwareName, diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index c3762fcd3e..691866da6a 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -177,6 +177,12 @@ export class MiUser { }) public isCat: boolean; + @Column('boolean', { + default: false, + comment: 'Whether the User is a gorilla.', + }) + public isGorilla: boolean; + @Column('boolean', { default: false, comment: 'Whether the User is the root.', diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 37bdcbe281..f0f225d4dc 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -83,6 +83,10 @@ export const packedUserLiteSchema = { type: 'boolean', nullable: false, optional: true, }, + isGorilla: { + type: 'boolean', + nullable: false, optional: true, + }, onlineStatus: { type: 'string', format: 'url', diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 0e6a4d2e36..67fcd81860 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -165,6 +165,7 @@ export const paramDef = { preventAiLearning: { type: 'boolean' }, isBot: { type: 'boolean' }, isCat: { type: 'boolean' }, + isGorilla: { type: 'boolean' }, injectFeaturedNote: { type: 'boolean' }, receiveAnnouncementEmail: { type: 'boolean' }, alwaysMarkNsfw: { type: 'boolean' }, @@ -267,7 +268,12 @@ export default class extends Endpoint { // eslint- if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed; if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle; if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning; - if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat; + if (typeof ps.isCat === 'boolean' && !ps.isGorilla) { + updates.isCat = ps.isCat; + }; + if (typeof ps.isGorilla === 'boolean' && !ps.isCat) { + updates.isGorilla = ps.isGorilla + }; if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote; if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail; if (typeof ps.alwaysMarkNsfw === 'boolean') { diff --git a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts index cb1abcd8c8..6bc513e301 100644 --- a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts +++ b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts @@ -16,6 +16,8 @@ import { defaultStore } from '@/store'; import { mixEmoji } from '@/scripts/emojiKitchen/emojiMixer'; import MkRuby from "@/components/global/MkRuby.vue"; import { nyaize as doNyaize } from '@/scripts/nyaize.js'; +import { uhoize as doUhoize } from '@/scripts/uhoize.js'; +import {ID, Instance} from "misskey-js/built/entities.js"; const QUOTE_STYLE = ` display: block; @@ -62,12 +64,41 @@ type MfmProps = { text: string; plain?: boolean; nowrap?: boolean; - author?: Misskey.entities.UserLite; + author?: { + id: ID; + username: string; + host: string | null; + name: string | null; + onlineStatus: 'online' | 'active' | 'offline' | 'unknown'; + avatarUrl: string; + avatarBlurhash: string; + avatarDecorations: { + id: ID; + url: string; + angle?: number; + flipH?: boolean; + }[]; + emojis: { + name: string; + url: string; + }[]; + instance?: { + name: Instance['name']; + softwareName: Instance['softwareName']; + softwareVersion: Instance['softwareVersion']; + iconUrl: Instance['iconUrl']; + faviconUrl: Instance['faviconUrl']; + themeColor: Instance['themeColor']; + }; + isGorilla?: boolean; + isCat?: boolean; + isBot?: boolean;}; i?: Misskey.entities.UserLite | null; isNote?: boolean; emojiUrls?: string[]; rootScale?: number; nyaize: boolean | 'account'; + uhoize: boolean | 'account'; parsedNodes?: mfm.MfmNode[] | null; }; @@ -75,7 +106,8 @@ type MfmProps = { export default function(props: MfmProps) { const isNote = props.isNote ?? true; const shouldNyaize = props.nyaize ? props.nyaize === 'account' ? props.author?.isCat : false : false; - + const shouldUhoize = props.nyaize ? props.nyaize === 'account' ? props.author?.isGorilla : false : false; + console.log(shouldUhoize, props.nyaize,props.author?.isGorilla) // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (props.text == null || props.text === '') return; @@ -93,15 +125,18 @@ export default function(props: MfmProps) { * @param ast MFM AST * @param scale How times large the text is * @param disableNyaize Whether nyaize is disabled or not + * @param disableUhoize */ - const genEl = (ast: mfm.MfmNode[], scale: number, disableNyaize = false) => ast.map((token): VNode | string | (VNode | string)[] => { + const genEl = (ast: mfm.MfmNode[], scale: number, disableNyaize = false, disableUhoize = false) => ast.map((token): VNode | string | (VNode | string)[] => { switch (token.type) { case 'text': { let text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n'); if (!disableNyaize && shouldNyaize) { text = doNyaize(text); } - + if (!disableUhoize && shouldUhoize) { + text = doUhoize(text); + } if (!props.plain) { const res: (VNode | string)[] = []; for (const t of text.split('\n')) { diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index 2ac8d15545..1ecde64d05 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -105,7 +105,8 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.flagAsCat }} + {{ i18n.ts.flagAsCat }} + {{ i18n.ts.flagAsGorilla }} {{ i18n.ts.flagAsBot }}
@@ -154,6 +155,7 @@ const profile = reactive({ lang: $i.lang, isBot: $i.isBot, isCat: $i.isCat, + isGorilla: $i.isGorilla, }); watch(() => profile, () => { @@ -206,6 +208,7 @@ function save() { lang: profile.lang || null, isBot: !!profile.isBot, isCat: !!profile.isCat, + isGorilla: !!profile.isGorilla, }); claimAchievement('profileFilled'); if (profile.name === 'syuilo' || profile.name === 'しゅいろ') { @@ -214,6 +217,9 @@ function save() { if (profile.isCat) { claimAchievement('markedAsCat'); } + if (profile.isGorilla) { + claimAchievement('markedAsCat'); + } } function changeAvatar(ev) { diff --git a/packages/frontend/src/scripts/achievements.ts b/packages/frontend/src/scripts/achievements.ts index af7c6b060c..e9d12eb6f2 100644 --- a/packages/frontend/src/scripts/achievements.ts +++ b/packages/frontend/src/scripts/achievements.ts @@ -265,6 +265,11 @@ export const ACHIEVEMENT_BADGES = { bg: 'linear-gradient(0deg, rgb(187 183 59), rgb(255 143 77))', frame: 'bronze', }, + 'markedAsGorilla': { + img: '/fluent-emoji/1f98D.png', + bg: 'linear-gradient(0deg, rgba(55,0,0,1) 0%, rgba(107,5,5,1) 59%, rgba(158,6,6,1) 100%)', + frame: 'bronze', + }, 'following1': { img: '/fluent-emoji/2618.png', bg: 'linear-gradient(0deg, rgb(59 187 116), rgb(199 211 102))', diff --git a/packages/frontend/src/scripts/uhoize.ts b/packages/frontend/src/scripts/uhoize.ts new file mode 100644 index 0000000000..25d3760722 --- /dev/null +++ b/packages/frontend/src/scripts/uhoize.ts @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export function uhoize(text) { + const gorillaNoises = ['ウホ', 'ウホホ', 'ウホッ']; + let result = ''; + let noiseIndex = 0; + for (let i = 0; i < text.length; i++) { + if (!(/[、。.,\/#!$%\^&\*;:{}=\-_`~()]/.test(text[i]))) { + if (/[^\x00-\x7F]/.test(text[i])) { + noiseIndex = Math.floor(Math.random() * 3); + const japaneseNoises = ['ウホ', 'ウホホ', 'ウホッ']; + result += japaneseNoises[noiseIndex]; + } else { + noiseIndex = Math.floor(Math.random() * 2); + const englishNoises = ['uho', 'uhoho']; + result += englishNoises[noiseIndex]; + } + }else{ + result += text[i]; + } + if (text.length*1.3 < result.length) return result + + } + return result; +} diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 88704a8236..e39a89fdbd 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2951,6 +2951,7 @@ type UserDetailed = UserLite & { isBlocking: boolean; isBot: boolean; isCat: boolean; + isGorilla: boolean; isFollowed: boolean; isFollowing: boolean; isLocked: boolean; @@ -3014,6 +3015,7 @@ type UserLite = { faviconUrl: Instance['faviconUrl']; themeColor: Instance['themeColor']; }; + isGorilla?: boolean; isCat?: boolean; isBot?: boolean; }; @@ -3026,8 +3028,8 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u // src/api.types.ts:16:32 - (ae-forgotten-export) The symbol "TODO" needs to be exported by the entry point index.d.ts // src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts // src/api.types.ts:633:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts -// src/entities.ts:116:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts -// src/entities.ts:614:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts +// src/entities.ts:118:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts +// src/entities.ts:616:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index ffe1109227..e2cea8c7e4 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -34,6 +34,7 @@ export type UserLite = { faviconUrl: Instance['faviconUrl']; themeColor: Instance['themeColor']; }; + isGorilla?: boolean; isCat?: boolean; isBot?: boolean; }; @@ -58,6 +59,7 @@ export type UserDetailed = UserLite & { isBlocking: boolean; isBot: boolean; isCat: boolean; + isGorilla: boolean; isFollowed: boolean; isFollowing: boolean; isLocked: boolean;