From 5eff4da27b382226bcd0be0772dac6105ade4216 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=80=81=E5=91=A8=E9=83=A8=E8=90=BD?=
 <laozhoubuluo@gmail.com>
Date: Sat, 13 Apr 2024 08:59:11 +0800
Subject: [PATCH 1/9] feat: antenna limit

---
 locales/en-US.yml                             |  1 +
 locales/zh-CN.yml                             |  1 +
 packages/backend-rs/index.d.ts                |  1 +
 packages/backend-rs/src/model/entity/meta.rs  |  2 ++
 .../migration/1712937600000-antennaLimit.ts   | 19 +++++++++++++++++++
 packages/backend/src/models/entities/meta.ts  |  6 ++++++
 .../src/server/api/endpoints/admin/meta.ts    |  6 ++++++
 .../server/api/endpoints/admin/update-meta.ts |  5 +++++
 .../server/api/endpoints/antennas/create.ts   |  5 ++++-
 .../backend/src/server/api/endpoints/meta.ts  |  6 ++++++
 packages/client/src/pages/admin/settings.vue  | 16 ++++++++++++++++
 packages/firefish-js/src/entities.ts          |  1 +
 12 files changed, 68 insertions(+), 1 deletion(-)
 create mode 100644 packages/backend/src/migration/1712937600000-antennaLimit.ts

diff --git a/locales/en-US.yml b/locales/en-US.yml
index f8da18450c..a8663375a8 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -394,6 +394,7 @@ enableRegistration: "Enable new user registration"
 invite: "Invite"
 driveCapacityPerLocalAccount: "Drive capacity per local user"
 driveCapacityPerRemoteAccount: "Drive capacity per remote user"
+antennaLimit: "The maximum number of antennas that each user can create"
 inMb: "In megabytes"
 iconUrl: "Icon URL"
 bannerUrl: "Banner image URL"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index a8510612dc..9e7a0ed19e 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -340,6 +340,7 @@ invite: "邀请"
 driveCapacityPerLocalAccount: "每个本地用户的网盘容量"
 driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
 inMb: "以兆字节 (MegaByte) 为单位"
+antennaLimit: "每个用户最多可以创建的天线数量"
 iconUrl: "图标 URL"
 bannerUrl: "横幅图 URL"
 backgroundImageUrl: "背景图 URL"
diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts
index 617bedf5b9..509c3d912d 100644
--- a/packages/backend-rs/index.d.ts
+++ b/packages/backend-rs/index.d.ts
@@ -443,6 +443,7 @@ export interface Meta {
   recaptchaSecretKey: string | null
   localDriveCapacityMb: number
   remoteDriveCapacityMb: number
+  antennaLimit: number
   summalyProxy: string | null
   enableEmail: boolean
   email: string | null
diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs
index b9a89914bd..7d0972b844 100644
--- a/packages/backend-rs/src/model/entity/meta.rs
+++ b/packages/backend-rs/src/model/entity/meta.rs
@@ -50,6 +50,8 @@ pub struct Model {
     pub local_drive_capacity_mb: i32,
     #[sea_orm(column_name = "remoteDriveCapacityMb")]
     pub remote_drive_capacity_mb: i32,
+    #[sea_orm(column_name = "antennaLimit")]
+    pub antenna_limit: i32,
     #[sea_orm(column_name = "summalyProxy")]
     pub summaly_proxy: Option<String>,
     #[sea_orm(column_name = "enableEmail")]
diff --git a/packages/backend/src/migration/1712937600000-antennaLimit.ts b/packages/backend/src/migration/1712937600000-antennaLimit.ts
new file mode 100644
index 0000000000..cd8f9ff658
--- /dev/null
+++ b/packages/backend/src/migration/1712937600000-antennaLimit.ts
@@ -0,0 +1,19 @@
+import type { MigrationInterface, QueryRunner } from "typeorm";
+
+export class antennaLimit1712937600000 implements MigrationInterface {
+	async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(
+			`ALTER TABLE "meta" ADD "antennaLimit" integer NOT NULL DEFAULT 5`,
+			undefined,
+		);
+		await queryRunner.query(
+			`COMMENT ON COLUMN "meta"."antennaLimit" IS 'Antenna Limit'`,
+		);
+	}
+	async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(
+			`ALTER TABLE "meta" DROP COLUMN "antennaLimit"`,
+			undefined,
+		);
+	}
+}
diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts
index cdb8e14c3f..5e267a8e24 100644
--- a/packages/backend/src/models/entities/meta.ts
+++ b/packages/backend/src/models/entities/meta.ts
@@ -276,6 +276,12 @@ export class Meta {
 	})
 	public remoteDriveCapacityMb: number;
 
