Skip to content

Commit aa02c9e

Browse files
committed
Merge tag '2024.5.0-io.7c' into bun
2 parents fafd78f + 428ff56 commit aa02c9e

29 files changed

+232
-65
lines changed

locales/en-US.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -1365,8 +1365,8 @@ _abuseReportCategory:
13651365
otherBreach_description: "Other actions that violate the terms but do not fall under specific categories"
13661366
violationRights: "Rights Infringement or Impersonation (Reported by Rights Holder)"
13671367
violationRights_description: "Posts infringing the rights (such as copyright or trademark) of the rights holder or impersonation"
1368-
violationRightsOther: "Rights Infringement or Impersonation (Reported by Third Party)"
1369-
violationRightsOther_description: "Posts infringing the rights (such as copyright or trademark) of others or impersonation\nIf reported by a third party, cases outside the scope of non-complaint offenses as defined by law may not be addressed"
1368+
violationRightsOther: "Rights Infringement (Reported by Third Party)"
1369+
violationRightsOther_description: "Posts infringing the rights (such as copyright or trademark) of others\nIf reported by a third party, cases outside the scope of non-complaint offenses as defined by law may not be addressed"
13701370
notLike: "Dislike This Person"
13711371
notLike_description: "Users or posts that you find unpleasant for personal reasons"
13721372
other: "Other"
@@ -1794,6 +1794,8 @@ _role:
17941794
ltlAvailable: "Can view the local timeline"
17951795
canPublicNote: "Can send public notes"
17961796
canScheduleNote: "Can schedule notes"
1797+
scheduleNoteLimit: "Maximum number of scheduled notes"
1798+
scheduleNoteMaxDays: "Maximum number of days that note can be scheduled"
17971799
canInitiateConversation: "Can mention, reply or quote"
17981800
canCreateContent: "Can create contents"
17991801
canUpdateContent: "Can edit contents"
@@ -2324,6 +2326,8 @@ _postForm:
23242326
d: "What do you want to say?"
23252327
e: "Start writing..."
23262328
f: "Waiting for you to write..."
2329+
policyScheduleNoteMaxDaysExceeded: "The maximum number of days you can schedule notes for with your current support plan is {max}.\nYou can upgrade your plan [here](https://go.misskey.io/donate)."
2330+
tosAndGuidelinesInfo: "Before posting, please read the [Terms of Service]({tosUrl}) and [NSFW Guidelines](https://go.misskey.io/media-guideline)."
23272331
_profile:
23282332
name: "Name"
23292333
username: "Username"
@@ -2348,7 +2352,7 @@ _profile:
23482352
sectionName: "Section name"
23492353
sectionNameNoneDescription: "Do not display the section name"
23502354
sectionNameNone: "Section without name"
2351-
policyDisplayLimitExceeded: "The number of items displayed exceeds the current support plan's limit ({max}). This item will not be displayed. You can upgrade your plan [here](https://go.misskey.io/donate)."
2355+
policyDisplayLimitExceeded: "The number of items displayed exceeds the current support plan's limit ({max}). This item will not be displayed.\nYou can upgrade your plan [here](https://go.misskey.io/donate)."
23522356
_exportOrImport:
23532357
allNotes: "All notes"
23542358
favoritedNotes: "Favorite notes"

