merge: add speakAsCat extension and non-nya speech option

This commit is contained in:
Marie 2023-10-04 05:01:58 +02:00 committed by GitHub
commit 6dd0b88050
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 48 additions and 2 deletions

View file

@ -164,6 +164,8 @@ flagAsBot: "Mark this account as a bot"
flagAsBotDescription: "Enable this option if this account is controlled by a program. If enabled, it will act as a flag for other developers to prevent endless interaction chains with other bots and adjust Misskey's internal systems to treat this account as a bot." flagAsBotDescription: "Enable this option if this account is controlled by a program. If enabled, it will act as a flag for other developers to prevent endless interaction chains with other bots and adjust Misskey's internal systems to treat this account as a bot."
flagAsCat: "Mark this account as a cat" flagAsCat: "Mark this account as a cat"
flagAsCatDescription: "Enable this option to mark this account as a cat." flagAsCatDescription: "Enable this option to mark this account as a cat."
flagSpeakAsCat: "Speak as a cat"
flagSpeakAsCatDescription: "Your posts will get nyanified when in cat mode."
flagShowTimelineReplies: "Show replies in timeline" flagShowTimelineReplies: "Show replies in timeline"
flagShowTimelineRepliesDescription: "Shows replies of users to notes of other users in the timeline if turned on." flagShowTimelineRepliesDescription: "Shows replies of users to notes of other users in the timeline if turned on."
autoAcceptFollowed: "Automatically approve follow requests from users you're following" autoAcceptFollowed: "Automatically approve follow requests from users you're following"

View file

@ -0,0 +1,12 @@
export class SpeakAsCat1696386694000 {
name = "SpeakAsCat1696386694000";
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" ADD "speakAsCat" boolean NOT NULL DEFAULT true`);
await queryRunner.query(`COMMENT ON COLUMN "user"."speakAsCat" IS 'Whether to speak as a cat if chosen.'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "speakAsCat"`);
}
}

View file

@ -501,6 +501,7 @@ export class ApRendererService {
discoverable: user.isExplorable, discoverable: user.isExplorable,
publicKey: this.renderKey(user, keypair, '#main-key'), publicKey: this.renderKey(user, keypair, '#main-key'),
isCat: user.isCat, isCat: user.isCat,
speakAsCat: user.speakAsCat,
attachment: attachment.length ? attachment : undefined, attachment: attachment.length ? attachment : undefined,
}; };
@ -646,6 +647,9 @@ export class ApRendererService {
'_misskey_reaction': 'misskey:_misskey_reaction', '_misskey_reaction': 'misskey:_misskey_reaction',
'_misskey_votes': 'misskey:_misskey_votes', '_misskey_votes': 'misskey:_misskey_votes',
'isCat': 'misskey:isCat', 'isCat': 'misskey:isCat',
// Firefish
firefish: "https://joinfirefish.org/ns#",
speakAsCat: "firefish:speakAsCat",
// vcard // vcard
vcard: 'http://www.w3.org/2006/vcard/ns#', vcard: 'http://www.w3.org/2006/vcard/ns#',
}, },

View file