+	@Column("integer", {
+		default: 5,
+		comment: "Antenna Limit",
+	})
+	public antennaLimit: number;
+
 	@Column("varchar", {
 		length: 128,
 		nullable: true,
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index a22fbab8f1..1f382f1254 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -24,6 +24,11 @@ export const meta = {
 				optional: false,
 				nullable: false,
 			},
+			antennaLimit: {
+				type: "number",
+				optional: false,
+				nullable: false,
+			},
 			cacheRemoteFiles: {
 				type: "boolean",
 				optional: false,
@@ -487,6 +492,7 @@ export default define(meta, paramDef, async () => {
 		enableGuestTimeline: instance.enableGuestTimeline,
 		driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
 		driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
+		antennaLimit: instance.antennaLimit,
 		emailRequiredForSignup: instance.emailRequiredForSignup,
 		enableHcaptcha: instance.enableHcaptcha,
 		hcaptchaSiteKey: instance.hcaptchaSiteKey,
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 604ef3a0fc..e5234ea720 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -94,6 +94,7 @@ export const paramDef = {
 		defaultDarkTheme: { type: "string", nullable: true },
 		localDriveCapacityMb: { type: "integer" },
 		remoteDriveCapacityMb: { type: "integer" },
+		antennaLimit: { type: "integer" },
 		cacheRemoteFiles: { type: "boolean" },
 		markLocalFilesNsfwByDefault: { type: "boolean" },
 		emailRequiredForSignup: { type: "boolean" },
@@ -327,6 +328,10 @@ export default define(meta, paramDef, async (ps, me) => {
 		set.remoteDriveCapacityMb = ps.remoteDriveCapacityMb;
 	}
 
+	if (ps.antennaLimit !== undefined) {
+		set.antennaLimit = ps.antennaLimit;
+	}
+
 	if (ps.cacheRemoteFiles !== undefined) {
 		set.cacheRemoteFiles = ps.cacheRemoteFiles;
 	}
diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index 792301d4de..792c5e30b4 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -3,6 +3,7 @@ import { genId } from "backend-rs";
 import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
 import { ApiError } from "@/server/api/error.js";
 import { publishInternalEvent } from "@/services/stream.js";
+import { fetchMeta } from "@/misc/fetch-meta.js";
 
 export const meta = {
 	tags: ["antennas"],
@@ -109,10 +110,12 @@ export default define(meta, paramDef, async (ps, user) => {
 	let userList;
 	let userGroupJoining;
 
+	const instance = await fetchMeta(true);
+
 	const antennas = await Antennas.findBy({
 		userId: user.id,
 	});
-	if (antennas.length > 5 && !user.isAdmin) {
+	if (antennas.length >= instance.antennaLimit) {
 		throw new ApiError(meta.errors.tooManyAntennas);
 	}
 
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index 2a674b52c3..cb494bf27e 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -126,6 +126,11 @@ export const meta = {
 				optional: false,
 				nullable: false,
 			},
+			antennaLimit: {
+				type: "number",
+				optional: false,
+				nullable: false,
+			},
 			cacheRemoteFiles: {
 				type: "boolean",
 				optional: false,
@@ -445,6 +450,7 @@ export default define(meta, paramDef, async (ps, me) => {
 		enableGuestTimeline: instance.enableGuestTimeline,
 		driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
 		driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
+		antennaLimit: instance.antennaLimit,
 		emailRequiredForSignup: instance.emailRequiredForSignup,
 		enableHcaptcha: instance.enableHcaptcha,
 		hcaptchaSiteKey: instance.hcaptchaSiteKey,
diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue
index f69c4fb23b..1c2188daac 100644
--- a/packages/client/src/pages/admin/settings.vue
+++ b/packages/client/src/pages/admin/settings.vue
@@ -350,6 +350,19 @@
 							</FormSplit>
 						</FormSection>
 
+						<FormSection>
+							<template #label>{{ i18n.ts.antennas }}</template>
+							<FormInput
+									v-model="antennaLimit"
+									type="number"
+									class="_formBlock"
+								>
+									<template #label>{{
+										i18n.ts.antennaLimit
+									}}</template>
+								</FormInput>
+						</FormSection>
+
 						<FormSection>
 							<template #label>ServiceWorker</template>
 
@@ -502,6 +515,7 @@ const cacheRemoteFiles = ref(false);
 const markLocalFilesNsfwByDefault = ref(false);
 const localDriveCapacityMb = ref(0);
 const remoteDriveCapacityMb = ref(0);
+const antennaLimit = ref(0);
 const enableRegistration = ref(false);
 const emailRequiredForSignup = ref(false);
 const enableServiceWorker = ref(false);
@@ -579,6 +593,7 @@ async function init() {
 	markLocalFilesNsfwByDefault.value = meta.markLocalFilesNsfwByDefault;
 	localDriveCapacityMb.value = meta.driveCapacityPerLocalUserMb;
 	remoteDriveCapacityMb.value = meta.driveCapacityPerRemoteUserMb;
+	antennaLimit.value = meta.antennaLimit;
 	enableRegistration.value = !meta.disableRegistration;
 	emailRequiredForSignup.value = meta.emailRequiredForSignup;
 	enableServiceWorker.value = meta.enableServiceWorker;
@@ -631,6 +646,7 @@ function save() {
 		markLocalFilesNsfwByDefault: markLocalFilesNsfwByDefault.value,
 		localDriveCapacityMb: localDriveCapacityMb.value,
 		remoteDriveCapacityMb: remoteDriveCapacityMb.value,
+		antennaLimit: antennaLimit.value,
 		disableRegistration: !enableRegistration.value,
 		emailRequiredForSignup: emailRequiredForSignup.value,
 		enableServiceWorker: enableServiceWorker.value,
diff --git a/packages/firefish-js/src/entities.ts b/packages/firefish-js/src/entities.ts
index ce940a1481..6f9d6b400b 100644
--- a/packages/firefish-js/src/entities.ts
+++ b/packages/firefish-js/src/entities.ts
@@ -341,6 +341,7 @@ export type LiteInstanceMetadata = {
 	disableGlobalTimeline: boolean;
 	driveCapacityPerLocalUserMb: number;
 	driveCapacityPerRemoteUserMb: number;
+	antennaLimit: number;
 	enableHcaptcha: boolean;
 	hcaptchaSiteKey: string | null;
 	enableRecaptcha: boolean;

From f0a50bc2889416c8fb741147523b077719621130 Mon Sep 17 00:00:00 2001
From: Lhcfl <Lhcfl@outlook.com>
Date: Sun, 14 Apr 2024 13:59:27 +0800
Subject: [PATCH 2/9] feat: show MkRemoteCaution in note history page

---
 packages/client/src/pages/note-history.vue | 74 ++++++++++++----------
 1 file changed, 39 insertions(+), 35 deletions(-)

diff --git a/packages/client/src/pages/note-history.vue b/packages/client/src/pages/note-history.vue
index f6fbf517a3..33cae5860a 100644
--- a/packages/client/src/pages/note-history.vue
+++ b/packages/client/src/pages/note-history.vue
@@ -4,30 +4,35 @@
 			><MkPageHeader :display-back-button="true"
 		/></template>
 		<MkSpacer :content-max="800">
-			<MkLoading v-if="!loaded" />
-			<MkPagination
-				v-else
-				ref="pagingComponent"
-				v-slot="{ items }"
-				:pagination="pagination"
-			>
-				<div ref="tlEl" class="giivymft noGap">
-					<XList
-						v-slot="{ item }"
-						:items="convertNoteEditsToNotes(items)"
-						class="notes"
-						:no-gap="true"
-					>
-						<XNote
-							:key="item.id"
-							class="qtqtichx"
-							:note="item"
-							:hide-footer="true"
-							:detailed-view="true"
-						/>
-					</XList>
-				</div>
-			</MkPagination>
+			<MkLoading v-if="note == null" />
+			<div class="" v-else>
+				<MkRemoteCaution
+					v-if="note.user.host != null"
+					:href="note.url ?? note.uri!"
+				/>
+				<MkPagination
+					ref="pagingComponent"
+					v-slot="{ items }"
+					:pagination="pagination"
+				>
+					<div ref="tlEl" class="giivymft noGap">
+						<XList
+							v-slot="{ item }"
+							:items="convertNoteEditsToNotes(items)"
+							class="notes"
+							:no-gap="true"
+						>
+							<XNote
+								:key="item.id"
+								class="qtqtichx"
+								:note="item"
+								:hide-footer="true"
+								:detailed-view="true"
+							/>
+						</XList>
+					</div>
+				</MkPagination>
+			</div>
 		</MkSpacer>
 	</MkStickyContainer>
 </template>
@@ -42,6 +47,7 @@ import XNote from "@/components/MkNote.vue";
 import { i18n } from "@/i18n";
 import { definePageMetadata } from "@/scripts/page-metadata";
 import icon from "@/scripts/icon";
+import MkRemoteCaution from "@/components/MkRemoteCaution.vue";
 
 const pagingComponent = ref<InstanceType<typeof MkPagination>>();
 
@@ -65,8 +71,7 @@ definePageMetadata(
 	})),
 );
 
-const note = ref<entities.Note>({} as entities.Note);
-const loaded = ref(false);
+const note = ref<entities.Note | null>(null);
 
 onMounted(() => {
 	api("notes/show", {
@@ -79,20 +84,19 @@ onMounted(() => {
 		res.replyId = null;
 
 		note.value = res;
-		loaded.value = true;
 	});
 });
 
 function convertNoteEditsToNotes(noteEdits: entities.NoteEdit[]) {
 	const now: entities.NoteEdit = {
 		id: "EditionNow",
-		noteId: note.value.id,
-		updatedAt: note.value.createdAt,
-		text: note.value.text,
-		cw: note.value.cw,
-		files: note.value.files,
-		fileIds: note.value.fileIds,
-		emojis: note.value.emojis,
+		noteId: note.value!.id,
+		updatedAt: note.value!.createdAt,
+		text: note.value!.text,
+		cw: note.value!.cw,
+		files: note.value!.files,
+		fileIds: note.value!.fileIds,
+		emojis: note.value!.emojis,
 	};
 
 	return [now]
@@ -108,7 +112,7 @@ function convertNoteEditsToNotes(noteEdits: entities.NoteEdit[]) {
 				_shouldInsertAd_: false,
 				files: noteEdit.files,
 				fileIds: noteEdit.fileIds,
-				emojis: note.value.emojis.concat(noteEdit.emojis),
+				emojis: note.value!.emojis.concat(noteEdit.emojis),
 			});
 		});
 }

From 54d9916fecaab64a8b61ea59fe52e6a51ebcc97e Mon Sep 17 00:00:00 2001
From: Lhcfl <Lhcfl@outlook.com>
Date: Sun, 14 Apr 2024 16:34:33 +0800
Subject: [PATCH 3/9] fix: rss feed no HTML

---
 packages/backend/src/server/web/feed.ts | 47 ++++++++++++++++++-------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts
index e6b09b4f4f..3b1b9d6fa5 100644
--- a/packages/backend/src/server/web/feed.ts
+++ b/packages/backend/src/server/web/feed.ts
@@ -2,7 +2,19 @@ import { Feed } from "feed";
 import { In, IsNull } from "typeorm";
 import config from "@/config/index.js";
 import type { User } from "@/models/entities/user.js";
+import type { Note } from "@/models/entities/note.js";
 import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js";
+import getNoteHtml from "@/remote/activitypub/misc/get-note-html.js";
+
+/**
+ * If there is this part in the note, it will cause CDATA to be terminated early.
+ * So I inserted two zero-width spaces in the middle, which doesn't make a visual difference
+ * Although this is not a good solution, there seems no other way.
+ * Anyway, it is not common to encounter such extreme situations.
+ */
+function escapeCDATA(str: string) {
+	return str.replaceAll("]]>", "]​]​>");
+}
 
 export default async function (
 	user: User,
@@ -15,7 +27,7 @@ export default async function (
 	const author = {
 		link: `${config.url}/@${user.username}`,
 		email: `${user.username}@${config.host}`,
-		name: user.name || user.username,
+		name: escapeCDATA(user.name || user.username),
 	};
 
 	const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
@@ -44,11 +56,13 @@ export default async function (
 		title: `${author.name} (@${user.username}@${config.host})`,
 		updated: notes[0].createdAt,
 		generator: "Firefish",
-		description: `${user.notesCount} Notes, ${
-			profile.ffVisibility === "public" ? user.followingCount : "?"
-		} Following, ${
-			profile.ffVisibility === "public" ? user.followersCount : "?"
-		} Followers${profile.description ? ` · ${profile.description}` : ""}`,
+		description: escapeCDATA(
+			`${user.notesCount} Notes, ${
+				profile.ffVisibility === "public" ? user.followingCount : "?"
+			} Following, ${
+				profile.ffVisibility === "public" ? user.followersCount : "?"
+			} Followers${profile.description ? ` · ${profile.description}` : ""}`,
+		),
 		link: author.link,
 		image: await Users.getAvatarUrl(user),
 		feedLinks: {
@@ -88,19 +102,23 @@ export default async function (
 		}
 
 		feed.addItem({
-			title: title
-				.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "")
-				.substring(0, 100),
+			title: escapeCDATA(
+				title
+					.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "")
+					.substring(0, 100),
+			),
 			link: `${config.url}/notes/${note.id}`,
 			date: note.createdAt,
 			description: note.cw
-				? note.cw.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "")
+				? escapeCDATA(note.cw.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ""))
 				: undefined,
-			content: contentStr.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ""),
+			content: escapeCDATA(
+				contentStr.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ""),
+			),
 		});
 	}
 
-	async function noteToString(note, isTheNote = false) {
+	async function noteToString(note: Note, isTheNote = false) {
 		const author = isTheNote
 			? null
 			: await Users.findOneBy({ id: note.userId });
@@ -135,7 +153,10 @@ export default async function (
 				}">${file.name}</a>`;
 			}
 		}
-		outstr += `${note.cw ? note.cw + "<br>" : ""}${note.text || ""}${fileEle}`;
+
+		outstr += `${note.cw ? note.cw + "<br>" : ""}${
+			getNoteHtml(note) || ""
+		}${fileEle}`;
 		if (isTheNote) {
 			outstr += ` <span class="${
 				note.renoteId ? "renote_note" : note.replyId ? "reply_note" : "new_note"

From 241c824ab54182c4cbaeccf33c9475c4652b14c0 Mon Sep 17 00:00:00 2001
From: Lhcfl <Lhcfl@outlook.com>
Date: Sun, 14 Apr 2024 16:44:12 +0800
Subject: [PATCH 4/9] fix: use better `]]>` replacer

---
 packages/backend/src/server/web/feed.ts | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts
index 3b1b9d6fa5..f3b3c97c32 100644
--- a/packages/backend/src/server/web/feed.ts
+++ b/packages/backend/src/server/web/feed.ts
@@ -8,12 +8,9 @@ import getNoteHtml from "@/remote/activitypub/misc/get-note-html.js";
 
 /**
  * If there is this part in the note, it will cause CDATA to be terminated early.
- * So I inserted two zero-width spaces in the middle, which doesn't make a visual difference
- * Although this is not a good solution, there seems no other way.
- * Anyway, it is not common to encounter such extreme situations.
  */
 function escapeCDATA(str: string) {
-	return str.replaceAll("]]>", "]​]​>");
+	return str.replaceAll("]]>", "]]]]><![CDATA[>");
 }
 
 export default async function (

From ce672f4edd542d78a1b33429d379ec969ae163cb Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Sun, 21 Apr 2024 22:36:05 +0900
Subject: [PATCH 5/9] dev: add cargo test to pnpm scripts

mocha test has been unmaintained for a long time and is very broken :(
---
 package.json | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index a62fae09f0..93594a5698 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,9 @@
 		"debug": "pnpm run build:debug && pnpm run start",
 		"build:debug": "pnpm run clean && pnpm node ./scripts/dev-build.mjs && pnpm run gulp",
 		"mocha": "pnpm --filter backend run mocha",
-		"test": "pnpm run mocha",
+		"test": "pnpm run test:ts && pnpm run test:rs",
+		"test:ts": "pnpm run mocha",
+		"test:rs": "cargo test",
 		"format": "pnpm run format:ts; pnpm run format:rs",
 		"format:ts": "pnpm -r --parallel run format",
 		"format:rs": "cargo fmt --all --",

From a107d8c1ec8309ca9d76583acdcf2d072fda3bfc Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Mon, 22 Apr 2024 05:52:56 +0900
Subject: [PATCH 6/9] fix (backend): update import

---
 packages/backend/src/server/api/endpoints/antennas/create.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index 792c5e30b4..aa5dcee044 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -1,9 +1,8 @@
 import define from "@/server/api/define.js";
-import { genId } from "backend-rs";
+import { fetchMeta, genId } from "backend-rs";
 import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
 import { ApiError } from "@/server/api/error.js";
 import { publishInternalEvent } from "@/services/stream.js";
-import { fetchMeta } from "@/misc/fetch-meta.js";
 
 export const meta = {
 	tags: ["antennas"],

From c4658801aa98e61f5ee14177583cc758c1904f1d Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Mon, 22 Apr 2024 05:54:32 +0900
Subject: [PATCH 7/9] chore: regenerate entities

---
 packages/backend-rs/src/model/entity/meta.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/backend-rs/src/model/entity/meta.rs b/packages/backend-rs/src/model/entity/meta.rs
index 7d0972b844..fcba9e0be9 100644
--- a/packages/backend-rs/src/model/entity/meta.rs
+++ b/packages/backend-rs/src/model/entity/meta.rs
@@ -50,8 +50,6 @@ pub struct Model {
     pub local_drive_capacity_mb: i32,
     #[sea_orm(column_name = "remoteDriveCapacityMb")]
     pub remote_drive_capacity_mb: i32,
-    #[sea_orm(column_name = "antennaLimit")]
-    pub antenna_limit: i32,
     #[sea_orm(column_name = "summalyProxy")]
     pub summaly_proxy: Option<String>,
     #[sea_orm(column_name = "enableEmail")]
@@ -175,6 +173,8 @@ pub struct Model {
     pub more_urls: Json,
     #[sea_orm(column_name = "markLocalFilesNsfwByDefault")]
     pub mark_local_files_nsfw_by_default: bool,
+    #[sea_orm(column_name = "antennaLimit")]
+    pub antenna_limit: i32,
 }
 
 #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]

From c9de5f6095dec1c3390a4e5c0300dd0fa296620a Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Mon, 22 Apr 2024 05:56:46 +0900
Subject: [PATCH 8/9] docs: update api-changes.md

---
 docs/api-change.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/docs/api-change.md b/docs/api-change.md
index f3ed584c32..dcd4329a27 100644
--- a/docs/api-change.md
+++ b/docs/api-change.md
@@ -2,6 +2,10 @@
 
 Breaking changes are indicated by the :warning: icon.
 
+## Unreleased
+
+- Added `antennaLimit` field to the response of `meta` and `admin/meta`, and the request of `admin/update-meta` (optional).
+
 ## v20240413
 
 - :warning: Removed `patrons` endpoint.

From ebaefb9697f7705313ce477a1c6a7ed9ec71ad98 Mon Sep 17 00:00:00 2001
From: naskya <m@naskya.net>
Date: Mon, 22 Apr 2024 06:02:08 +0900
Subject: [PATCH 9/9] chore (minor, client): remove redundant attribute

---
 packages/client/src/pages/note-history.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/client/src/pages/note-history.vue b/packages/client/src/pages/note-history.vue
index c3665d41bc..8c97448f72 100644
--- a/packages/client/src/pages/note-history.vue
+++ b/packages/client/src/pages/note-history.vue
@@ -5,7 +5,7 @@
 		/></template>
 		<MkSpacer :content-max="800">
 			<MkLoading v-if="note == null" />
-			<div class="" v-else>
+			<div v-else>
 				<MkRemoteCaution
 					v-if="note.user.host != null"
 					:href="note.url ?? note.uri!"