locales/index.d.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -5490,11 +5490,11 @@ export interface Locale extends ILocale {
54905490
*/
54915491
"violationRights_description": string;
54925492
/**
5493-
* 権利侵害やなりすまし(第三者による通報)
5493+
* 権利侵害(第三者による通報)
54945494
*/
54955495
"violationRightsOther": string;
54965496
/**
5497-
* 他人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為
5497+
* 他人の著作権、商標権、またはその他の権利を侵害する行為
54985498
* 第三者による通報の場合、法律で定められた非親告罪の範囲外のケースには対応できないことがあります
54995499
*/
55005500
"violationRightsOther_description": string;
@@ -7019,6 +7019,14 @@ export interface Locale extends ILocale {
70197019
* 予約投稿の許可
70207020
*/
70217021
"canScheduleNote": string;
7022+
/**
7023+
* 予約投稿の最大数
7024+
*/
7025+
"scheduleNoteLimit": string;
7026+
/**
7027+
* 予約投稿の最大日数
7028+
*/
7029+
"scheduleNoteMaxDays": string;
70227030
/**
70237031
* メンション、リプライ、引用の許可
70247032
*/
@@ -9068,9 +9076,14 @@ export interface Locale extends ILocale {
90689076
"f": string;
90699077
};
90709078
/**
9071-
* [NSFWガイドライン]({nsfwGuideUrl})を必ずお読みになってからご利用ください。
9079+
* 現在の支援プランで予約できる日数の上限は{max}日です。
9080+
* [ここ](https://go.misskey.io/donate)からプランをアップグレードできます。
9081+
*/
9082+
"policyScheduleNoteMaxDaysExceeded": ParameterizedString<"max">;
9083+
/**
9084+
* 投稿する前に、[利用規約]({tosUrl})と[NSFWガイドライン](https://go.misskey.io/media-guideline)を必ずお読みください。
90729085
*/
9073-
"guidelineInfo": ParameterizedString<"nsfwGuideUrl">;
9086+
"tosAndGuidelinesInfo": ParameterizedString<"tosUrl">;
90749087
};
90759088
"_profile": {
90769089
/**
@@ -9166,7 +9179,8 @@ export interface Locale extends ILocale {
91669179
*/
91679180
"sectionNameNone": string;
91689181
/**
9169-
* 現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。
9182+
* 現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。
9183+
* [ここ](https://go.misskey.io/donate)からプランをアップグレードできます。
91709184
*/
91719185
"policyDisplayLimitExceeded": ParameterizedString<"max">;
91729186
};

locales/ja-JP.yml

+7-4
Original file line numberDiff line numberDiff line change
@@ -1370,8 +1370,8 @@ _abuseReportCategory:
13701370
otherBreach_description: "明確に分類されないその他の規約違反行為"
13711371
violationRights: "権利侵害やなりすまし(侵害を受けた権利者本人によるご申告)"
13721372
violationRights_description: "権利者本人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為"
1373-
violationRightsOther: "権利侵害やなりすまし(第三者による通報)"
1374-
violationRightsOther_description: "他人の著作権、商標権、またはその他の権利を侵害する投稿及びなりすまし行為\n第三者による通報の場合、法律で定められた非親告罪の範囲外のケースには対応できないことがあります"
1373+
violationRightsOther: "権利侵害(第三者による通報)"
1374+
violationRightsOther_description: "他人の著作権、商標権、またはその他の権利を侵害する行為\n第三者による通報の場合、法律で定められた非親告罪の範囲外のケースには対応できないことがあります"
13751375
notLike: "この人が気に入らない"
13761376
notLike_description: "個人的な理由で不快と感じるユーザーや投稿"
13771377
other: "その他"
@@ -1808,6 +1808,8 @@ _role:
18081808
ltlAvailable: "ローカルタイムラインの閲覧"
18091809
canPublicNote: "パブリック投稿の許可"
18101810
canScheduleNote: "予約投稿の許可"
1811+
scheduleNoteLimit: "予約投稿の最大数"
1812+
scheduleNoteMaxDays: "予約投稿の最大日数"
18111813
canInitiateConversation: "メンション、リプライ、引用の許可"
18121814
canCreateContent: "コンテンツの作成"
18131815
canUpdateContent: "コンテンツの編集"
@@ -2377,7 +2379,8 @@ _postForm:
23772379
d: "言いたいことは?"
23782380
e: "ここに書いてください"
23792381
f: "あなたが書くのを待っています..."
2380-
guidelineInfo: "[NSFWガイドライン]({nsfwGuideUrl})を必ずお読みになってからご利用ください。"
2382+
policyScheduleNoteMaxDaysExceeded: "現在の支援プランで予約できる日数の上限は{max}日です。\n[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。"
2383+
tosAndGuidelinesInfo: "投稿する前に、[利用規約]({tosUrl})と[NSFWガイドライン](https://go.misskey.io/media-guideline)を必ずお読みください。"
23812384

23822385
_profile:
23832386
name: "名前"
@@ -2403,7 +2406,7 @@ _profile:
24032406
sectionName: "セクション名"
24042407
sectionNameNoneDescription: "セクション名を表示しないようにする"
24052408
sectionNameNone: "名前が表示されないセクション"
2406-
policyDisplayLimitExceeded: "現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。"
2409+
policyDisplayLimitExceeded: "現在の支援プランの表示上限({max}個)を超えているため、この項目は表示されません。\n[ここ](https://go.misskey.io/donate)からプランをアップグレードできます。"
24072410

24082411
_exportOrImport:
24092412
allNotes: "全てのノート"

locales/ko-KR.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -1362,8 +1362,8 @@ _abuseReportCategory:
13621362
otherBreach_description: "명확하게 분류되지 않는 기타 규약 위반 행위"
13631363
violationRights: "권리 침해 또는 사칭 (권리자 본인에 의한 신고)"
13641364
violationRights_description: "권리자 본인의 저작권, 상표권 또는 기타 권리를 침해하는 게시물 및 사칭 행위"
1365-
violationRightsOther: "권리 침해 또는 사칭 (제3자에 의한 신고)"
1366-
violationRightsOther_description: "타인의 저작권, 상표권 또는 기타 권리를 침해하는 게시물 및 사칭 행위\n제3자에 의한 신고의 경우, 법으로 정해진 비친고죄 범위 외의 사례에는 대응할 수 없습니다"
1365+
violationRightsOther: "권리 침해 (제3자에 의한 신고)"
1366+
violationRightsOther_description: "타인의 저작권, 상표권 또는 기타 권리를 침해하는 행위\n제3자에 의한 신고의 경우, 법으로 정해진 비친고죄 범위 외의 사례에는 대응할 수 없습니다"
13671367
notLike: "이 사람이 마음에 들지 않음"
13681368
notLike_description: "개인적인 이유로 불쾌감을 느끼는 사용자나 게시물"
13691369
other: "기타"
@@ -1791,6 +1791,8 @@ _role:
17911791
ltlAvailable: "로컬 타임라인 보이기"
17921792
canPublicNote: "공개 노트 허용"
17931793
canScheduleNote: "노트 예약 허용"
1794+
scheduleNoteLimit: "노트 예약 한도"
1795+
scheduleNoteMaxDays: "노트 예약 최대 일수"
17941796
mentionMax: "노트에 넣을 수 있는 멘션 수"
17951797
canCreateContent: "컨텐츠 생성 허용"
17961798
canUpdateContent: "컨텐츠 수정 허용"
@@ -2310,6 +2312,8 @@ _postForm:
23102312
d: "말하고 싶은 게 있나요?"
23112313
e: "여기에 적어 주세요"
23122314
f: "글 쓰기를 기다려요…"
2315+
policyScheduleNoteMaxDaysExceeded: "현재 지원 플랜의 예약 가능한 최대 일수는 {max}일입니다.\n[여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다."
2316+
tosAndGuidelinesInfo: "노트를 게시하기 전에 [이용약관]({tosUrl})과 [NSFW 가이드라인](https://go.misskey.io/media-guideline)을 반드시 읽어 주세요."
23132317
_profile:
23142318
name: "이름"
23152319
username: "사용자 이름"
@@ -2334,7 +2338,7 @@ _profile:
23342338
sectionName: "섹션 이름"
23352339
sectionNameNoneDescription: "섹션 이름이 표시되지 않도록 합니다"
23362340
sectionNameNone: "이름이 표시되지 않는 섹션"
2337-
policyDisplayLimitExceeded: "현재 지원 플랜의 표시 제한({max}개)을 초과하였기 때문에 이 항목은 표시되지 않습니다. [여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다."
2341+
policyDisplayLimitExceeded: "현재 지원 플랜의 표시 제한({max}개)을 초과하였기 때문에 이 항목은 표시되지 않습니다.\n[여기](https://go.misskey.io/donate)에서 플랜을 업그레이드할 수 있습니다."
23382342
_exportOrImport:
23392343
allNotes: "모든 노트"
23402344
favoritedNotes: "즐겨찾기한 노트"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "misskey",
3-
"version": "2024.5.0-io.7b",
3+
"version": "2024.5.0-io.7c",
44
"codename": "nasubi",
55
"repository": {
66
"type": "git",

packages/backend/src/core/NoteCreateService.ts

+9
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,15 @@ export class NoteCreateService implements OnApplicationShutdown {
425425
throw new IdentifiableError('7cc42034-f7ab-4f7c-87b4-e00854479080', 'User has no permission to schedule notes.');
426426
}
427427

428+
if ((data.scheduledAt.getTime() - Date.now()) / 86_400_000 > policies.scheduleNoteMaxDays) {
429+
throw new IdentifiableError('506006cf-3092-4ae1-8145-b025001c591f', `User can schedule notes up to ${policies.scheduleNoteMaxDays} days in the future.`);
430+
}
431+
432+
const scheduledCount = await this.scheduledNotesRepository.countBy({ userId: user.id });
433+
if (scheduledCount >= policies.scheduleNoteLimit) {
434+
throw new IdentifiableError('7fc78d25-d947-45c1-9547-02257b98cab3', `User can schedule up to ${policies.scheduleNoteLimit} notes.`);
435+
}
436+
428437
const draft = await this.insertScheduledNote(user, data);
429438

430439
await this.queueService.createScheduledNoteJob(draft.id, draft.scheduledAt!);

packages/backend/src/core/RoleService.ts

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export type RolePolicies = {
3737
ltlAvailable: boolean;
3838
canPublicNote: boolean;
3939
canScheduleNote: boolean;
40+
scheduleNoteLimit: number;
41+
scheduleNoteMaxDays: number;
4042
canInitiateConversation: boolean;
4143
canCreateContent: boolean;
4244
canUpdateContent: boolean;
@@ -79,6 +81,8 @@ export const DEFAULT_POLICIES: RolePolicies = {
7981
ltlAvailable: true,
8082
canPublicNote: true,
8183
canScheduleNote: true,
84+
scheduleNoteLimit: 10,
85+
scheduleNoteMaxDays: 365,
8286
canInitiateConversation: true,
8387
canCreateContent: true,
8488
canUpdateContent: true,
@@ -392,6 +396,8 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
392396
ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)),
393397
canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)),
394398
canScheduleNote: calc('canScheduleNote', vs => vs.some(v => v === true)),
399+
scheduleNoteLimit: calc('scheduleNoteLimit', vs => Math.max(...vs)),
400+
scheduleNoteMaxDays: calc('scheduleNoteMaxDays', vs => Math.max(...vs)),
395401
canInitiateConversation: calc('canInitiateConversation', vs => vs.some(v => v === true)),
396402
canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
397403
canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),