@ -326,6 +326,7 @@ export class ApPersonService implements OnModuleInit {
tags, tags,
isBot, isBot,
isCat: (person as any).isCat === true, isCat: (person as any).isCat === true,
speakAsCat: (person as any).speakAsCat != null ? (person as any).speakAsCat === true : (person as any).isCat === true,
emojis, emojis,
})) as MiRemoteUser; })) as MiRemoteUser;
@ -460,12 +461,13 @@ export class ApPersonService implements OnModuleInit {
tags, tags,
isBot: getApType(object) === 'Service', isBot: getApType(object) === 'Service',
isCat: (person as any).isCat === true, isCat: (person as any).isCat === true,
speakAsCat: (person as any).speakAsCat != null ? (person as any).speakAsCat === true : (person as any).isCat === true,
isLocked: person.manuallyApprovesFollowers, isLocked: person.manuallyApprovesFollowers,
movedToUri: person.movedTo ?? null, movedToUri: person.movedTo ?? null,
alsoKnownAs: person.alsoKnownAs ?? null, alsoKnownAs: person.alsoKnownAs ?? null,
isExplorable: person.discoverable, isExplorable: person.discoverable,
...(await this.resolveAvatarAndBanner(exist, person.icon, person.image).catch(() => ({}))), ...(await this.resolveAvatarAndBanner(exist, person.icon, person.image).catch(() => ({}))),
} as Partial<MiRemoteUser> & Pick<MiRemoteUser, 'isBot' | 'isCat' | 'isLocked' | 'movedToUri' | 'alsoKnownAs' | 'isExplorable'>; } as Partial<MiRemoteUser> & Pick<MiRemoteUser, 'isBot' | 'isCat' | 'speakAsCat' | 'isLocked' | 'movedToUri' | 'alsoKnownAs' | 'isExplorable'>;
const moving = ((): boolean => { const moving = ((): boolean => {
// 移行先がない→ある // 移行先がない→ある

View file

@ -364,7 +364,7 @@ export class NoteEntityService implements OnModuleInit {
} : {}), } : {}),
}); });
if (packed.user.isCat && packed.text) { if (packed.user.isCat && packed.user.speakAsCat && packed.text) {
const tokens = packed.text ? mfm.parse(packed.text) : []; const tokens = packed.text ? mfm.parse(packed.text) : [];
function nyaizeNode(node: mfm.MfmNode) { function nyaizeNode(node: mfm.MfmNode) {
if (node.type === 'quote') return; if (node.type === 'quote') return;

View file

@ -352,6 +352,7 @@ export class UserEntityService implements OnModuleInit {
createdAt: user.createdAt.toISOString(), createdAt: user.createdAt.toISOString(),
isBot: user.isBot ?? falsy, isBot: user.isBot ?? falsy,
isCat: user.isCat ?? falsy, isCat: user.isCat ?? falsy,
speakAsCat: user.speakAsCat ?? falsy,
instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? { instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? {
name: instance.name, name: instance.name,
softwareName: instance.softwareName, softwareName: instance.softwareName,

View file

@ -174,6 +174,12 @@ export class MiUser {
}) })
public isCat: boolean; public isCat: boolean;
@Column('boolean', {
default: true,
comment: 'Whether the User speaks in nya.',
})
public speakAsCat: boolean;
@Column('boolean', { @Column('boolean', {
default: false, default: false,
comment: 'Whether the User is the root.', comment: 'Whether the User is the root.',

View file

@ -55,6 +55,10 @@ export const packedUserLiteSchema = {
type: 'boolean', type: 'boolean',
nullable: false, optional: true, nullable: false, optional: true,
}, },
speakAsCat: {
type: 'boolean',
nullable: false, optional: true,
},
onlineStatus: { onlineStatus: {
type: 'string', type: 'string',
format: 'url', format: 'url',

View file

@ -156,6 +156,7 @@ export const paramDef = {
preventAiLearning: { type: 'boolean' }, preventAiLearning: { type: 'boolean' },
isBot: { type: 'boolean' }, isBot: { type: 'boolean' },
isCat: { type: 'boolean' }, isCat: { type: 'boolean' },
speakAsCat: { type: 'boolean' },
injectFeaturedNote: { type: 'boolean' }, injectFeaturedNote: { type: 'boolean' },
receiveAnnouncementEmail: { type: 'boolean' }, receiveAnnouncementEmail: { type: 'boolean' },
alwaysMarkNsfw: { type: 'boolean' }, alwaysMarkNsfw: { type: 'boolean' },
@ -259,6 +260,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle; if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning; if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning;
if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat; if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
if (typeof ps.speakAsCat === 'boolean') updates.speakAsCat = ps.speakAsCat;
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote; if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail; if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
if (typeof ps.alwaysMarkNsfw === 'boolean') { if (typeof ps.alwaysMarkNsfw === 'boolean') {

View file

@ -70,6 +70,7 @@ describe('ユーザー', () => {
avatarBlurhash: user.avatarBlurhash, avatarBlurhash: user.avatarBlurhash,
isBot: user.isBot, isBot: user.isBot,
isCat: user.isCat, isCat: user.isCat,
speakAsCat: user.speakAsCat,
instance: user.instance, instance: user.instance,
emojis: user.emojis, emojis: user.emojis,
onlineStatus: user.onlineStatus, onlineStatus: user.onlineStatus,
@ -350,6 +351,7 @@ describe('ユーザー', () => {
assert.strictEqual(response.avatarBlurhash, null); assert.strictEqual(response.avatarBlurhash, null);
assert.strictEqual(response.isBot, false); assert.strictEqual(response.isBot, false);
assert.strictEqual(response.isCat, false); assert.strictEqual(response.isCat, false);
assert.strictEqual(response.speakAsCat, false);
assert.strictEqual(response.instance, undefined); assert.strictEqual(response.instance, undefined);
assert.deepStrictEqual(response.emojis, {}); assert.deepStrictEqual(response.emojis, {});
assert.strictEqual(response.onlineStatus, 'unknown'); assert.strictEqual(response.onlineStatus, 'unknown');
@ -481,6 +483,8 @@ describe('ユーザー', () => {
{ parameters: (): object => ({ isBot: false }) }, { parameters: (): object => ({ isBot: false }) },
{ parameters: (): object => ({ isCat: true }) }, { parameters: (): object => ({ isCat: true }) },
{ parameters: (): object => ({ isCat: false }) }, { parameters: (): object => ({ isCat: false }) },
{ parameters: (): object => ({ speakAsCat: true }) },
{ parameters: (): object => ({ speakAsCat: false }) },
{ parameters: (): object => ({ injectFeaturedNote: true }) }, { parameters: (): object => ({ injectFeaturedNote: true }) },
{ parameters: (): object => ({ injectFeaturedNote: false }) }, { parameters: (): object => ({ injectFeaturedNote: false }) },
{ parameters: (): object => ({ receiveAnnouncementEmail: true }) }, { parameters: (): object => ({ receiveAnnouncementEmail: true }) },

View file

@ -99,6 +99,7 @@ export function userDetailed(id = 'someuserid', username = 'miskist', host = 'mi
isBlocking: false, isBlocking: false,
isBot: false, isBot: false,
isCat: false, isCat: false,
speakAsCat: false,
isFollowed: false, isFollowed: false,
isFollowing: false, isFollowing: false,
isLocked: false, isLocked: false,

View file

@ -93,6 +93,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps_m"> <div class="_gaps_m">
<MkSwitch v-model="profile.isCat">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></MkSwitch> <MkSwitch v-model="profile.isCat">{{ i18n.ts.flagAsCat }}<template #caption>{{ i18n.ts.flagAsCatDescription }}</template></MkSwitch>
<MkSwitch v-if="profile.isCat" v-model="profile.speakAsCat">{{ i18n.ts.flagSpeakAsCat }}<template #caption>{{ i18n.ts.flagSpeakAsCatDescription }}</template></MkSwitch>
<MkSwitch v-model="profile.isBot">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></MkSwitch> <MkSwitch v-model="profile.isBot">{{ i18n.ts.flagAsBot }}<template #caption>{{ i18n.ts.flagAsBotDescription }}</template></MkSwitch>
</div> </div>
</MkFolder> </MkFolder>
@ -141,6 +142,7 @@ const profile = reactive({
lang: $i.lang, lang: $i.lang,
isBot: $i.isBot, isBot: $i.isBot,
isCat: $i.isCat, isCat: $i.isCat,
speakAsCat: $i.speakAsCat,
}); });
watch(() => profile, () => { watch(() => profile, () => {
@ -190,6 +192,7 @@ function save() {
lang: profile.lang || null, lang: profile.lang || null,
isBot: !!profile.isBot, isBot: !!profile.isBot,
isCat: !!profile.isCat, isCat: !!profile.isCat,
speakAsCat: !!profile.speakAsCat,
}); });
claimAchievement('profileFilled'); claimAchievement('profileFilled');
if (profile.name === 'syuilo' || profile.name === 'しゅいろ') { if (profile.name === 'syuilo' || profile.name === 'しゅいろ') {

View file

@ -13,6 +13,7 @@ namespace MisskeyEntity {
isModerator: boolean isModerator: boolean
isBot: boolean isBot: boolean
isCat: boolean isCat: boolean
speakAsCat: boolean
emojis: Array<Emoji> | { [key: string]: string } emojis: Array<Emoji> | { [key: string]: string }
createdAt: string createdAt: string
bannerUrl: string bannerUrl: string

View file

@ -1541,6 +1541,7 @@ export type Endpoints = {
noCrawle?: boolean; noCrawle?: boolean;
isBot?: boolean; isBot?: boolean;
isCat?: boolean; isCat?: boolean;
speakAsCat?: boolean;
injectFeaturedNote?: boolean; injectFeaturedNote?: boolean;
receiveAnnouncementEmail?: boolean; receiveAnnouncementEmail?: boolean;
alwaysMarkNsfw?: boolean; alwaysMarkNsfw?: boolean;
@ -2915,6 +2916,7 @@ type UserDetailed = UserLite & {
isBlocking: boolean; isBlocking: boolean;
isBot: boolean; isBot: boolean;
isCat: boolean; isCat: boolean;
speakAsCat: boolean;
isFollowed: boolean; isFollowed: boolean;
isFollowing: boolean; isFollowing: boolean;
isLocked: boolean; isLocked: boolean;

View file

@ -426,6 +426,7 @@ export type Endpoints = {
noCrawle?: boolean; noCrawle?: boolean;
isBot?: boolean; isBot?: boolean;
isCat?: boolean; isCat?: boolean;
speakAsCat?: boolean;
injectFeaturedNote?: boolean; injectFeaturedNote?: boolean;
receiveAnnouncementEmail?: boolean; receiveAnnouncementEmail?: boolean;
alwaysMarkNsfw?: boolean; alwaysMarkNsfw?: boolean;

View file

@ -50,6 +50,7 @@ export type UserDetailed = UserLite & {
isBlocking: boolean; isBlocking: boolean;
isBot: boolean; isBot: boolean;
isCat: boolean; isCat: boolean;
speakAsCat: boolean;
isFollowed: boolean; isFollowed: boolean;
isFollowing: boolean; isFollowing: boolean;
isLocked: boolean; isLocked: boolean;