mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-24 17:24:14 +02:00
Merge branch 'develop' into mahjong
This commit is contained in:
@@ -32,6 +32,7 @@ import { isQuote, isRenote } from '@/misc/is-renote.js';
|
||||
import * as Acct from '@/misc/acct.js';
|
||||
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify';
|
||||
import type { FindOptionsWhere } from 'typeorm';
|
||||
import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js';
|
||||
|
||||
const ACTIVITY_JSON = 'application/activity+json; charset=utf-8';
|
||||
const LD_JSON = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8';
|
||||
@@ -75,6 +76,7 @@ export class ActivityPubServerService {
|
||||
private queueService: QueueService,
|
||||
private userKeypairService: UserKeypairService,
|
||||
private queryService: QueryService,
|
||||
private fanoutTimelineEndpointService: FanoutTimelineEndpointService,
|
||||
) {
|
||||
//this.createServer = this.createServer.bind(this);
|
||||
}
|
||||
@@ -461,16 +463,28 @@ export class ActivityPubServerService {
|
||||
const partOf = `${this.config.url}/users/${userId}/outbox`;
|
||||
|
||||
if (page) {
|
||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId)
|
||||
.andWhere('note.userId = :userId', { userId: user.id })
|
||||
.andWhere(new Brackets(qb => {
|
||||
qb
|
||||
.where('note.visibility = \'public\'')
|
||||
.orWhere('note.visibility = \'home\'');
|
||||
}))
|
||||
.andWhere('note.localOnly = FALSE');
|
||||
|
||||
const notes = await query.limit(limit).getMany();
|
||||
const notes = this.meta.enableFanoutTimeline ? await this.fanoutTimelineEndpointService.getMiNotes({
|
||||
sinceId: sinceId ?? null,
|
||||
untilId: untilId ?? null,
|
||||
limit: limit,
|
||||
allowPartial: false, // Possibly true? IDK it's OK for ordered collection.
|
||||
me: null,
|
||||
redisTimelines: [
|
||||
`userTimeline:${user.id}`,
|
||||
`userTimelineWithReplies:${user.id}`,
|
||||
],
|
||||
useDbFallback: true,
|
||||
ignoreAuthorFromMute: true,
|
||||
excludePureRenotes: false,
|
||||
noteFilter: (note) => {
|
||||
if (note.visibility !== 'home' && note.visibility !== 'public') return false;
|
||||
if (note.localOnly) return false;
|
||||
return true;
|
||||
},
|
||||
dbFallback: async (untilId, sinceId, limit) => {
|
||||
return await this.getUserNotesFromDb(sinceId, untilId, limit, user.id);
|
||||
},
|
||||
}) : await this.getUserNotesFromDb(sinceId ?? null, untilId ?? null, limit, user.id);
|
||||
|
||||
if (sinceId) notes.reverse();
|
||||
|
||||
@@ -508,6 +522,20 @@ export class ActivityPubServerService {
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async getUserNotesFromDb(untilId: string | null, sinceId: string | null, limit: number, userId: MiUser['id']) {
|
||||
return await this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), sinceId, untilId)
|
||||
.andWhere('note.userId = :userId', { userId })
|
||||
.andWhere(new Brackets(qb => {
|
||||
qb
|
||||
.where('note.visibility = \'public\'')
|
||||
.orWhere('note.visibility = \'home\'');
|
||||
}))
|
||||
.andWhere('note.localOnly = FALSE')
|
||||
.limit(limit)
|
||||
.getMany();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async userInfo(request: FastifyRequest, reply: FastifyReply, user: MiUser | null) {
|
||||
if (this.meta.federation === 'none') {
|
||||
@@ -735,7 +763,7 @@ export class ActivityPubServerService {
|
||||
const acct = Acct.parse(request.params.acct);
|
||||
|
||||
const user = await this.usersRepository.findOneBy({
|
||||
usernameLower: acct.username,
|
||||
usernameLower: acct.username.toLowerCase(),
|
||||
host: acct.host ?? IsNull(),
|
||||
isSuspended: false,
|
||||
});
|
||||
|
||||
@@ -221,7 +221,7 @@ export class ServerService implements OnApplicationShutdown {
|
||||
reply.header('Cache-Control', 'public, max-age=86400');
|
||||
|
||||
if (user) {
|
||||
reply.redirect(user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user));
|
||||
reply.redirect((user.avatarId == null ? null : user.avatarUrl) ?? this.userEntityService.getIdenticonUrl(user));
|
||||
} else {
|
||||
reply.redirect('/static-assets/user-unknown.png');
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ fastify.get('/.well-known/change-password', async (request, reply) => {
|
||||
|
||||
const fromAcct = (acct: Acct.Acct): FindOptionsWhere<MiUser> | number =>
|
||||
!acct.host || acct.host === this.config.host.toLowerCase() ? {
|
||||
usernameLower: acct.username,
|
||||
usernameLower: acct.username.toLowerCase(),
|
||||
host: IsNull(),
|
||||
isSuspended: false,
|
||||
} : 422;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { QUEUE_TYPES, QueueService } from '@/core/QueueService.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@@ -18,8 +18,11 @@ export const meta = {
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
properties: {
|
||||
type: { type: 'string', enum: QUEUE_TYPES },
|
||||
state: { type: 'string', enum: ['*', 'wait', 'delayed'] },
|
||||
},
|
||||
required: ['type', 'state'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
@@ -29,7 +32,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
private queueService: QueueService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
this.queueService.destroy();
|
||||
this.queueService.clearQueue(ps.type, ps.state);
|
||||
|
||||
this.moderationLogService.log(me, 'clearQueue');
|
||||
});
|
||||
|
||||
@@ -534,7 +534,7 @@ export class ClientServerService {
|
||||
|
||||
return await reply.view('user', {
|
||||
user, profile, me,
|
||||
avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
||||
avatarUrl: _user.avatarUrl,
|
||||
sub: request.params.sub,
|
||||
...await this.generateCommonPugData(this.meta),
|
||||
clientCtx: htmlSafeJsonStringify({
|
||||
|
||||
@@ -65,7 +65,7 @@ export class FeedService {
|
||||
generator: 'Misskey',
|
||||
description: `${user.notesCount} Notes, ${profile.followingVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.followersVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`,
|
||||
link: author.link,
|
||||
image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
||||
image: (user.avatarId == null ? null : user.avatarUrl) ?? this.userEntityService.getIdenticonUrl(user),
|
||||
feedLinks: {
|
||||
json: `${author.link}.json`,
|
||||
atom: `${author.link}.atom`,
|
||||
|
||||
Reference in New Issue
Block a user