packages/backend/src/models/json-schema/role.ts

+8
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ export const packedRolePoliciesSchema = {
184184
type: 'boolean',
185185
optional: false, nullable: false,
186186
},
187+
scheduleNoteLimit: {
188+
type: 'integer',
189+
optional: false, nullable: false,
190+
},
191+
scheduleNoteMaxDays: {
192+
type: 'integer',
193+
optional: false, nullable: false,
194+
},
187195
canInitiateConversation: {
188196
type: 'boolean',
189197
optional: false, nullable: false,

packages/backend/src/queue/processors/CheckMissingScheduledNoteProcessorService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class CheckMissingScheduledNoteProcessorService {
3737
}
3838

3939
const query = this.scheduledNotesRepository.createQueryBuilder('draft')
40-
.where('draft.scheduledAt < now() - interval \'5 minutes\'').orderBy('draft.createdAt', 'ASC');
40+
.where('draft.scheduledAt < now() + interval \'10 minutes\'').orderBy('draft.createdAt', 'ASC');
4141

4242
let lastId = '0';
4343
while (true) {

packages/backend/src/server/api/SigninApiService.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,15 @@ export class SigninApiService {
9797
reply.code(429);
9898
return {
9999
error: {
100-
message: 'Too many failed attempts to sign in. Try again later.',
101-
code: 'TOO_MANY_AUTHENTICATION_FAILURES',
100+
message: 'Rate limit exceeded. Please try again later.',
101+
code: 'RATE_LIMIT_EXCEEDED',
102102
id: '22d05606-fbcf-421a-a2db-b32610dcfd1b',
103-
},
103+
info: {
104+
message: 'Too many failed attempts to sign in.',
105+
code: 'TOO_MANY_AUTHENTICATION_FAILURES',
106+
id: '6c181469-ecb9-42d2-82c9-60db5486a819',
107+
},
108+
}
104109
};
105110
}
106111

packages/backend/src/server/api/endpoints/notes/create.ts

+20-15
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,26 @@ export const meta = {
155155
id: 'e577d185-8179-4a17-b47f-6093985558e6',
156156
},
157157

158-
cannotScheduleToFarFuture: {
159-
message: 'Cannot schedule to the far future.',
160-
code: 'CANNOT_SCHEDULE_TO_FAR_FUTURE',
161-
id: 'ea102856-e8da-4ae9-a98a-0326821bd177',
162-
},
163-
164158
cannotScheduleSameTime: {
165159
message: 'Cannot schedule multiple notes at the same time.',
166160
code: 'CANNOT_SCHEDULE_SAME_TIME',
167161
id: '187a8fab-fd83-4ae6-a46c-0f6f07784634',
168162
},
169163

164+
tooManyScheduledNotes: {
165+
message: 'You cannot schedule notes any more.',
166+
code: 'TOO_MANY_SCHEDULED_NOTES',
167+
kind: 'permission',
168+
id: '9e33041f-f6fb-414d-98c1-591466e55287'
169+
},
170+
171+
cannotScheduleToFarFuture: {
172+
message: 'Cannot schedule to the far future.',
173+
code: 'CANNOT_SCHEDULE_TO_FAR_FUTURE',
174+
kind: 'permission',
175+
id: 'ea102856-e8da-4ae9-a98a-0326821bd177',
176+
},
177+
170178
rolePermissionDenied: {
171179
message: 'You are not assigned to a required role.',
172180
code: 'ROLE_PERMISSION_DENIED',
@@ -462,11 +470,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
462470
logger.error('Cannot schedule to the past.', { scheduledAt });
463471
throw new ApiError(meta.errors.cannotScheduleToPast);
464472
}
465-
466-
if (scheduledAt.getTime() - now.getTime() > ms('1year')) {
467-
logger.error('Cannot schedule to the far future.', { scheduledAt });
468-
throw new ApiError(meta.errors.cannotScheduleToFarFuture);
469-
}
470473
}
471474

