Exclude channel notes from featured polls (#13838)
* feat(backend): add `channelId` to `MiPoll` as a Denormalized field * feat(backend): option to exclude polls in channels * chore: exclude channel notes from featured polls * docs(changelog): みつけるのアンケート欄にてチャンネルのアンケートが含まれてしまう問題を修正 * fix: missing license header
This commit is contained in:
parent
4d0db37d2e
commit
f6df94070b
7 changed files with 44 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
||||||
- 「アカウントを見つけやすくする」が有効なユーザーか
|
- 「アカウントを見つけやすくする」が有効なユーザーか
|
||||||
- Fix: Play作成時に設定した公開範囲が機能していない問題を修正
|
- Fix: Play作成時に設定した公開範囲が機能していない問題を修正
|
||||||
- Fix: 正規化されていない状態のhashtagが連合されてきたhtmlに含まれているとhashtagが正しくhashtagに復元されない問題を修正
|
- Fix: 正規化されていない状態のhashtagが連合されてきたhtmlに含まれているとhashtagが正しくhashtagに復元されない問題を修正
|
||||||
|
- Fix: みつけるのアンケート欄にてチャンネルのアンケートが含まれてしまう問題を修正
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
- Feat: アップロードするファイルの名前をランダム文字列にできるように
|
- Feat: アップロードするファイルの名前をランダム文字列にできるように
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class ChannelIdDenormalizedForMiPoll1716129964060 {
|
||||||
|
name = 'ChannelIdDenormalizedForMiPoll1716129964060'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "poll" ADD "channelId" character varying(32)`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "poll"."channelId" IS '[Denormalized]'`);
|
||||||
|
await queryRunner.query(`CREATE INDEX "IDX_c1240fcc9675946ea5d6c2860e" ON "poll" ("channelId") `);
|
||||||
|
await queryRunner.query(`UPDATE "poll" SET "channelId" = "note"."channelId" FROM "note" WHERE "poll"."noteId" = "note"."id"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`DROP INDEX "public"."IDX_c1240fcc9675946ea5d6c2860e"`);
|
||||||
|
await queryRunner.query(`COMMENT ON COLUMN "poll"."channelId" IS '[Denormalized]'`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "poll" DROP COLUMN "channelId"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -473,6 +473,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
noteVisibility: insert.visibility,
|
noteVisibility: insert.visibility,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
userHost: user.host,
|
userHost: user.host,
|
||||||
|
channelId: insert.channelId,
|
||||||
});
|
});
|
||||||
|
|
||||||
await transactionalEntityManager.insert(MiPoll, poll);
|
await transactionalEntityManager.insert(MiPoll, poll);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { noteVisibilities } from '@/types.js';
|
||||||
import { id } from './util/id.js';
|
import { id } from './util/id.js';
|
||||||
import { MiNote } from './Note.js';
|
import { MiNote } from './Note.js';
|
||||||
import type { MiUser } from './User.js';
|
import type { MiUser } from './User.js';
|
||||||
|
import type { MiChannel } from "@/models/Channel.js";
|
||||||
|
|
||||||
@Entity('poll')
|
@Entity('poll')
|
||||||
export class MiPoll {
|
export class MiPoll {
|
||||||
|
@ -58,6 +59,14 @@ export class MiPoll {
|
||||||
comment: '[Denormalized]',
|
comment: '[Denormalized]',
|
||||||
})
|
})
|
||||||
public userHost: string | null;
|
public userHost: string | null;
|
||||||
|
|
||||||
|
@Index()
|
||||||
|
@Column({
|
||||||
|
...id(),
|
||||||
|
nullable: true,
|
||||||
|
comment: '[Denormalized]',
|
||||||
|
})
|
||||||
|
public channelId: MiChannel['id'] | null;
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
constructor(data: Partial<MiPoll>) {
|
constructor(data: Partial<MiPoll>) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ export const paramDef = {
|
||||||
properties: {
|
properties: {
|
||||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||||
offset: { type: 'integer', default: 0 },
|
offset: { type: 'integer', default: 0 },
|
||||||
|
excludeChannels: { type: 'boolean', default: false },
|
||||||
},
|
},
|
||||||
required: [],
|
required: [],
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -86,6 +87,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
query.setParameters(mutingQuery.getParameters());
|
query.setParameters(mutingQuery.getParameters());
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region exclude channels
|
||||||
|
if (ps.excludeChannels) {
|
||||||
|
query.andWhere('poll.channelId IS NULL');
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
const polls = await query
|
const polls = await query
|
||||||
.orderBy('poll.noteId', 'DESC')
|
.orderBy('poll.noteId', 'DESC')
|
||||||
.limit(ps.limit)
|
.limit(ps.limit)
|
||||||
|
|
|
@ -29,6 +29,9 @@ const paginationForPolls = {
|
||||||
endpoint: 'notes/polls/recommendation' as const,
|
endpoint: 'notes/polls/recommendation' as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
offsetMode: true,
|
offsetMode: true,
|
||||||
|
params: {
|
||||||
|
excludeChannels: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const tab = ref('notes');
|
const tab = ref('notes');
|
||||||
|
|
|
@ -21019,6 +21019,8 @@ export type operations = {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
/** @default 0 */
|
/** @default 0 */
|
||||||
offset?: number;
|
offset?: number;
|
||||||
|
/** @default false */
|
||||||
|
excludeChannels?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue