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

feat: vみみソーシャルTL #2

Merged
merged 5 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ _initialTutorial:
local: "You can view notes from all users on this server."
social: "Notes from the Home and Local timelines will be displayed."
global: "You can view notes from all connected servers."
vmimi: "Notes from Virtual Kemomimi Relay and local will be displayed."
description2: "You can switch between timelines at the top of the screen at any time."
description3: "Additionally, there are list timelines and channel timelines. For more details, please refer to {link}."
_postNote:
Expand Down Expand Up @@ -1383,6 +1384,7 @@ _timelineDescription:
local: "In the Local timeline, you can see notes from all users on this server."
social: "The Social timeline displays notes from both the Home and Local timelines."
global: "In the Global timeline, you can see notes from all connected servers."
vmimi: "In the Vmimi Timeline, you can see notes from the Virtual Kemomimi Relay and local timelines."
_serverRules:
description: "A set of rules to be displayed before registration. Setting a summary of the Terms of Service is recommended."
_serverSettings:
Expand Down Expand Up @@ -2266,6 +2268,7 @@ _timelines:
local: "Local"
social: "Social"
global: "Global"
vmimi: "Vmimi"
_play:
new: "Create Play"
edit: "Edit Play"
Expand Down
32 changes: 32 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4988,6 +4988,10 @@ export interface Locale extends ILocale {
* センシティブなファイルを含むノートを表示
*/
readonly "withSensitive": string;
/**
* ローカルのみのノートを表示
*/
readonly "showLocalOnlyInTimeline": string;
/**
* {name}のセンシティブなファイルを含む投稿
*/
Expand Down Expand Up @@ -5370,6 +5374,14 @@ export interface Locale extends ILocale {
* 接続している他のすべてのサーバーからの投稿を見られます。
*/
readonly "global": string;
/**
* VirtualKemomimiリレーに参加しているサーバーからの投稿を見られます。
*/
readonly "vmimi": string;
/**
* Vみみタイムラインの投稿とホームタイムラインの投稿が両方表示されます。
*/
readonly "vmimiHybrid": string;
/**
* それぞれのタイムラインは、画面上部でいつでも切り替えられます。
*/
Expand Down Expand Up @@ -5507,6 +5519,14 @@ export interface Locale extends ILocale {
* グローバルタイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。
*/
readonly "global": string;
/**
* Vみみタイムラインでは、VirtualKemomimiリレーに参加しているサーバーからの投稿を見られます。
*/
readonly "vmimi": string;
/**
* Vみみソーシャルタイムラインでは、Vみみタイムラインとホームタイムラインの両方の投稿を表示することができます。
*/
readonly "vmimiHybrid": string;
};
readonly "_serverRules": {
/**
Expand Down Expand Up @@ -6630,6 +6650,10 @@ export interface Locale extends ILocale {
readonly "high": string;
};
readonly "_options": {
/**
* Vミミタイムラインの閲覧
*/
readonly "vrtlAvailable": string;
/**
* グローバルタイムラインの閲覧
*/
Expand Down Expand Up @@ -8789,6 +8813,14 @@ export interface Locale extends ILocale {
* グローバル
*/
readonly "global": string;
/**
* Vみみ
*/
readonly "vmimi": string;
/**
* Vみみソーシャル
*/
readonly "vmimiHybrid": string;
};
readonly "_play": {
/**
Expand Down
8 changes: 8 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ lastNDays: "直近{n}日"
backToTitle: "タイトルへ"
hemisphere: "お住まいの地域"
withSensitive: "センシティブなファイルを含むノートを表示"
showLocalOnlyInTimeline: "ローカルのみのノートを表示"
userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿"
enableHorizontalSwipe: "スワイプしてタブを切り替える"
loading: "読み込み中"
Expand Down Expand Up @@ -1350,6 +1351,8 @@ _initialTutorial:
local: "このサーバーにいるユーザー全員の投稿を見られます。"
social: "ホームタイムラインとローカルタイムラインの投稿が両方表示されます。"
global: "接続している他のすべてのサーバーからの投稿を見られます。"
vmimi: "VirtualKemomimiリレーに参加しているサーバーからの投稿を見られます。"
vmimiHybrid: "Vみみタイムラインの投稿とホームタイムラインの投稿が両方表示されます。"
description2: "それぞれのタイムラインは、画面上部でいつでも切り替えられます。"
description3: "その他にも、リストタイムラインやチャンネルタイムラインなどがあります。詳しくは{link}をご覧ください。"
_postNote:
Expand Down Expand Up @@ -1389,6 +1392,8 @@ _timelineDescription:
local: "ローカルタイムラインでは、このサーバーにいるユーザー全員の投稿を見られます。"
social: "ソーシャルタイムラインには、ホームタイムラインとローカルタイムラインの投稿が両方表示されます。"
global: "グローバルタイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。"
vmimi: "Vみみタイムラインでは、VirtualKemomimiリレーに参加しているサーバーからの投稿を見られます。"
vmimiHybrid: "Vみみソーシャルタイムラインでは、Vみみタイムラインとホームタイムラインの両方の投稿を表示することができます。"

_serverRules:
description: "新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。"
Expand Down Expand Up @@ -1714,6 +1719,7 @@ _role:
middle: "中"
high: "高"
_options:
vrtlAvailable: "Vミミタイムラインの閲覧"
gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧"
canPublicNote: "パブリック投稿の許可"
Expand Down Expand Up @@ -2319,6 +2325,8 @@ _timelines:
local: "ローカル"
social: "ソーシャル"
global: "グローバル"
vmimi: "Vみみ"
vmimiHybrid: "Vみみソーシャル"

_play:
new: "Playの作成"
Expand Down
4 changes: 4 additions & 0 deletions locales/ja-KS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ _initialTutorial:
local: "このサーバーの中におる全員の投稿が見れるで。"
social: "ホームタイムラインの投稿もローカルタイムラインのも一緒に見れるで。"
global: "繋がってる他の全サーバーからの投稿が見れるで。"
vmimi: "Virtual Kemomimiリレーに参加してるサーバーの投稿が見れるで。"
description2: "それぞれのタイムラインは、いつでも画面上で切り替えられんねん。覚えとき。"
description3: "その他にも、リストタイムラインとかチャンネルタイムラインとかがあんねん。詳しいのは{link}を見とき。"
_postNote:
Expand Down Expand Up @@ -1383,6 +1384,7 @@ _timelineDescription:
local: "ローカルタイムラインは、このサーバーにおる全員の投稿を見れるで。"
social: "ソーシャルタイムラインは、ホームタイムラインの投稿もローカルタイムラインのも一緒に見れるで。"
global: "グローバルタイムラインは、繋がっとる他のサーバーの投稿、全部ひっくるめて見れんで。"
vmimi: "Vミミタイムラインは、VirtualKemomimiリレーに参加しているサーバーの投稿を見れるで。"
_serverRules:
description: "新規登録前に見せる、サーバーのカンタンなルールを決めるで。内容は使うための決め事の要約がええと思うわ。"
_serverSettings:
Expand Down Expand Up @@ -1703,6 +1705,7 @@ _role:
middle: "中くらい"
high: "高い"
_options:
vrtlAvailable: "Vミミタイムライン見る"
gtlAvailable: "グローバルタイムライン見る"
ltlAvailable: "ローカルタイムライン見る"
canPublicNote: "パブリック投稿できるか"
Expand Down Expand Up @@ -2266,6 +2269,7 @@ _timelines:
local: "ローカル"
social: "ソーシャル"
global: "グローバル"
vmimi: "Vミミ"
_play:
new: "Playの作成"
edit: "Playの編集"
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/core/CoreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import { FanoutTimelineService } from './FanoutTimelineService.js';
import { ChannelFollowingService } from './ChannelFollowingService.js';
import { RegistryApiService } from './RegistryApiService.js';
import { ReversiService } from './ReversiService.js';
import { VmimiRelayService } from './VmimiRelayService.js';

import { ChartLoggerService } from './chart/ChartLoggerService.js';
import FederationChart from './chart/charts/federation.js';
Expand Down Expand Up @@ -221,6 +222,7 @@ const $FanoutTimelineEndpointService: Provider = { provide: 'FanoutTimelineEndpo
const $ChannelFollowingService: Provider = { provide: 'ChannelFollowingService', useExisting: ChannelFollowingService };
const $RegistryApiService: Provider = { provide: 'RegistryApiService', useExisting: RegistryApiService };
const $ReversiService: Provider = { provide: 'ReversiService', useExisting: ReversiService };
const $VmimiRelayService: Provider = { provide: 'VmimiRelayService', useExisting: VmimiRelayService };

const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService };
const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart };
Expand Down Expand Up @@ -369,6 +371,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ChannelFollowingService,
RegistryApiService,
ReversiService,
VmimiRelayService,

ChartLoggerService,
FederationChart,
Expand Down Expand Up @@ -513,6 +516,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ChannelFollowingService,
$RegistryApiService,
$ReversiService,
$VmimiRelayService,

$ChartLoggerService,
$FederationChart,
Expand Down Expand Up @@ -658,6 +662,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ChannelFollowingService,
RegistryApiService,
ReversiService,
VmimiRelayService,

FederationChart,
NotesChart,
Expand Down Expand Up @@ -801,6 +806,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ChannelFollowingService,
$RegistryApiService,
$ReversiService,
$VmimiRelayService,

$FederationChart,
$NotesChart,
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 timeline
| 'vmimiRelayTimeline' // replies not included
| 'vmimiRelayTimelineWithFiles' // only 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
16 changes: 16 additions & 0 deletions packages/backend/src/core/NoteCreateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { VmimiRelayService } from '@/core/VmimiRelayService.js';

type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';

Expand Down Expand Up @@ -218,6 +219,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private instanceChart: InstanceChart,
private utilityService: UtilityService,
private userBlockingService: UserBlockingService,
private vmimiRelayService: VmimiRelayService,
) { }

@bindThis
Expand Down Expand Up @@ -956,6 +958,13 @@ export class NoteCreateService implements OnApplicationShutdown {
this.fanoutTimelineService.push(`localTimelineWithReplyTo:${note.replyUserId}`, note.id, 300 / 10, r);
}
}

if (note.visibility === 'public' && this.vmimiRelayService.isRelayedInstance(note.userHost) && !note.localOnly) {
this.fanoutTimelineService.push('vmimiRelayTimelineWithReplies', note.id, 300 / 10, r);
if (note.replyUserHost == null) {
this.fanoutTimelineService.push(`vmimiRelayTimelineWithReplyTo:${note.replyUserId}`, note.id, 300 / 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 +977,13 @@ export class NoteCreateService implements OnApplicationShutdown {
this.fanoutTimelineService.push('localTimelineWithFiles', note.id, 500, r);
}
}

if (note.visibility === 'public' && this.vmimiRelayService.isRelayedInstance(note.userHost) && !note.localOnly) {
this.fanoutTimelineService.push('vmimiRelayTimeline', note.id, 1000, r);
if (note.fileIds.length > 0) {
this.fanoutTimelineService.push('vmimiRelayTimelineWithFiles', note.id, 500, 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
78 changes: 78 additions & 0 deletions packages/backend/src/core/VmimiRelayService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

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

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

const updateInterval = 1000 * 60 * 60 * 24; // 1 day
const minRetryInterval = 1000 * 60; // 5 minutes
const maxRetryInterval = 1000 * 60 * 60 * 6; // 6 hour

@Injectable()
export class VmimiRelayService {
private logger: Logger;

instaceHosts: Set<string>;
instanceHostsArr: string[];
nextUpdate: number;
retryInterval: number;
updatePromise: Promise<void> | null;

constructor(
private httpRequestService: HttpRequestService,
private LoggerService: LoggerService,
) {
this.instaceHosts = new Set<string>([]);
this.instanceHostsArr = [];
this.nextUpdate = 0;
this.retryInterval = minRetryInterval;
this.updatePromise = null;

this.logger = this.LoggerService.getLogger('VmimiRelay');
}

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

@bindThis
public async updateInstanceList() {
try {
this.logger.info("Updating Vmimi instance list...");
const instanceList = await this.httpRequestService.getJson<VmimiInstanceList>('https://relay.virtualkemomimi.net/api/servers');

this.instanceHostsArr = instanceList.map(i => new URL(i.Url).host);
this.instaceHosts = new Set<string>(this.instanceHostsArr);
this.nextUpdate = Date.now() + updateInterval;
this.logger.info(`Updated Vmimi instance list: ${this.instanceHostsArr}`);
this.retryInterval = minRetryInterval;
} catch (e) {
this.logger.error(`Failed to update Vmimi instance list: ${e}`);
this.retryInterval = Math.min(this.retryInterval * 2, maxRetryInterval);
}
}

@bindThis
public isRelayedInstance(host: string | null): boolean {
this.chechForUpdateInstanceList();

if (host == null) return true;
return this.instaceHosts.has(host);
}

get hostNames (): string[] {
this.chechForUpdateInstanceList();
return this.instanceHostsArr;
}
}
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
Loading