Merge remote-tracking branch 'misskey-original/develop' into develop
# Conflicts: # locales/index.d.ts # locales/ja-JP.yml # package.json # packages/backend/src/core/RoleService.ts # packages/backend/src/server/api/endpoints/notes/create.ts # packages/frontend/src/components/MkTimeline.vue # packages/frontend/src/const.ts # packages/frontend/src/pages/admin/roles.editor.vue # packages/frontend/src/pages/settings/general.vue # packages/frontend/src/pages/timeline.vue # packages/frontend/src/store.ts # packages/frontend/src/ui/_common_/stream-indicator.vue # packages/frontend/src/ui/universal.vue
This commit is contained in:
commit
9199a493f1
50 changed files with 537 additions and 121 deletions
|
|
@ -24,6 +24,7 @@ import { bindThis } from '@/decorators.js';
|
|||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { SearchService } from '@/core/SearchService.js';
|
||||
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||
import { isPureRenote } from '@/misc/is-pure-renote.js';
|
||||
|
||||
@Injectable()
|
||||
export class NoteDeleteService {
|
||||
|
|
@ -77,8 +78,8 @@ export class NoteDeleteService {
|
|||
if (this.userEntityService.isLocalUser(user) && !note.localOnly) {
|
||||
let renote: MiNote | null = null;
|
||||
|
||||
// if deletd note is renote
|
||||
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
|
||||
// if deleted note is renote
|
||||
if (isPureRenote(note)) {
|
||||
renote = await this.notesRepository.findOneBy({
|
||||
id: note.renoteId,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export type RolePolicies = {
|
|||
inviteExpirationTime: number;
|
||||
canManageCustomEmojis: boolean;
|
||||
canRequestCustomEmojis: boolean;
|
||||
canManageAvatarDecorations: boolean;
|
||||
canSearchNotes: boolean;
|
||||
canUseTranslator: boolean;
|
||||
canHideAds: boolean;
|
||||
|
|
@ -60,6 +61,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
|||
inviteLimitCycle: 60 * 24 * 7,
|
||||
inviteExpirationTime: 0,
|
||||
canManageCustomEmojis: false,
|
||||
canManageAvatarDecorations: false,
|
||||
canRequestCustomEmojis: false,
|
||||
canSearchNotes: false,
|
||||
canUseTranslator: true,
|
||||
|
|
@ -311,6 +313,7 @@ export class RoleService implements OnApplicationShutdown {
|
|||
inviteLimitCycle: calc('inviteLimitCycle', vs => Math.max(...vs)),
|
||||
inviteExpirationTime: calc('inviteExpirationTime', vs => Math.max(...vs)),
|
||||
canManageCustomEmojis: calc('canManageCustomEmojis', vs => vs.some(v => v === true)),
|
||||
canManageAvatarDecorations: calc('canManageAvatarDecorations', vs => vs.some(v => v === true)),
|
||||
canRequestCustomEmojis: calc('canRequestCustomEmojis', vs => vs.some(v => v === true)),
|
||||
canSearchNotes: calc('canSearchNotes', vs => vs.some(v => v === true)),
|
||||
canUseTranslator: calc('canUseTranslator', vs => vs.some(v => v === true)),
|
||||
|
|
|
|||
|
|
@ -319,9 +319,17 @@ export class ApPersonService implements OnModuleInit {
|
|||
emojis,
|
||||
})) as MiRemoteUser;
|
||||
|
||||
let _description: string | null = null;
|
||||
|
||||
if (person._misskey_summary) {
|
||||
_description = truncate(person._misskey_summary, summaryLength);
|
||||
} else if (person.summary) {
|
||||
_description = this.apMfmService.htmlToMfm(truncate(person.summary, summaryLength), person.tag);
|
||||
}
|
||||
|
||||
await transactionalEntityManager.save(new MiUserProfile({
|
||||
userId: user.id,
|
||||
description: person._misskey_summary ? truncate(person._misskey_summary, summaryLength) : person.summary ? this.apMfmService.htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null,
|
||||
description: _description,
|
||||
url,
|
||||
fields,
|
||||
birthday: bday?.[0] ?? null,
|
||||
|
|
@ -487,10 +495,18 @@ export class ApPersonService implements OnModuleInit {
|
|||
});
|
||||
}
|
||||
|
||||
let _description: string | null = null;
|
||||
|
||||
if (person._misskey_summary) {
|
||||
_description = truncate(person._misskey_summary, summaryLength);
|
||||
} else if (person.summary) {
|
||||
_description = this.apMfmService.htmlToMfm(truncate(person.summary, summaryLength), person.tag);
|
||||
}
|
||||
|
||||
await this.userProfilesRepository.update({ userId: exist.id }, {
|
||||
url,
|
||||
fields,
|
||||
description: person.summary ? this.apMfmService.htmlToMfm(truncate(person.summary, summaryLength), person.tag) : null,
|
||||
description: _description,
|
||||
birthday: bday?.[0] ?? null,
|
||||
location: person['vcard:Address'] ?? null,
|
||||
});
|
||||
|
|
|
|||
10
packages/backend/src/misc/is-pure-renote.ts
Normal file
10
packages/backend/src/misc/is-pure-renote.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { MiNote } from '@/models/Note.js';
|
||||
|
||||
export function isPureRenote(note: MiNote): note is MiNote & { renoteId: NonNullable<MiNote['renoteId']> } {
|
||||
if (!note.renoteId) return false;
|
||||
|
||||
if (note.text) return false; // it's quoted with text
|
||||
if (note.fileIds.length !== 0) return false; // it's quoted with files
|
||||
if (note.hasPoll) return false; // it's quoted with poll
|
||||
return true;
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ import { UtilityService } from '@/core/UtilityService.js';
|
|||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { IActivity } from '@/core/activitypub/type.js';
|
||||
import { isPureRenote } from '@/misc/is-pure-renote.js';
|
||||
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
|
||||
import type { FindOptionsWhere } from 'typeorm';
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ export class ActivityPubServerService {
|
|||
*/
|
||||
@bindThis
|
||||
private async packActivity(note: MiNote): Promise<any> {
|
||||
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
|
||||
if (isPureRenote(note)) {
|
||||
const renote = await this.notesRepository.findOneByOrFail({ id: note.renoteId });
|
||||
return this.apRendererService.renderAnnounce(renote.uri ? renote.uri : `${this.config.url}/notes/${renote.id}`, note);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const meta = {
|
|||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
requireRolePolicy: 'canManageAvatarDecorations',
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ export const meta = {
|
|||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
|
||||
requireRolePolicy: 'canManageAvatarDecorations',
|
||||
errors: {
|
||||
},
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export const meta = {
|
|||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
requireRolePolicy: 'canManageAvatarDecorations',
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const meta = {
|
|||
tags: ['admin'],
|
||||
|
||||
requireCredential: true,
|
||||
requireModerator: true,
|
||||
requireRolePolicy: 'canManageAvatarDecorations',
|
||||
|
||||
errors: {
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { NoteCreateService } from '@/core/NoteCreateService.js';
|
|||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import {noteVisibilities} from "@/types.js";
|
||||
import { isPureRenote } from '@/misc/is-pure-renote.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
|
@ -222,7 +223,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
if (renote == null) {
|
||||
throw new ApiError(meta.errors.noSuchRenoteTarget);
|
||||
} else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.hasPoll) {
|
||||
} else if (isPureRenote(renote)) {
|
||||
throw new ApiError(meta.errors.cannotReRenote);
|
||||
}
|
||||
|
||||
|
|
@ -255,7 +256,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
if (reply == null) {
|
||||
throw new ApiError(meta.errors.noSuchReplyTarget);
|
||||
} else if (reply.renoteId && !reply.text && !reply.fileIds && !reply.hasPoll) {
|
||||
} else if (isPureRenote(reply)) {
|
||||
throw new ApiError(meta.errors.cannotReplyToPureRenote);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
const followingChannelIds = followingChannels.map(x => x.followeeId);
|
||||
query.andWhere(new Brackets(qb => {
|
||||
qb
|
||||
.where('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds })
|
||||
.where(new Brackets(qb2 => {
|
||||
qb2
|
||||
.where('note.userId IN (:...meOrFolloweeIds)', { meOrFolloweeIds: meOrFolloweeIds })
|
||||
.andWhere('note.channelId IS NULL');
|
||||
}))
|
||||
.orWhere('note.channelId IN (:...followingChannelIds)', { followingChannelIds });
|
||||
}));
|
||||
} else if (followees.length > 0) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ export default abstract class Channel {
|
|||
}
|
||||
|
||||
public abstract init(params: any): void;
|
||||
|
||||
public dispose?(): void;
|
||||
|
||||
public onMessage?(type: string, body: any): void;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue