Skip to content

Commit 1bc4f40

Browse files
committed
Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
2 parents 458c72c + 6bd3ed2 commit 1bc4f40

27 files changed

+227
-72
lines changed

CHANGELOG.md

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
## 2024.10.2
1+
## 2024.11.0
22

33
### General
44
- Feat: コンテンツの表示にログインを必須にできるように
55
- Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
6+
- Enhance: 依存関係の更新
7+
- Enhance: l10nの更新
68

79
### Client
810
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
@@ -15,22 +17,34 @@
1517
- どのアカウントで認証しようとしているのかがわかるように
1618
- 認証するアカウントを切り替えられるように
1719
- Enhance: Self-XSS防止用の警告を追加
18-
- Enhance: カタルーニャ語 (ca-ES) に対応
20+
- Enhance: カタルーニャ語 (ca-ES) に対応
21+
- Enhance: 個別お知らせページではMetaタグを出力するように
1922
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
2023
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
2124
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
2225
- Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
2326
- Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
2427
- Fix: リンク切れを修正
28+
= Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
29+
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
30+
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
2531

2632
### Server
2733
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
2834
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
2935
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
36+
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
37+
- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
3038
- Fix: Nested proxy requestsを検出した際にブロックするように
3139
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
3240
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
3341
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
42+
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
43+
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
44+
- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正
45+
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
46+
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
47+
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
3448

3549
### Misskey.js
3650
- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正

CONTRIBUTING.md

+4
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ One should not add property that has defined before by other implementation, or
8383
## Reviewers guide
8484
Be willing to comment on the good points and not just the things you want fixed 💯
8585

86+
読んでおくといいやつ
87+
- https://blog.lacolaco.net/posts/1e2cf439b3c2/
88+
- https://konifar-zatsu.hatenadiary.jp/entry/2024/11/05/192421
89+
8690
### Review perspective
8791
- Scope
8892
- Are the goals of the PR clear?

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "misskey",
3-
"version": "2024.10.2-alpha.2",
3+
"version": "2024.11.0-alpha.0",
44
"codename": "nasubi",
55
"repository": {
66
"type": "git",

packages/backend/src/core/MfmService.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,10 @@ export class MfmService {
406406
mention: (node) => {
407407
const a = doc.createElement('a');
408408
const { username, host, acct } = node.props;
409-
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
410-
a.setAttribute('href', remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`);
409+
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username.toLowerCase() === username.toLowerCase() && remoteUser.host?.toLowerCase() === host?.toLowerCase());
410+
a.setAttribute('href', remoteUserInfo
411+
? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri)
412+
: `${this.config.url}/${acct.endsWith(`@${this.config.url}`) ? acct.substring(0, acct.length - this.config.url.length - 1) : acct}`);
411413
a.className = 'u-url mention';
412414
a.textContent = acct;
413415
return a;

packages/backend/src/misc/sql-like-escape.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
*/
55

66
export function sqlLikeEscape(s: string) {
7-
return s.replace(/([%_])/g, '\\$1');
7+
return s.replace(/([\\%_])/g, '\\$1');
88
}

packages/backend/src/server/ActivityPubServerService.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
2929
import { bindThis } from '@/decorators.js';
3030
import { IActivity } from '@/core/activitypub/type.js';
3131
import { isQuote, isRenote } from '@/misc/is-renote.js';
32+
import * as Acct from '@/misc/acct.js';
3233
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify';
3334
import type { FindOptionsWhere } from 'typeorm';
3435

@@ -486,6 +487,16 @@ export class ActivityPubServerService {
486487
return;
487488
}
488489

490+
// リモートだったらリダイレクト
491+
if (user.host != null) {
492+
if (user.uri == null || this.utilityService.isSelfHost(user.host)) {
493+
reply.code(500);
494+
return;
495+
}
496+
reply.redirect(user.uri, 301);
497+
return;
498+
}
499+
489500
reply.header('Cache-Control', 'public, max-age=180');
490501
this.setResponseType(request, reply);
491502
return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as MiLocalUser)));
@@ -654,19 +665,20 @@ export class ActivityPubServerService {
654665

655666
const user = await this.usersRepository.findOneBy({
656667
id: userId,
657-
host: IsNull(),
658668
isSuspended: false,
659669
});
660670

661671
return await this.userInfo(request, reply, user);
662672
});
663673

664-
fastify.get<{ Params: { user: string; } }>('/@:user', { constraints: { apOrHtml: 'ap' } }, async (request, reply) => {
674+
fastify.get<{ Params: { acct: string; } }>('/@:acct', { constraints: { apOrHtml: 'ap' } }, async (request, reply) => {
665675
vary(reply.raw, 'Accept');
666676

677+
const acct = Acct.parse(request.params.acct);
678+
667679
const user = await this.usersRepository.findOneBy({
668-
usernameLower: request.params.user.toLowerCase(),
669-
host: IsNull(),
680+
usernameLower: acct.username,
681+
host: acct.host ?? IsNull(),
670682
isSuspended: false,
671683
});
672684

packages/backend/src/server/api/endpoints/i/update.ts

+6
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
465465
const newName = updates.name === undefined ? user.name : updates.name;
466466
const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
467467
const newFields = profileUpdates.fields === undefined ? profile.fields : profileUpdates.fields;
468+
const newFollowedMessage = profileUpdates.followedMessage === undefined ? profile.followedMessage : profileUpdates.followedMessage;
468469

469470
if (newName != null) {
470471
let hasProhibitedWords = false;
@@ -494,6 +495,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
494495
]);
495496
}
496497

498+
if (newFollowedMessage != null) {
499+
const tokens = mfm.parse(newFollowedMessage);
500+
emojis = emojis.concat(extractCustomEmojisFromMfm(tokens));
501+
}
502+
497503
updates.emojis = emojis;
498504
updates.tags = tags;
499505

packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
112112

113113
this.activeUsersChart.read(me);
114114

115-
await this.noteEntityService.packMany(timeline, me);
115+
return await this.noteEntityService.packMany(timeline, me);
116116
}
117117

118118
const timeline = await this.fanoutTimelineEndpointService.timeline({

packages/backend/src/server/web/ClientServerService.ts

+36-1
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,26 @@ import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
4242
import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
4343
import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
4444
import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
45-
import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
45+
import type {
46+
AnnouncementsRepository,
47+
ChannelsRepository,
48+
ClipsRepository,
49+
FlashsRepository,
50+
GalleryPostsRepository,
51+
MiMeta,
52+
NotesRepository,
53+
PagesRepository,
54+
ReversiGamesRepository,
55+
UserProfilesRepository,
56+
UsersRepository,
57+
} from '@/models/_.js';
4658
import type Logger from '@/logger.js';
4759
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
4860
import { bindThis } from '@/decorators.js';
4961
import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
5062
import { RoleService } from '@/core/RoleService.js';
5163
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
64+
import { AnnouncementEntityService } from '@/core/entities/AnnouncementEntityService.js';
5265
import { FeedService } from './FeedService.js';
5366
import { UrlPreviewService } from './UrlPreviewService.js';
5467
import { ClientLoggerService } from './ClientLoggerService.js';
@@ -103,6 +116,9 @@ export class ClientServerService {
103116
@Inject(DI.reversiGamesRepository)
104117
private reversiGamesRepository: ReversiGamesRepository,
105118

119+
@Inject(DI.announcementsRepository)
120+
private announcementsRepository: AnnouncementsRepository,
121+
106122
private flashEntityService: FlashEntityService,
107123
private userEntityService: UserEntityService,
108124
private noteEntityService: NoteEntityService,
@@ -112,6 +128,7 @@ export class ClientServerService {
112128
private clipEntityService: ClipEntityService,
113129
private channelEntityService: ChannelEntityService,
114130
private reversiGameEntityService: ReversiGameEntityService,
131+
private announcementEntityService: AnnouncementEntityService,
115132
private urlPreviewService: UrlPreviewService,
116133
private feedService: FeedService,
117134
private roleService: RoleService,
@@ -776,6 +793,24 @@ export class ClientServerService {
776793
return await renderBase(reply);
777794
}
778795
});
796+
797+
// 個別お知らせページ
798+
fastify.get<{ Params: { announcementId: string; } }>('/announcements/:announcementId', async (request, reply) => {
799+
const announcement = await this.announcementsRepository.findOneBy({
800+
id: request.params.announcementId,
801+
});
802+
803+
if (announcement) {
804+
const _announcement = await this.announcementEntityService.pack(announcement);
805+
reply.header('Cache-Control', 'public, max-age=3600');
806+
return await reply.view('announcement', {
807+
announcement: _announcement,
808+
...await this.generateCommonPugData(this.meta),
809+
});
810+
} else {
811+
return await renderBase(reply);
812+
}
813+
});
779814
//#endregion
780815

781816
//#region noindex pages
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
extends ./base
2+
3+
block vars
4+
- const title = announcement.title;
5+
- const description = announcement.text.length > 100 ? announcement.text.slice(0, 100) + '' : announcement.text;
6+
- const url = `${config.url}/announcements/${announcement.id}`;
7+
8+
block title
9+
= `${title} | ${instanceName}`
10+
11+
block desc
12+
meta(name='description' content=description)
13+
14+
block og
15+
meta(property='og:type' content='article')
16+
meta(property='og:title' content= title)
17+
meta(property='og:description' content= description)
18+
meta(property='og:url' content= url)
19+
if announcement.imageUrl
20+
meta(property='og:image' content=announcement.imageUrl)
21+
meta(property='twitter:card' content='summary_large_image')

packages/backend/src/server/web/views/base.pug

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ block vars
22

33
block loadClientEntry
44
- const entry = config.frontendEntry;
5+
- const baseUrl = config.url;
56

67
doctype html
78

@@ -32,7 +33,7 @@ html
3233
link(rel='icon' href= icon || '/favicon.ico')
3334
link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png')
3435
link(rel='manifest' href='/manifest.json')
35-
link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`)
36+
link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${baseUrl}/opensearch.xml`)
3637
link(rel='prefetch' href=serverErrorImageUrl)
3738
link(rel='prefetch' href=infoImageUrl)
3839
link(rel='prefetch' href=notFoundImageUrl)

packages/backend/test/e2e/fetch-resource.ts

+2
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ describe('Webリソース', () => {
230230
path: path('xxxxxxxxxx'),
231231
type: HTML,
232232
}));
233+
test.todo('HTMLとしてGETできる。(リモートユーザーでもリダイレクトせず)');
233234
});
234235

235236
describe.each([
@@ -249,6 +250,7 @@ describe('Webリソース', () => {
249250
path: path('xxxxxxxxxx'),
250251
accept,
251252
}));
253+
test.todo('はオリジナルにリダイレクトされる。(リモートユーザー)');
252254
});
253255
});
254256

packages/frontend/src/boot/common.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { updateI18n, i18n } from '@/i18n.js';
1515
import { $i, refreshAccount, login } from '@/account.js';
1616
import { defaultStore, ColdDeviceStorage } from '@/store.js';
1717
import { fetchInstance, instance } from '@/instance.js';
18-
import { deviceKind } from '@/scripts/device-kind.js';
18+
import { deviceKind, updateDeviceKind } from '@/scripts/device-kind.js';
1919
import { reloadChannel } from '@/scripts/unison-reload.js';
2020
import { getUrlWithoutLoginId } from '@/scripts/login-id.js';
2121
import { getAccountFromId } from '@/scripts/get-account-from-id.js';
@@ -185,6 +185,10 @@ export async function common(createVue: () => App<Element>) {
185185
}
186186
});
187187

188+
watch(defaultStore.reactiveState.overridedDeviceKind, (kind) => {
189+
updateDeviceKind(kind);
190+
}, { immediate: true });
191+
188192
watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
189193
document.documentElement.style.setProperty('--MI-modalBgFilter', v ? 'blur(4px)' : 'none');
190194
}, { immediate: true });

packages/frontend/src/components/MkMediaVideo.vue

+20-23
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ import { hms } from '@/filters/hms.js';
118118
import { defaultStore } from '@/store.js';
119119
import { i18n } from '@/i18n.js';
120120
import * as os from '@/os.js';
121-
import { isFullscreenNotSupported } from '@/scripts/device-kind.js';
121+
import { exitFullscreen, requestFullscreen } from '@/scripts/fullscreen.js';
122122
import hasAudio from '@/scripts/media-has-audio.js';
123123
import MkMediaRange from '@/components/MkMediaRange.vue';
124124
import { $i, iAmModerator } from '@/account.js';
@@ -334,26 +334,21 @@ function togglePlayPause() {
334334
}
335335

336336
function toggleFullscreen() {
337-
if (isFullscreenNotSupported && videoEl.value) {
338-
if (isFullscreen.value) {
339-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
340-
//@ts-ignore
341-
videoEl.value.webkitExitFullscreen();
342-
isFullscreen.value = false;
343-
} else {
344-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
345-
//@ts-ignore
346-
videoEl.value.webkitEnterFullscreen();
347-
isFullscreen.value = true;
348-
}
349-
} else if (playerEl.value) {
350-
if (isFullscreen.value) {
351-
document.exitFullscreen();
352-
isFullscreen.value = false;
353-
} else {
354-
playerEl.value.requestFullscreen({ navigationUI: 'hide' });
355-
isFullscreen.value = true;
356-
}
337+
if (playerEl.value == null || videoEl.value == null) return;
338+
if (isFullscreen.value) {
339+
exitFullscreen({
340+
videoEl: videoEl.value,
341+
});
342+
isFullscreen.value = false;
343+
} else {
344+
requestFullscreen({
345+
videoEl: videoEl.value,
346+
playerEl: playerEl.value,
347+
options: {
348+
navigationUI: 'hide',
349+
},
350+
});
351+
isFullscreen.value = true;
357352
}
358353
}
359354

@@ -454,8 +449,10 @@ watch(loop, (to) => {
454449
});
455450

456451
watch(hide, (to) => {
457-
if (to && isFullscreen.value) {
458-
document.exitFullscreen();
452+
if (videoEl.value && to && isFullscreen.value) {
453+
exitFullscreen({
454+
videoEl: videoEl.value,
455+
});
459456
isFullscreen.value = false;
460457
}
461458
});

0 commit comments

Comments
 (0)