Skip to content

Commit

Permalink
Merge branch 'develop' into advsearchWiledcard
Browse files Browse the repository at this point in the history
  • Loading branch information
penginn-net authored Jan 10, 2025
2 parents a74b09a + 8350c4d commit 8540e29
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG_YOJO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
- Feat: システムユーザーのファイル一覧を追加 [#595](https://github.com/yojo-art/cherrypick/pull/595)

### Client
- Fix: チュートリアルを現状に合わせて更新[#586](https://github.com/yojo-art/cherrypick/pull/586)
- Enhance: ノート詳細から前後のHTL/LTLを開く機能を追加 [#572](https://github.com/yojo-art/cherrypick/pull/572)
- Enhance: インポート時にライセンス欄にインポート元を追記する [#573](https://github.com/yojo-art/cherrypick/pull/573)
- Feat: コンパネのファイルに絵文字として利用中ラベルを表示する [#603](https://github.com/yojo-art/cherrypick/pull/603)
- Enhance: TLオプション表示有無切り替えの選択肢にメディアタイムラインを追加 [#609](https://github.com/yojo-art/cherrypick/pull/609)

### Server
- Change: `ap/fetch-outbox`から`includeAnnounce`オプションを削除 [#606](https://github.com/yojo-art/cherrypick/pull/606)
- Enhance: 高度な検索であいまい検索が無効な時ワイルドカードを利用可能に [#564](https://github.com/yojo-art/cherrypick/pull/564)
- Feat: フォローしているユーザーなら鍵ノートでもアンテナにひっかかるように [#568](https://github.com/yojo-art/cherrypick/pull/568)
- based-on https://github.com/team-shahu/misskey/pull/38


## 1.2.2
Cherrypick 4.13.0
Misskey 2024.10.1
Expand Down
34 changes: 34 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6549,6 +6549,10 @@ export interface Locale extends ILocale {
* 接続している他のすべてのサーバーからの投稿を見られます。
*/
"global": string;
/**
* 接続している他のすべてのサーバーからのファイル付き投稿を見られます。
*/
"media": string;
/**
* それぞれのタイムラインは、画面上部でいつでも切り替えられます。
*/
Expand Down Expand Up @@ -6601,6 +6605,36 @@ export interface Locale extends ILocale {
*/
"localOnly": string;
};
"_searchbility": {
/**
* 検索許可の設定
*/
"title": string;
/**
* ノートを表示できる相手を制限できます。
*/
"description": string;
/**
* すべてのユーザーが検索できます
*/
"public": string;
/**
* フォロワーと反応した人が検索できます
*/
"followers": string;
/**
* 反応した人が検索できます
*/
"reactedOnly": string;
/**
* 自分のみが検索できます
*/
"private": string;
/**
* リモートサーバーでは適用されない可能性があります。
*/
"notApplyRemote": string;
};
"_cw": {
/**
* 内容を隠す(CW)
Expand Down
9 changes: 9 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,7 @@ _initialTutorial:
local: "このサーバーにいるユーザー全員の投稿を見られます。"
social: "ホームタイムラインとローカルタイムラインの投稿が両方表示されます。"
global: "接続している他のすべてのサーバーからの投稿を見られます。"
media: "接続している他のすべてのサーバーからのファイル付き投稿を見られます。"
description2: "それぞれのタイムラインは、画面上部でいつでも切り替えられます。"
description3: "その他にも、リストタイムラインやチャンネルタイムラインなどがあります。詳しくは{link}をご覧ください。"
_postNote:
Expand All @@ -1670,6 +1671,14 @@ _initialTutorial:
doNotSendConfidencialOnDirect1: "機密情報は送信する際は注意してください。"
doNotSendConfidencialOnDirect2: "送信先のサーバーの管理者は投稿内容を見ることが可能なので、信頼できないサーバーのユーザーにダイレクト投稿を送信する場合は、機密情報の扱いに注意が必要です。"
localOnly: "他のサーバーに投稿を連合しません。上記の公開範囲に関わらず、他のサーバーのユーザーは、この設定がついたノートを直接閲覧することができなくなります。"
_searchbility:
title: "検索許可の設定"
description: "ノートを表示できる相手を制限できます。"
public: "すべてのユーザーが検索できます"
followers: "フォロワーと反応した人が検索できます"
reactedOnly: "反応した人が検索できます"
private: "自分のみが検索できます"
notApplyRemote: "リモートサーバーでは適用されない可能性があります。"
_cw:
title: "内容を隠す(CW)"
description: "本文のかわりに「注釈」に書いた内容が表示されます。「もっと見る」を押すと本文が表示されます。"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class ApOutboxFetchService implements OnModuleInit {
* outboxから投稿を取得します
*/
@bindThis
public async fetchOutbox(userId: MiUser['id'], includeAnnounce = false, resolver?: Resolver): Promise<void> {
public async fetchOutbox(userId: MiUser['id'], resolver?: Resolver): Promise<void> {
const user = (await this.usersRepository.findOneBy({ id: userId }) as MiRemoteUser | null) ?? null;
if (!user) throw new IdentifiableError('3fc5a089-cab4-48db-b9f3-f220574b3c0a', 'No such user');
if (!user.host) throw new IdentifiableError('67070303-177c-4600-af93-b26a7ab889c6', 'Is local user');
Expand Down Expand Up @@ -106,7 +106,7 @@ export class ApOutboxFetchService implements OnModuleInit {
if (!activityes) throw new IdentifiableError('2a05bb06-f38c-4854-af6f-7fd5e87c98ee', 'item is unavailable');

do {
current = await this.fetchObjects(user, activityes, includeAnnounce, current.created);
current = await this.fetchObjects(user, activityes, current.created);
page++;
}
while (!current.breaked && page < pagelimit);
Expand All @@ -119,15 +119,15 @@ export class ApOutboxFetchService implements OnModuleInit {
}

@bindThis
private async fetchObjects(user: MiRemoteUser, activityes: any[], includeAnnounce:boolean, created: number): Promise<{
private async fetchObjects(user: MiRemoteUser, activityes: any[], created: number): Promise<{
created: number;
breaked: boolean;
}> {
for (const activity of activityes) {
if (createLimit < created) return { created: created, breaked: true };
try {
if (activity.actor !== user.uri) throw new IdentifiableError('bde7c204-5441-4a87-9b7e-f81e8d05788a');
if (activity.type === 'Announce' && includeAnnounce) {
if (activity.type === 'Announce') {
const object = await this.apNoteService.fetchNote(activity.id);

if (object) continue;
Expand Down
17 changes: 14 additions & 3 deletions packages/backend/src/core/entities/NotificationEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { Inject, Injectable } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { FollowRequestsRepository, NotesRepository, MiUser, UsersRepository, UserGroupInvitationsRepository } from '@/models/_.js';
import type { FollowRequestsRepository, NotesRepository, MiUser, UsersRepository, UserGroupInvitationsRepository, MiUserGroupInvitation } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { MiGroupedNotification, MiNotification } from '@/models/Notification.js';
import type { MiNote } from '@/models/Note.js';
import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js';
import { FilterUnionByProperty, groupedNotificationTypes } from '@/types.js';
import { CacheService } from '@/core/CacheService.js';
import { NotificationService } from '../NotificationService.js';
import { RoleEntityService } from './RoleEntityService.js';
import type { OnModuleInit } from '@nestjs/common';
import type { UserEntityService } from './UserEntityService.js';
Expand All @@ -29,6 +30,7 @@ export class NotificationEntityService implements OnModuleInit {
private noteEntityService: NoteEntityService;
private roleEntityService: RoleEntityService;
private userGroupInvitationEntityService: UserGroupInvitationEntityService;
private notificationService: NotificationService;

constructor(
private moduleRef: ModuleRef,
Expand Down Expand Up @@ -58,6 +60,7 @@ export class NotificationEntityService implements OnModuleInit {
this.noteEntityService = this.moduleRef.get('NoteEntityService');
this.roleEntityService = this.moduleRef.get('RoleEntityService');
this.userGroupInvitationEntityService = this.moduleRef.get('UserGroupInvitationEntityService');
this.notificationService = this.moduleRef.get('NotificationService');
}

/**
Expand Down Expand Up @@ -172,8 +175,16 @@ export class NotificationEntityService implements OnModuleInit {
if (needsRole && !role) {
return null;
}
let group_invitation: MiUserGroupInvitation|null = null;
if (notification.type === 'groupInvited') {
group_invitation = await this.userGroupInvitationsRepository.findOneBy({ id: notification.userGroupInvitationId });
if (group_invitation === null) {
this.notificationService.deleteNotification(meId, notification.id);
return null;
}
}

return await awaitAll({
return awaitAll({
id: notification.id,
createdAt: new Date(notification.createdAt).toISOString(),
type: notification.type,
Expand All @@ -184,7 +195,7 @@ export class NotificationEntityService implements OnModuleInit {
reaction: notification.reaction,
} : {}),
...(notification.type === 'groupInvited' ? {
invitation: this.userGroupInvitationEntityService.pack(notification.userGroupInvitationId),
invitation: this.userGroupInvitationEntityService.pack(group_invitation!),
} : {}),
...(notification.type === 'roleAssigned' ? {
role: role,
Expand Down
9 changes: 2 additions & 7 deletions packages/backend/src/server/api/endpoints/ap/fetch-outbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ export const paramDef = {
default: false,
description: 'Outboxの取得が終わるまで待ちます',
},
includeAnnounce: {
type: 'boolean',
default: false,
description: 'Outbox取得の際にRenoteも対象にします',
},
//skip: { type: 'integer', minimum: 1, default: 0 },
},
required: ['userId'],
Expand All @@ -87,7 +82,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
super(meta, paramDef, async (ps, me) => {
if (ps.wait) {
try {
await this.apOutboxFetchService.fetchOutbox(ps.userId, ps.includeAnnounce);
await this.apOutboxFetchService.fetchOutbox(ps.userId);
} catch (err) {
if (err instanceof IdentifiableError) {
if (err.id === '3fc5a089-cab4-48db-b9f3-f220574b3c0a') throw new ApiError(meta.errors.noSuchUser);
Expand All @@ -100,7 +95,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw (err);
}
} else {
this.apOutboxFetchService.fetchOutbox(ps.userId, ps.includeAnnounce);
this.apOutboxFetchService.fetchOutbox(ps.userId);
}
});
}
Expand Down
65 changes: 65 additions & 0 deletions packages/backend/test-federation/test/fetch-outbox.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { deepStrictEqual, strictEqual } from 'assert';
import * as Misskey from 'cherrypick-js';
import { createAccount, type LoginUser, resolveRemoteUser } from './utils.js';

describe('fetch-outbox', () => {
let alice: LoginUser, bob: LoginUser;
let bobInAliceHost: Misskey.entities.UserDetailedNotMe;
let bobNote: Misskey.entities.Note, bobRenote: Misskey.entities.Note;

beforeAll(async () => {
[alice, bob] = await Promise.all([
createAccount('a.test'),
createAccount('b.test'),
]);

[bobInAliceHost] = await Promise.all([
resolveRemoteUser('b.test', bob.id, alice),
]);
bobNote = (await bob.client.request('notes/create', { text: 'I am Bob!' })).createdNote;
bobRenote = (await bob.client.request('notes/create', { renoteId: bobNote.id })).createdNote;
});
test('New User', async () => {
await alice.client.request('ap/fetch-outbox', { userId: bobInAliceHost.id, wait: true });
const fetch_notes = await alice.client.request('users/notes', { userId: bobInAliceHost.id, withReplies: false, withRenotes: true });
strictEqual(fetch_notes.length, 2, JSON.stringify(fetch_notes));
deepStrictEqual(JSON.stringify(fetch_notes.map(note => {
return {
text: note.text,
createdAt: note.createdAt,
};
})), JSON.stringify([
{
text: bobRenote.text,
createdAt: bobRenote.createdAt,
}, {
text: bobNote.text,
createdAt: bobNote.createdAt,
},
]));
strictEqual(fetch_notes[0].renote?.id, fetch_notes[1].id);
});
test('Know User (cache hit)', async () => {
//キャッシュを利用するためこのノートは取得されない
await bob.client.request('notes/create', { text: 'Bob Note 2' });
await alice.client.request('ap/fetch-outbox', { userId: bobInAliceHost.id, wait: true });
const fetch_notes = await alice.client.request('users/notes', { userId: bobInAliceHost.id, withReplies: false, withRenotes: true });
//一度取得したノートは破棄されない
strictEqual(fetch_notes.length, 2, JSON.stringify(fetch_notes));
deepStrictEqual(JSON.stringify(fetch_notes.map(note => {
return {
text: note.text,
createdAt: note.createdAt,
};
})), JSON.stringify([
{
text: bobRenote.text,
createdAt: bobRenote.createdAt,
}, {
text: bobNote.text,
createdAt: bobNote.createdAt,
},
]));
strictEqual(fetch_notes[0].renote?.id, fetch_notes[1].id);
});
});
5 changes: 0 additions & 5 deletions packages/cherrypick-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12235,11 +12235,6 @@ export type operations = {
* @default false
*/
wait?: boolean;
/**
* @description Outbox取得の際にRenoteも対象にします
* @default false
*/
includeAnnounce?: boolean;
};
};
};
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/components/MkTutorialDialog.Note.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const exampleNote = reactive<Misskey.entities.Note>({
text: 'just setting up my crpk',
cw: null,
visibility: 'public',
searchableBy: 'public',
localOnly: false,
reactionAcceptance: null,
renoteCount: 0,
Expand Down
18 changes: 16 additions & 2 deletions packages/frontend/src/components/MkTutorialDialog.PostNote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,21 @@ SPDX-License-Identifier: AGPL-3.0-only
<b>{{ i18n.ts._initialTutorial._postNote._visibility.doNotSendConfidencialOnDirect1 }}</b> {{ i18n.ts._initialTutorial._postNote._visibility.doNotSendConfidencialOnDirect2 }}
</MkInfo>
</div>
<div><i class="ti ti-rocket-off"></i> <b>{{ i18n.ts._visibility.disableFederation }}</b> … {{ i18n.ts._initialTutorial._postNote._visibility.localOnly }}</div>
</div>
</MkFormSection>
<MkFormSection>
<template #label>{{ i18n.ts._initialTutorial._postNote._searchbility.title }}</template>
<div class="_gaps">
<div>{{ i18n.ts._initialTutorial._postNote._searchbility.description }}</div>
<div><i class="ti ti-world-search"></i> <b>{{ i18n.ts._searchbility.public }}</b> … {{ i18n.ts._initialTutorial._postNote._searchbility.public }}</div>
<div><i class="ti ti-user-search"></i> <b>{{ i18n.ts._searchbility.followersAndReacted }}</b> … {{ i18n.ts._initialTutorial._postNote._searchbility.followers }}</div>
<div><i class="ti ti-lock-search"></i> <b>{{ i18n.ts._searchbility.reactedOnly }}</b> … {{ i18n.ts._initialTutorial._postNote._searchbility.reactedOnly }}</div>
<div class="_gaps_s">
<div><i class="ti ti-mail-search"></i> <b>{{ i18n.ts._searchbility.private }}</b> … {{ i18n.ts._initialTutorial._postNote._searchbility.private }}</div>
</div>
<MkInfo :warn="true">
<b>{{ i18n.ts._initialTutorial._postNote._searchbility.notApplyRemote }}</b>
</MkInfo>
</div>
</MkFormSection>
<MkFormSection>
Expand Down Expand Up @@ -64,7 +78,7 @@ const exampleCWNote = reactive<Misskey.entities.Note>({
text: i18n.ts._initialTutorial._postNote._cw._exampleNote.note,
cw: i18n.ts._initialTutorial._postNote._cw._exampleNote.cw,
visibility: 'public',
localOnly: false,
searchableBy: 'public',
reactionAcceptance: null,
renoteCount: 0,
repliesCount: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const exampleNote = reactive<Misskey.entities.Note>({
text: i18n.ts._initialTutorial._howToMakeAttachmentsSensitive._exampleNote.note,
cw: null,
visibility: 'public',
searchableBy: 'public',
localOnly: false,
reactionAcceptance: null,
renoteCount: 0,
Expand Down
11 changes: 11 additions & 0 deletions packages/frontend/src/pages/timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const enableHomeTimeline = ref(defaultStore.state.enableHomeTimeline);
const enableLocalTimeline = ref(defaultStore.state.enableLocalTimeline);
const enableSocialTimeline = ref(defaultStore.state.enableSocialTimeline);
const enableGlobalTimeline = ref(defaultStore.state.enableGlobalTimeline);
const enableMediaTimeline = ref(defaultStore.state.enableMediaTimeline);
const enableListTimeline = ref(defaultStore.state.enableListTimeline);
const enableAntennaTimeline = ref(defaultStore.state.enableAntennaTimeline);
const enableTagTimeline = ref(defaultStore.state.enableTagTimeline);
Expand Down Expand Up @@ -224,6 +225,11 @@ watch(enableGlobalTimeline, (x) => {
reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});

watch(enableMediaTimeline, (x) => {
defaultStore.set('enableMediaTimeline', x);
reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});

watch(enableListTimeline, (x) => {
defaultStore.set('enableListTimeline', x);
reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
Expand Down Expand Up @@ -513,6 +519,11 @@ const headerActions = computed(() => {
text: i18n.ts._timelines.global,
icon: 'ti ti-world',
ref: enableGlobalTimeline,
}, {
type: 'switch',
text: i18n.ts._timelines.media,
icon: 'ti ti-photo',
ref: enableMediaTimeline,
}, { type: 'divider' }, {
type: 'switch',
text: i18n.ts.lists,
Expand Down
1 change: 0 additions & 1 deletion packages/frontend/src/scripts/get-user-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
os.apiWithDialog('ap/fetch-outbox', {
userId: user.id,
wait: true,
includeAnnounce: true,
});
}

Expand Down

0 comments on commit 8540e29

Please sign in to comment.