472475
// 投稿を作成
@@ -517,10 +520,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
517520
logger.error('Failed to create a note.', { error: err });
518521

519522
if (err instanceof IdentifiableError) {
520-
if (err.id === '689ee33f-f97c-479a-ac49-1b9f8140af99') throw new ApiError(meta.errors.containsProhibitedWords);
521-
if (err.id === '9f466dab-c856-48cd-9e65-ff90ff750580') throw new ApiError(meta.errors.containsTooManyMentions);
522-
if (err.id === '7cc42034-f7ab-4f7c-87b4-e00854479080') throw new ApiError(meta.errors.rolePermissionDenied);
523-
if (err.id === '5ea8e4f5-9d64-4e6c-92b8-9e2b5a4756bc') throw new ApiError(meta.errors.cannotScheduleSameTime);
523+
if (err.id === '689ee33f-f97c-479a-ac49-1b9f8140af99') throw new ApiError(meta.errors.containsProhibitedWords, { message: err.message });
524+
if (err.id === '9f466dab-c856-48cd-9e65-ff90ff750580') throw new ApiError(meta.errors.containsTooManyMentions, { message: err.message });
525+
if (err.id === '5ea8e4f5-9d64-4e6c-92b8-9e2b5a4756bc') throw new ApiError(meta.errors.cannotScheduleSameTime, { message: err.message });
526+
if (err.id === '7fc78d25-d947-45c1-9547-02257b98cab3') throw new ApiError(meta.errors.tooManyScheduledNotes, { message: err.message });
527+
if (err.id === '506006cf-3092-4ae1-8145-b025001c591f') throw new ApiError(meta.errors.cannotScheduleToFarFuture, { message: err.message });
528+
if (err.id === '7cc42034-f7ab-4f7c-87b4-e00854479080') throw new ApiError(meta.errors.rolePermissionDenied, { message: err.message });
524529
}
525530

