Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge 2024.8.0 to generic #14433

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
813d8b7
feat: initial commit for vkemo relay as a copy of global timeline
anatawa12 Apr 11, 2024
287aecf
feat: filter notes from non-vkemo servers
anatawa12 Apr 11, 2024
72766f7
feat: filter notes in endpoint version of vkemo relay
anatawa12 Apr 11, 2024
8c49825
feat: fetch instance list from API
anatawa12 Apr 11, 2024
242f503
chore: rename vkemo -> vmimi
anatawa12 Apr 11, 2024
9f607cb
chore: update misskey-js
anatawa12 Apr 11, 2024
aecac19
chore: set icon for vmimi relay tl
anatawa12 Apr 11, 2024
ce06c80
chore(i18n): ぶいみみリレー
anatawa12 Apr 11, 2024
5f79f2d
chore: retry when error returned from relay server
anatawa12 Apr 11, 2024
312340c
feat: withReplies for vmimi relay timeline
anatawa12 Apr 11, 2024
613a6f8
fix: if withReplies is false for the user in following, note is remov…
anatawa12 Apr 12, 2024
1c71111
chore(vmimi-relay): reimplement with FFT
anatawa12 Apr 15, 2024
59211d9
chore(vmimi-relay): VRTLのwithRepliesの仕様をLTLに揃える
anatawa12 Apr 16, 2024
835f752
feat(vmimi-relay): vmimi relay hybrid timeline
anatawa12 Apr 16, 2024
390b53d
feat(vmimi-relay/frontend): virtual kemomimi relay social timeline
anatawa12 Apr 16, 2024
bfa5f42
chore: ぶいみみリレーソーシャル > ぶいみみソーシャル
anatawa12 Apr 17, 2024
efe9cc6
feat: ぶいみみタイムラインに説明を追加
anatawa12 Apr 17, 2024
3c1d39f
fix: vrtlAvailableをwebからいじれない
anatawa12 Apr 17, 2024
490bd1f
fix: featuresの命名が揃っていない
anatawa12 Apr 17, 2024
a0e1d5a
Merge tag 'refs/tags/2024.5.0' into vmimi-relay-timeline
anatawa12 May 31, 2024
9d25ad9
chore: reimplement mute system with new APIs
anatawa12 May 31, 2024
6a2cf7d
Merge pull request #25 from anatawa12/vmimi-relay-timeline-merge-2024…
anatawa12 May 31, 2024
cbfb898
VRTL available for nodeinfo (#29)
anatawa12 Jun 13, 2024
aa00eb8
Fix replies to me are not included in V[RS]TL if withReplies is disab…
anatawa12 Jun 14, 2024
843152d
fix: Fix VRTL/VSTL is not avaiable on timeline widgets (#33)
anatawa12 Jun 16, 2024
c947c19
CHANGELOGを日本語に (#35)
anatawa12 Jun 16, 2024
24be6b1
VRTL/VSTLに連合なし投稿を含めるかを選択可能に (#36)
anatawa12 Jun 16, 2024
1dd7398
chore(backend): VRTL参加サーバーの取得に失敗したときのリトライの間隔を短く (#38)
anatawa12 Jun 16, 2024
03707e0
Merge tag '2024.7.0' into vmimi-relay-timeline/merge-2024.7.0
anatawa12 Jul 31, 2024
18ebf1c
Merge pull request #81 from anatawa12/vmimi-relay-timeline/merge-2024…
anatawa12 Jul 31, 2024
19eb8d4
fix: V[RS]TL doesn't have withReplies toggle (#92)
anatawa12 Aug 4, 2024
1203f24
fix(frontend): VRTL VSTLの名前が表示されないところがある問題 (#97)
anatawa12 Aug 7, 2024
bd71bbc
Merge tag 'refs/tags/2024.8.0' into vmimi-relay-timeline/merge-2024.8.0
anatawa12 Aug 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG-VRTL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# CHANGELOG about VRTL

VRTLのブランチで行われた変更点をまとめています

<!-- VV Please add changelog here VV -->
- fix(frontend): VRTL VSTLの名前が表示されないところがある問題 (anatawa12#97) - 2024/08/07
- fic(frontend): VRTL VSTLでリプライのトグルが表示されない問題 (anatawa12#92) - 2024/08/04
- chore(backend): VRTL参加サーバーの取得に失敗したときのリトライの間隔を短く
- feat: VRTL/VSTLに連合なし投稿を含めるかを選択可能に
- もともとのVRTL/VSTLでは連合なし投稿が常に含まれていましたが、正しくVRTL/VSTLのノートを表現するために含めないようにできるようになりました
- VSTLの場合、連合なし投稿を含めないようにしてもフォローしている人の連合なし投稿は表示されます
- fix(frontend): ウィジェットでVRTL/VSTLが使用できない問題を修正
- fix(backend): 自分自身に対するリプライがwithReplies = falseなVRTL/VSTLにて含まれていない問題を修正
- feat(backend): `vmimiRelayTimelineImplemented` と `disableVmimiRelayTimeline` nodeinfo に追加しました
- これによりサードパーティクライアントがVRTLの有無を認知できるようになりました。
24 changes: 24 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4780,6 +4780,10 @@ export interface Locale extends ILocale {
* TLに現在フォロー中の人全員の返信を含めないようにする
*/
"hideRepliesToOthersInTimelineAll": string;
/**
* TLに連合なし投稿を含める
*/
"showLocalOnlyInTimeline": string;
/**
* この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?
*/
Expand Down Expand Up @@ -5507,6 +5511,14 @@ export interface Locale extends ILocale {
* グローバルタイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。
*/
"global": string;
/**
* ぶいみみリレータイムラインでは、バーチャルケモミミリレーサーバーに参加しているサーバーのユーザー全員の投稿を見られます。
*/
"vmimi-relay": string;
/**
* ぶいみみソーシャルタイムラインには、ホームタイムラインとぶいみみリレータイムラインの投稿が両方表示されます。
*/
"vmimi-relay-social": string;
};
"_serverRules": {
/**
Expand Down Expand Up @@ -6638,6 +6650,10 @@ export interface Locale extends ILocale {
* ローカルタイムラインの閲覧
*/
"ltlAvailable": string;
/**
* ぶいみみリレータイムラインの閲覧
*/
"vrtlAvailable": string;
/**
* パブリック投稿の許可
*/
Expand Down Expand Up @@ -8789,6 +8805,14 @@ export interface Locale extends ILocale {
* グローバル
*/
"global": string;
/**
* ぶいみみリレー
*/
"vmimi-relay": string;
/**
* ぶいみみソーシャル
*/
"vmimi-relay-social": string;
};
"_play": {
/**
Expand Down
6 changes: 6 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ showRepliesToOthersInTimeline: "TLに他の人への返信を含める"
hideRepliesToOthersInTimeline: "TLに他の人への返信を含めない"
showRepliesToOthersInTimelineAll: "TLに現在フォロー中の人全員の返信を含めるようにする"
hideRepliesToOthersInTimelineAll: "TLに現在フォロー中の人全員の返信を含めないようにする"
showLocalOnlyInTimeline: "TLに連合なし投稿を含める"
confirmShowRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?"
confirmHideRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めないようにしますか?"
externalServices: "外部サービス"
Expand Down Expand Up @@ -1389,6 +1390,8 @@ _timelineDescription:
local: "ローカルタイムラインでは、このサーバーにいるユーザー全員の投稿を見られます。"
social: "ソーシャルタイムラインには、ホームタイムラインとローカルタイムラインの投稿が両方表示されます。"
global: "グローバルタイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。"
vmimi-relay: "ぶいみみリレータイムラインでは、バーチャルケモミミリレーサーバーに参加しているサーバーのユーザー全員の投稿を見られます。"
vmimi-relay-social: "ぶいみみソーシャルタイムラインには、ホームタイムラインとぶいみみリレータイムラインの投稿が両方表示されます。"

_serverRules:
description: "新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。"
Expand Down Expand Up @@ -1716,6 +1719,7 @@ _role:
_options:
gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧"
vrtlAvailable: "ぶいみみリレータイムラインの閲覧"
canPublicNote: "パブリック投稿の許可"
mentionMax: "ノート内の最大メンション数"
canInvite: "サーバー招待コードの発行"
Expand Down Expand Up @@ -2319,6 +2323,8 @@ _timelines:
local: "ローカル"
social: "ソーシャル"
global: "グローバル"
vmimi-relay: "ぶいみみリレー"
vmimi-relay-social: "ぶいみみソーシャル"

_play:
new: "Playの作成"
Expand Down
16 changes: 16 additions & 0 deletions packages/backend/migration/1713168415416-VmimiRelayTimeline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: anatawa12 and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class VmimiRelayTimeline1713168415416 {
name = 'VmimiRelayTimeline1713168415416'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "vmimiRelayTimelineCacheMax" integer NOT NULL DEFAULT '300'`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "vmimiRelayTimelineCacheMax"`);
}
}
6 changes: 6 additions & 0 deletions packages/backend/src/core/CoreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,14 @@ import { ApMentionService } from './activitypub/models/ApMentionService.js';
import { ApNoteService } from './activitypub/models/ApNoteService.js';
import { ApPersonService } from './activitypub/models/ApPersonService.js';
import { ApQuestionService } from './activitypub/models/ApQuestionService.js';
import { VmimiRelayTimelineService } from './VmimiRelayTimelineService.js';
import { QueueModule } from './QueueModule.js';
import { QueueService } from './QueueService.js';
import { LoggerService } from './LoggerService.js';
import type { Provider } from '@nestjs/common';

//#region 文字列ベースでのinjection用(循環参照対応のため)
const $VmimiRelayTimelineService: Provider = { provide: 'VmimiRelayTimelineService', useExisting: VmimiRelayTimelineService };
const $LoggerService: Provider = { provide: 'LoggerService', useExisting: LoggerService };
const $AbuseReportService: Provider = { provide: 'AbuseReportService', useExisting: AbuseReportService };
const $AbuseReportNotificationService: Provider = { provide: 'AbuseReportNotificationService', useExisting: AbuseReportNotificationService };
Expand Down Expand Up @@ -300,6 +302,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
QueueModule,
],
providers: [
VmimiRelayTimelineService,
LoggerService,
AbuseReportService,
AbuseReportNotificationService,
Expand Down Expand Up @@ -444,6 +447,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
QueueService,

//#region 文字列ベースでのinjection用(循環参照対応のため)
$VmimiRelayTimelineService,
$LoggerService,
$AbuseReportService,
$AbuseReportNotificationService,
Expand Down Expand Up @@ -588,6 +592,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
//#endregion
],
exports: [
VmimiRelayTimelineService,
QueueModule,
LoggerService,
AbuseReportService,
Expand Down Expand Up @@ -732,6 +737,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
QueueService,

//#region 文字列ベースでのinjection用(循環参照対応のため)
$VmimiRelayTimelineService,
$LoggerService,
$AbuseReportService,
$AbuseReportNotificationService,
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/core/FanoutTimelineService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export type FanoutTimelineName =
// role timelines
| `roleTimeline:${string}` // any notes are included

// vmimi relay timelines
| 'vmimiRelayTimeline' // replies are not included
| 'vmimiRelayTimelineWithFiles' // only non-reply notes with files are included
| 'vmimiRelayTimelineWithReplies' // only replies are included
| `vmimiRelayTimelineWithReplyTo:${string}` // Only replies to specific local user are included. Parameter is reply user id.

@Injectable()
export class FanoutTimelineService {
constructor(
Expand Down
14 changes: 14 additions & 0 deletions packages/backend/src/core/NoteCreateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { NoteReadService } from '@/core/NoteReadService.js';
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
import { bindThis } from '@/decorators.js';
import { DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js';
import { VmimiRelayTimelineService } from '@/core/VmimiRelayTimelineService.js';
import { RoleService } from '@/core/RoleService.js';
import { MetaService } from '@/core/MetaService.js';
import { SearchService } from '@/core/SearchService.js';
Expand Down Expand Up @@ -192,6 +193,7 @@ export class NoteCreateService implements OnApplicationShutdown {
@Inject(DI.channelFollowingsRepository)
private channelFollowingsRepository: ChannelFollowingsRepository,

private vmimiRelayTimelineService: VmimiRelayTimelineService,
private userEntityService: UserEntityService,
private noteEntityService: NoteEntityService,
private idService: IdService,
Expand Down Expand Up @@ -956,6 +958,12 @@ export class NoteCreateService implements OnApplicationShutdown {
this.fanoutTimelineService.push(`localTimelineWithReplyTo:${note.replyUserId}`, note.id, 300 / 10, r);
}
}
if (note.visibility === 'public' && this.vmimiRelayTimelineService.isRelayedInstance(note.userHost) && !note.localOnly) {
this.fanoutTimelineService.push('vmimiRelayTimelineWithReplies', note.id, meta.vmimiRelayTimelineCacheMax, r);
if (note.replyUserHost == null) {
this.fanoutTimelineService.push(`vmimiRelayTimelineWithReplyTo:${note.replyUserId}`, note.id, meta.vmimiRelayTimelineCacheMax / 10, r);
}
}
} else {
this.fanoutTimelineService.push(`userTimeline:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
if (note.fileIds.length > 0) {
Expand All @@ -968,6 +976,12 @@ export class NoteCreateService implements OnApplicationShutdown {
this.fanoutTimelineService.push('localTimelineWithFiles', note.id, 500, r);
}
}
if (note.visibility === 'public' && this.vmimiRelayTimelineService.isRelayedInstance(note.userHost) && !note.localOnly) {
this.fanoutTimelineService.push('vmimiRelayTimeline', note.id, meta.vmimiRelayTimelineCacheMax, r);
if (note.fileIds.length > 0) {
this.fanoutTimelineService.push('vmimiRelayTimelineWithFiles', note.id, meta.vmimiRelayTimelineCacheMax / 2, r);
}
}
}

if (Math.random() < 0.1) {
Expand Down
3 changes: 3 additions & 0 deletions packages/backend/src/core/RoleService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { NotificationService } from '@/core/NotificationService.js';
import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';

export type RolePolicies = {
vrtlAvailable: boolean;
gtlAvailable: boolean;
ltlAvailable: boolean;
canPublicNote: boolean;
Expand Down Expand Up @@ -61,6 +62,7 @@ export type RolePolicies = {
};

export const DEFAULT_POLICIES: RolePolicies = {
vrtlAvailable: true,
gtlAvailable: true,
ltlAvailable: true,
canPublicNote: true,
Expand Down Expand Up @@ -361,6 +363,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
}

return {
vrtlAvailable: calc('vrtlAvailable', vs => vs.some(v => v === true)),
gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)),
ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)),
canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)),
Expand Down
82 changes: 82 additions & 0 deletions packages/backend/src/core/VmimiRelayTimelineService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { Injectable } from '@nestjs/common';
import { Brackets, SelectQueryBuilder } from 'typeorm';
import { bindThis } from '@/decorators.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js';

type VmimiInstanceList = { Url: string; }[];

// one day
const UpdateInterval = 1000 * 60 * 60 * 24; // 24 hours = 1 day
const MinRetryInterval = 1000 * 60; // one minutes
const MaxRetryInterval = 1000 * 60 * 60 * 6; // 6 hours

@Injectable()
export class VmimiRelayTimelineService {
instanceHosts: Set<string>;
instanceHostsArray: string[];
nextUpdate: number;
nextRetryInterval: number;
updatePromise: Promise<void> | null;
private logger: Logger;

constructor(
private httpRequestService: HttpRequestService,
private loggerService: LoggerService,
) {
// Initialize with
this.instanceHosts = new Set<string>([]);
this.instanceHostsArray = [];
this.nextUpdate = 0;
this.nextRetryInterval = MinRetryInterval;
this.updatePromise = null;

this.logger = this.loggerService.getLogger('vmimi');

this.checkForUpdateInstanceList();
}

@bindThis
checkForUpdateInstanceList() {
if (this.updatePromise == null && this.nextUpdate < Date.now()) {
this.updatePromise = this.updateInstanceList().finally(() => this.updatePromise = null);
}
}

@bindThis
async updateInstanceList() {
try {
this.logger.info('Updating instance list');
const instanceList = await this.httpRequestService.getJson<VmimiInstanceList>('https://relay.virtualkemomimi.net/api/servers');
this.instanceHostsArray = instanceList.map(i => new URL(i.Url).host);
this.instanceHosts = new Set<string>(this.instanceHostsArray);
this.nextUpdate = Date.now() + UpdateInterval;
this.logger.info(`Got instance list: ${this.instanceHostsArray}`);
this.nextRetryInterval = MinRetryInterval;
} catch (e) {
this.logger.error('Failed to update instance list', e as any);
this.nextUpdate = Date.now() + this.nextRetryInterval;
setTimeout(() => this.checkForUpdateInstanceList(), this.nextRetryInterval + 5);
this.nextRetryInterval = Math.min(this.nextRetryInterval * 2, MaxRetryInterval);
}
}

@bindThis
isRelayedInstance(host: string | null): boolean {
this.checkForUpdateInstanceList();
// assuming the current instance is joined to the i relay
if (host == null) return true;
return this.instanceHosts.has(host);
}

get hostNames (): string[] {
this.checkForUpdateInstanceList();
return this.instanceHostsArray;
}
}
1 change: 1 addition & 0 deletions packages/backend/src/core/entities/MetaEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export class MetaEntityService {
features: {
localTimeline: instance.policies.ltlAvailable,
globalTimeline: instance.policies.gtlAvailable,
vmimiRelayTimeline: instance.policies.vrtlAvailable,
registration: !instance.disableRegistration,
emailRequiredForSignup: instance.emailRequiredForSignup,
hcaptcha: instance.enableHcaptcha,
Expand Down
5 changes: 5 additions & 0 deletions packages/backend/src/models/Meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@ export class MiMeta {
})
public preservedUsernames: string[];

@Column('integer', {
default: 300,
})
public vmimiRelayTimelineCacheMax: number;

@Column('boolean', {
default: true,
})
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/models/json-schema/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ export const packedMetaDetailedOnlySchema = {
type: 'boolean',
optional: false, nullable: false,
},
vmimiRelayTimeline: {
type: 'boolean',
optional: false, nullable: false,
},
hcaptcha: {
type: 'boolean',
optional: false, nullable: false,
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/models/json-schema/role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ export const packedRolePoliciesSchema = {
type: 'object',
optional: false, nullable: false,
properties: {
vrtlAvailable: {
type: 'boolean',
optional: false, nullable: false,
},
gtlAvailable: {
type: 'boolean',
optional: false, nullable: false,
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/server/NodeinfoServerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ export class NodeinfoServerService {
disableRegistration: meta.disableRegistration,
disableLocalTimeline: !basePolicies.ltlAvailable,
disableGlobalTimeline: !basePolicies.gtlAvailable,
vmimiRelayTimelineImplemented: true,
disableVmimiRelayTimeline: !basePolicies.vrtlAvailable,
emailRequiredForSignup: meta.emailRequiredForSignup,
enableHcaptcha: meta.enableHcaptcha,
enableRecaptcha: meta.enableRecaptcha,
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/server/ServerModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { AntennaChannelService } from './api/stream/channels/antenna.js';
import { ChannelChannelService } from './api/stream/channels/channel.js';
import { DriveChannelService } from './api/stream/channels/drive.js';
import { GlobalTimelineChannelService } from './api/stream/channels/global-timeline.js';
import { VmimiRelayTimelineChannelService } from './api/stream/channels/vmimi-relay-timeline.js';
import { VmimiRelayHybridTimelineChannelService } from './api/stream/channels/vmimi-relay-hybrid-timeline.js';
import { HashtagChannelService } from './api/stream/channels/hashtag.js';
import { HomeTimelineChannelService } from './api/stream/channels/home-timeline.js';
import { HybridTimelineChannelService } from './api/stream/channels/hybrid-timeline.js';
Expand Down Expand Up @@ -80,6 +82,8 @@ import { ReversiGameChannelService } from './api/stream/channels/reversi-game.js
ChannelChannelService,
DriveChannelService,
GlobalTimelineChannelService,
VmimiRelayTimelineChannelService,
VmimiRelayHybridTimelineChannelService,
HashtagChannelService,
RoleTimelineChannelService,
ReversiChannelService,
Expand Down
Loading
Loading