526531
throw err;

packages/backend/src/server/api/stream/channels/antenna.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class AntennaChannel extends Channel {
5151

5252
if (this.isNoteMutedOrBlocked(note)) return;
5353

54+
if (this.user && (note.visibleUserIds?.includes(this.user.id) ?? note.mentions?.includes(this.user.id))) {
55+
this.connection.cacheNote(note);
56+
}
57+
5458
if (this.minimize && ['public', 'home'].includes(note.visibility)) {
5559
this.send('note', {
5660
id: note.id, myReaction: note.myReaction,
@@ -59,7 +63,6 @@ class AntennaChannel extends Channel {
5963
renote: note.renote?.myReaction ? { myReaction: note.renote.myReaction } : undefined,
6064
});
6165
} else {
62-
this.connection.cacheNote(note);
6366
this.send('note', note);
6467
}
6568
} else {

packages/backend/src/server/api/stream/channels/channel.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class ChannelChannel extends Channel {
5757
}
5858
}
5959

60+
if (this.user && (note.visibleUserIds?.includes(this.user.id) ?? note.mentions?.includes(this.user.id))) {
61+
this.connection.cacheNote(note);
62+
}
63+
6064
if (this.minimize && ['public', 'home'].includes(note.visibility)) {
6165
this.send('note', {
6266
id: note.id, myReaction: note.myReaction,
@@ -65,7 +69,6 @@ class ChannelChannel extends Channel {
6569
renote: note.renote?.myReaction ? { myReaction: note.renote.myReaction } : undefined,
6670
});
6771
} else {
68-
this.connection.cacheNote(note);
6972
this.send('note', note);
7073
}
7174
}

packages/backend/src/server/api/stream/channels/global-timeline.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class GlobalTimelineChannel extends Channel {
8787
}
8888
}
8989

90+
if (this.user && (note.visibleUserIds?.includes(this.user.id) ?? note.mentions?.includes(this.user.id))) {
91+
this.connection.cacheNote(note);
92+
}
93+
9094
if (this.minimize && ['public', 'home'].includes(note.visibility)) {
9195
this.send('note', {
9296
id: note.id, myReaction: note.myReaction,
@@ -95,7 +99,6 @@ class GlobalTimelineChannel extends Channel {
9599
renote: note.renote?.myReaction ? { myReaction: note.renote.myReaction } : undefined,
96100
});
97101
} else {
98-
this.connection.cacheNote(note);
99102
this.send('note', note);
100103
}
101104
}

0 commit comments

Comments
 (0)