Merge branch 'develop' into pag-back
This commit is contained in:
commit
72ae8441e1
54 changed files with 1558 additions and 2308 deletions
|
|
@ -57,24 +57,24 @@
|
|||
"@aws-sdk/client-s3": "3.367.0",
|
||||
"@aws-sdk/lib-storage": "3.367.0",
|
||||
"@aws-sdk/node-http-handler": "3.360.0",
|
||||
"@bull-board/api": "5.6.0",
|
||||
"@bull-board/fastify": "5.6.0",
|
||||
"@bull-board/ui": "5.6.0",
|
||||
"@bull-board/api": "5.6.1",
|
||||
"@bull-board/fastify": "5.6.1",
|
||||
"@bull-board/ui": "5.6.1",
|
||||
"@discordapp/twemoji": "14.1.2",
|
||||
"@fastify/accepts": "4.2.0",
|
||||
"@fastify/cookie": "8.3.0",
|
||||
"@fastify/cors": "8.3.0",
|
||||
"@fastify/http-proxy": "9.2.1",
|
||||
"@fastify/multipart": "7.7.0",
|
||||
"@fastify/multipart": "7.7.1",
|
||||
"@fastify/static": "6.10.2",
|
||||
"@fastify/view": "8.0.0",
|
||||
"@nestjs/common": "10.0.5",
|
||||
"@nestjs/core": "10.0.5",
|
||||
"@nestjs/testing": "10.0.5",
|
||||
"@nestjs/common": "10.1.0",
|
||||
"@nestjs/core": "10.1.0",
|
||||
"@nestjs/testing": "10.1.0",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sinonjs/fake-timers": "10.3.0",
|
||||
"@swc/cli": "0.1.62",
|
||||
"@swc/core": "1.3.69",
|
||||
"@swc/core": "1.3.70",
|
||||
"accepts": "1.3.8",
|
||||
"ajv": "8.12.0",
|
||||
"archiver": "5.3.1",
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
"autwh": "0.1.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "2.0.5",
|
||||
"bullmq": "4.3.0",
|
||||
"bullmq": "4.4.0",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "9.0.0",
|
||||
"chalk": "5.3.0",
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
"date-fns": "2.30.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"escape-regexp": "0.0.1",
|
||||
"fastify": "4.19.2",
|
||||
"fastify": "4.20.0",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "18.5.0",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@ import { IsNull, In, MoreThan, Not } from 'typeorm';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { LocalUser, RemoteUser } from '@/models/entities/User.js';
|
||||
import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
|
||||
import type { BlockingsRepository, FollowingsRepository, InstancesRepository, Muting, MutingsRepository, UserListJoiningsRepository, UsersRepository } from '@/models/index.js';
|
||||
import type { RelationshipJobData, ThinUser } from '@/queue/types.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { GlobalEventService } from '@/core/GlobalEventService.js';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { URL } from 'node:url';
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import * as Redis from 'ioredis';
|
||||
import type { Instance } from '@/models/entities/Instance.js';
|
||||
import type Logger from '@/logger.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
|
@ -10,7 +11,6 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
|
|||
import { bindThis } from '@/decorators.js';
|
||||
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
|
||||
import type { DOMWindow } from 'jsdom';
|
||||
import * as Redis from 'ioredis';
|
||||
|
||||
type NodeInfo = {
|
||||
openRegistrations?: unknown;
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
|||
where: {
|
||||
userId: data.reply.userId,
|
||||
threadId: data.reply.threadId ?? data.reply.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (!isThreadMuted) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Inject, Injectable, OnModuleInit, forwardRef } from '@nestjs/common';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import { IsNull } from 'typeorm';
|
||||
import type { LocalUser, PartialLocalUser, PartialRemoteUser, RemoteUser, User } from '@/models/entities/User.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
|
|
@ -21,9 +22,8 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
|
|||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import Logger from '../logger.js';
|
||||
import { IsNull } from 'typeorm';
|
||||
import { AccountMoveService } from '@/core/AccountMoveService.js';
|
||||
import Logger from '../logger.js';
|
||||
|
||||
const logger = new Logger('following/create');
|
||||
|
||||
|
|
@ -322,7 +322,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
where: {
|
||||
followerId: follower.id,
|
||||
followeeId: followee.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (following === null || !following.follower || !following.followee) {
|
||||
|
|
@ -412,8 +412,8 @@ export class UserFollowingService implements OnModuleInit {
|
|||
followerId: user.id,
|
||||
followee: {
|
||||
movedToUri: IsNull(),
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
const nonMovedFollowers = await this.followingsRepository.count({
|
||||
relations: {
|
||||
|
|
@ -423,8 +423,8 @@ export class UserFollowingService implements OnModuleInit {
|
|||
followeeId: user.id,
|
||||
follower: {
|
||||
movedToUri: IsNull(),
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
await this.usersRepository.update(
|
||||
{ id: user.id },
|
||||
|
|
@ -646,7 +646,7 @@ export class UserFollowingService implements OnModuleInit {
|
|||
where: {
|
||||
followeeId: followee.id,
|
||||
followerId: follower.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (!following || !following.followee || !following.follower) return;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export class VideoProcessingService {
|
|||
query({
|
||||
thumbnail: '1',
|
||||
url,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
|
|||
import type { AbuseUserReportsRepository } from '@/models/index.js';
|
||||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { AbuseUserReport } from '@/models/entities/AbuseUserReport.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class AbuseUserReportEntityService {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { AuthSessionsRepository } from '@/models/index.js';
|
|||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { AuthSession } from '@/models/entities/AuthSession.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import { AppEntityService } from './AppEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { AppEntityService } from './AppEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class AuthSessionEntityService {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export class ChannelEntityService {
|
|||
const hasUnreadNote = meId ? await this.noteUnreadsRepository.exist({
|
||||
where: {
|
||||
noteChannelId: channel.id,
|
||||
userId: meId
|
||||
userId: meId,
|
||||
},
|
||||
}) : undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { FollowRequestsRepository } from '@/models/index.js';
|
|||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { FollowRequest } from '@/models/entities/FollowRequest.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class FollowRequestEntityService {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
|
|||
import type { GalleryLikesRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { GalleryLike } from '@/models/entities/GalleryLike.js';
|
||||
import { GalleryPostEntityService } from './GalleryPostEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { GalleryPostEntityService } from './GalleryPostEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class GalleryLikeEntityService {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { ModerationLogsRepository } from '@/models/index.js';
|
|||
import { awaitAll } from '@/misc/prelude/await-all.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { ModerationLog } from '@/models/entities/ModerationLog.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class ModerationLogEntityService {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { NoteFavoritesRepository } from '@/models/index.js';
|
|||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { NoteFavorite } from '@/models/entities/NoteFavorite.js';
|
||||
import { NoteEntityService } from './NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NoteEntityService } from './NoteEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class NoteFavoriteEntityService {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { PageLikesRepository } from '@/models/index.js';
|
|||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { PageLike } from '@/models/entities/PageLike.js';
|
||||
import { PageEntityService } from './PageEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { PageEntityService } from './PageEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class PageLikeEntityService {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { DI } from '@/di-symbols.js';
|
|||
import type { SigninsRepository } from '@/models/index.js';
|
||||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { Signin } from '@/models/entities/Signin.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class SigninEntityService {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Writable, WritableOptions } from "node:stream";
|
||||
import { Writable, WritableOptions } from 'node:stream';
|
||||
|
||||
export class DevNull extends Writable implements NodeJS.WritableStream {
|
||||
constructor(opts?: WritableOptions) {
|
||||
super(opts);
|
||||
}
|
||||
constructor(opts?: WritableOptions) {
|
||||
super(opts);
|
||||
}
|
||||
|
||||
_write (chunk: any, encoding: BufferEncoding, cb: (err?: Error | null) => void) {
|
||||
setImmediate(cb);
|
||||
}
|
||||
_write (chunk: any, encoding: BufferEncoding, cb: (err?: Error | null) => void) {
|
||||
setImmediate(cb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|||
export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
|
||||
|
||||
export function parseUlid(id: string): { date: Date; } {
|
||||
const timestamp = id.slice(0, 10);
|
||||
let time = 0;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
time = time * 32 + CHARS.indexOf(timestamp[i]);
|
||||
}
|
||||
return { date: new Date(time) };
|
||||
const timestamp = id.slice(0, 10);
|
||||
let time = 0;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
time = time * 32 + CHARS.indexOf(timestamp[i]);
|
||||
}
|
||||
return { date: new Date(time) };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export async function awaitAll<T>(obj: Promiseable<T>): Promise<T> {
|
|||
const resolvedValues = await Promise.all(values.map(value =>
|
||||
(!value || !value.constructor || value.constructor.name !== 'Object')
|
||||
? value
|
||||
: awaitAll(value)
|
||||
: awaitAll(value),
|
||||
));
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ import { User } from '@/models/entities/User.js';
|
|||
import { UserIp } from '@/models/entities/UserIp.js';
|
||||
import { UserKeypair } from '@/models/entities/UserKeypair.js';
|
||||
import { UserList } from '@/models/entities/UserList.js';
|
||||
import { UserListFavorite } from './entities/UserListFavorite.js';
|
||||
import { UserListJoining } from '@/models/entities/UserListJoining.js';
|
||||
import { UserNotePining } from '@/models/entities/UserNotePining.js';
|
||||
import { UserPending } from '@/models/entities/UserPending.js';
|
||||
|
|
@ -64,6 +63,7 @@ import { Role } from '@/models/entities/Role.js';
|
|||
import { RoleAssignment } from '@/models/entities/RoleAssignment.js';
|
||||
import { Flash } from '@/models/entities/Flash.js';
|
||||
import { FlashLike } from '@/models/entities/FlashLike.js';
|
||||
import { UserListFavorite } from './entities/UserListFavorite.js';
|
||||
import type { Repository } from 'typeorm';
|
||||
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ import type { DriveFile } from '@/models/entities/DriveFile.js';
|
|||
import type { Note } from '@/models/entities/Note.js';
|
||||
import { EmailService } from '@/core/EmailService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { SearchService } from '@/core/SearchService.js';
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import type * as Bull from 'bullmq';
|
||||
import type { DbUserDeleteJobData } from '../types.js';
|
||||
import { SearchService } from "@/core/SearchService.js";
|
||||
|
||||
@Injectable()
|
||||
export class DeleteAccountProcessorService {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import type * as Bull from 'bullmq';
|
||||
|
||||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type Logger from '@/logger.js';
|
||||
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import { RelationshipJobData } from '../types.js';
|
||||
import type { UsersRepository } from '@/models/index.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { LocalUser, RemoteUser } from '@/models/entities/User.js';
|
||||
import { RelationshipJobData } from '../types.js';
|
||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||
import type * as Bull from 'bullmq';
|
||||
|
||||
@Injectable()
|
||||
export class RelationshipProcessorService {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { fileURLToPath } from 'node:url';
|
|||
import { dirname } from 'node:path';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import rename from 'rename';
|
||||
import sharp from 'sharp';
|
||||
import { sharpBmp } from 'sharp-read-bmp';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { DriveFile, DriveFilesRepository } from '@/models/index.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
|
|
@ -18,11 +20,9 @@ import { contentDisposition } from '@/misc/content-disposition.js';
|
|||
import { FileInfoService } from '@/core/FileInfoService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
|
||||
import { isMimeImage } from '@/misc/is-mime-image.js';
|
||||
import sharp from 'sharp';
|
||||
import { sharpBmp } from 'sharp-read-bmp';
|
||||
import { correctFilename } from '@/misc/correct-filename.js';
|
||||
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
|
@ -180,8 +180,8 @@ export class FileServerService {
|
|||
reply.header('Content-Disposition',
|
||||
contentDisposition(
|
||||
'inline',
|
||||
correctFilename(file.filename, image.ext)
|
||||
)
|
||||
correctFilename(file.filename, image.ext),
|
||||
),
|
||||
);
|
||||
return image.data;
|
||||
}
|
||||
|
|
@ -278,11 +278,11 @@ export class FileServerService {
|
|||
};
|
||||
} else {
|
||||
const data = (await sharpBmp(file.path, file.mime, { animated: !('static' in request.query) }))
|
||||
.resize({
|
||||
height: 'emoji' in request.query ? 128 : 320,
|
||||
withoutEnlargement: true,
|
||||
})
|
||||
.webp(webpDefault);
|
||||
.resize({
|
||||
height: 'emoji' in request.query ? 128 : 320,
|
||||
withoutEnlargement: true,
|
||||
})
|
||||
.webp(webpDefault);
|
||||
|
||||
image = {
|
||||
data,
|
||||
|
|
@ -355,8 +355,8 @@ export class FileServerService {
|
|||
reply.header('Content-Disposition',
|
||||
contentDisposition(
|
||||
'inline',
|
||||
correctFilename(file.filename, image.ext)
|
||||
)
|
||||
correctFilename(file.filename, image.ext),
|
||||
),
|
||||
);
|
||||
return image.data;
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { IsNull } from 'typeorm';
|
||||
import vary from 'vary';
|
||||
import fastifyAccepts from '@fastify/accepts';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { UsersRepository } from '@/models/index.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { escapeAttribute, escapeValue } from '@/misc/prelude/xml.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import * as Acct from '@/misc/acct.js';
|
||||
import { NodeinfoServerService } from './NodeinfoServerService.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import type { FindOptionsWhere } from 'typeorm';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { NodeinfoServerService } from './NodeinfoServerService.js';
|
||||
import type { FindOptionsWhere } from 'typeorm';
|
||||
import type { FastifyInstance, FastifyPluginOptions } from 'fastify';
|
||||
import fastifyAccepts from '@fastify/accepts';
|
||||
|
||||
@Injectable()
|
||||
export class WellKnownServerService {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import { EmailService } from '@/core/EmailService.js';
|
|||
import { LocalUser } from '@/models/entities/User.js';
|
||||
import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
|
||||
import { SigninService } from './SigninService.js';
|
||||
import type { FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { L_CHARS, secureRndstr } from '@/misc/secure-rndstr.js';
|
||||
|
||||
@Injectable()
|
||||
export class SignupApiService {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
|
||||
if (queryarry) {
|
||||
emojis = emojis.filter(emoji =>
|
||||
queryarry.includes(`:${emoji.name}:`)
|
||||
queryarry.includes(`:${emoji.name}:`),
|
||||
);
|
||||
} else {
|
||||
emojis = emojis.filter(emoji =>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { UsersRepository, BlockingsRepository } from '@/models/index.js';
|
|||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { UserBlockingService } from '@/core/UserBlockingService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['account'],
|
||||
|
|
@ -88,7 +88,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
where: {
|
||||
blockerId: blocker.id,
|
||||
blockeeId: blockee.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (!exist) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import type { ClipNotesRepository, ClipsRepository } from '@/models/index.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['account', 'notes', 'clips'],
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
|
|||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'users'],
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { UsersRepository, FollowingsRepository } from '@/models/index.js';
|
|||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { UserFollowingService } from '@/core/UserFollowingService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['following', 'users'],
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const meta = {
|
|||
id: 'e5b3b9f0-2b8f-4b9f-9c1f-8c5c1b2e1b1a',
|
||||
kind: 'permission',
|
||||
},
|
||||
}
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
super(meta, paramDef, async (ps, me) => {
|
||||
const instance = await this.metaService.fetch(true);
|
||||
|
||||
const ads = await this.adsRepository.createQueryBuilder("ads")
|
||||
const ads = await this.adsRepository.createQueryBuilder('ads')
|
||||
.where('ads.expiresAt > :now', { now: new Date() })
|
||||
.andWhere('ads.startsAt <= :now', { now: new Date() })
|
||||
.andWhere(new Brackets(qb => {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import type { NotesRepository } from '@/models/index.js';
|
|||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import type { NotesRepository } from '@/models/index.js';
|
|||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import type { PromoReadsRepository } from '@/models/index.js';
|
|||
import { IdService } from '@/core/IdService.js';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export const meta = {
|
|||
code: 'NO_SUCH_REGISTRATION',
|
||||
id: ' b09d8066-8064-5613-efb6-0e963b21d012',
|
||||
},
|
||||
}
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import type { NotesRepository, UsersRepository } from '@/models/index.js';
|
|||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['users'],
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { isUserRelated } from '@/misc/is-user-related.js';
|
|||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import Channel from '../channel.js';
|
||||
import { StreamMessages } from '../types.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
|
||||
class RoleTimelineChannel extends Channel {
|
||||
public readonly chName = 'roleTimeline';
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@
|
|||
"@rollup/plugin-json": "6.0.0",
|
||||
"@rollup/plugin-replace": "5.0.2",
|
||||
"@rollup/pluginutils": "5.0.2",
|
||||
"@syuilo/aiscript": "0.13.3",
|
||||
"@syuilo/aiscript": "0.14.0",
|
||||
"@tabler/icons-webfont": "2.25.0",
|
||||
"@vitejs/plugin-vue": "4.2.3",
|
||||
"@vue-macros/reactivity-transform": "0.3.14",
|
||||
"@vue-macros/reactivity-transform": "0.3.15",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"astring": "1.8.6",
|
||||
"autosize": "6.0.1",
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
"prismjs": "1.29.0",
|
||||
"punycode": "2.3.0",
|
||||
"querystring": "0.2.1",
|
||||
"rollup": "3.26.2",
|
||||
"rollup": "3.26.3",
|
||||
"s-age": "1.1.2",
|
||||
"sanitize-html": "2.11.0",
|
||||
"sass": "1.63.6",
|
||||
|
|
@ -77,24 +77,24 @@
|
|||
"vuedraggable": "next"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "7.0.27",
|
||||
"@storybook/addon-essentials": "7.0.27",
|
||||
"@storybook/addon-interactions": "7.0.27",
|
||||
"@storybook/addon-links": "7.0.27",
|
||||
"@storybook/addon-storysource": "7.0.27",
|
||||
"@storybook/addons": "7.0.27",
|
||||
"@storybook/blocks": "7.0.27",
|
||||
"@storybook/core-events": "7.0.27",
|
||||
"@storybook/addon-actions": "7.1.0",
|
||||
"@storybook/addon-essentials": "7.1.0",
|
||||
"@storybook/addon-interactions": "7.1.0",
|
||||
"@storybook/addon-links": "7.1.0",
|
||||
"@storybook/addon-storysource": "7.1.0",
|
||||
"@storybook/addons": "7.1.0",
|
||||
"@storybook/blocks": "7.1.0",
|
||||
"@storybook/core-events": "7.1.0",
|
||||
"@storybook/jest": "0.1.0",
|
||||
"@storybook/manager-api": "7.0.27",
|
||||
"@storybook/preview-api": "7.0.27",
|
||||
"@storybook/react": "7.0.27",
|
||||
"@storybook/react-vite": "7.0.27",
|
||||
"@storybook/manager-api": "7.1.0",
|
||||
"@storybook/preview-api": "7.1.0",
|
||||
"@storybook/react": "7.1.0",
|
||||
"@storybook/react-vite": "7.1.0",
|
||||
"@storybook/testing-library": "0.2.0",
|
||||
"@storybook/theming": "7.0.27",
|
||||
"@storybook/types": "7.0.27",
|
||||
"@storybook/vue3": "7.0.27",
|
||||
"@storybook/vue3-vite": "7.0.27",
|
||||
"@storybook/theming": "7.1.0",
|
||||
"@storybook/types": "7.1.0",
|
||||
"@storybook/vue3": "7.1.0",
|
||||
"@storybook/vue3-vite": "7.1.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/vue": "7.0.0",
|
||||
"@types/escape-regexp": "0.0.1",
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"start-server-and-test": "2.0.0",
|
||||
"storybook": "7.0.27",
|
||||
"storybook": "7.1.0",
|
||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||
"summaly": "github:misskey-dev/summaly",
|
||||
"vite-plugin-turbosnap": "1.0.2",
|
||||
|
|
|
|||
|
|
@ -259,6 +259,17 @@ useTooltip(renoteButton, async (showing) => {
|
|||
}, {}, 'closed');
|
||||
});
|
||||
|
||||
type Visibility = 'public' | 'home' | 'followers' | 'specified';
|
||||
|
||||
// defaultStore.state.visibilityがstringなためstringも受け付けている
|
||||
function smallerVisibility(a: Visibility | string, b: Visibility | string): Visibility {
|
||||
if (a === 'specified' || b === 'specified') return 'specified';
|
||||
if (a === 'followers' || b === 'followers') return 'followers';
|
||||
if (a === 'home' || b === 'home') return 'home';
|
||||
// if (a === 'public' || b === 'public')
|
||||
return 'public';
|
||||
}
|
||||
|
||||
function renote(viaKeyboard = false) {
|
||||
pleaseLogin();
|
||||
showMovedDialog();
|
||||
|
|
@ -309,7 +320,12 @@ function renote(viaKeyboard = false) {
|
|||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||
}
|
||||
|
||||
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
|
||||
const localOnly = defaultStore.state.rememberNoteVisibility ? defaultStore.state.localOnly : defaultStore.state.defaultNoteLocalOnly;
|
||||
|
||||
os.api('notes/create', {
|
||||
localOnly,
|
||||
visibility: smallerVisibility(appearNote.visibility, configuredVisibility),
|
||||
renoteId: appearNote.id,
|
||||
}).then(() => {
|
||||
os.toast(i18n.ts.renoted);
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
</div>
|
||||
<div :class="$style.status">
|
||||
<div :class="$style.statusItem">
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.notes }}</p><span :class="$style.statusItemValue">{{ user.notesCount }}</span>
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.notes }}</p><span :class="$style.statusItemValue">{{ number(user.notesCount) }}</span>
|
||||
</div>
|
||||
<div :class="$style.statusItem">
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.following }}</p><span :class="$style.statusItemValue">{{ user.followingCount }}</span>
|
||||
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.following }}</p><span :class="$style.statusItemValue">{{ number(user.followingCount) }}</span>
|
||||
</div>
|
||||
<div :class="$style.statusItem">
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ user.followersCount }}</span>
|
||||
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
|
||||
<p :class="$style.statusItemLabel">{{ i18n.ts.followers }}</p><span :class="$style.statusItemValue">{{ number(user.followersCount) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<MkFollowButton v-if="$i && user.id != $i.id" :class="$style.follow" :user="user" mini/>
|
||||
|
|
@ -31,9 +31,11 @@
|
|||
<script lang="ts" setup>
|
||||
import * as misskey from 'misskey-js';
|
||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||
import number from '@/filters/number';
|
||||
import { userPage } from '@/filters/user';
|
||||
import { i18n } from '@/i18n';
|
||||
import { $i } from '@/account';
|
||||
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
|
||||
|
||||
defineProps<{
|
||||
user: misskey.entities.UserDetailed;
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@
|
|||
<div :class="$style.statusItemLabel">{{ i18n.ts.notes }}</div>
|
||||
<div>{{ number(user.notesCount) }}</div>
|
||||
</div>
|
||||
<div :class="$style.statusItem">
|
||||
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
|
||||
<div :class="$style.statusItemLabel">{{ i18n.ts.following }}</div>
|
||||
<div>{{ number(user.followingCount) }}</div>
|
||||
</div>
|
||||
<div :class="$style.statusItem">
|
||||
<div v-if="isFfVisibleForMe(user)" :class="$style.statusItem">
|
||||
<div :class="$style.statusItemLabel">{{ i18n.ts.followers }}</div>
|
||||
<div>{{ number(user.followersCount) }}</div>
|
||||
</div>
|
||||
|
|
@ -61,6 +61,7 @@ import number from '@/filters/number';
|
|||
import { i18n } from '@/i18n';
|
||||
import { defaultStore } from '@/store';
|
||||
import { $i } from '@/account';
|
||||
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
|
||||
|
||||
const props = defineProps<{
|
||||
showing: boolean;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
|||
import MkInput from '@/components/MkInput.vue';
|
||||
import { useRouter } from '@/router';
|
||||
|
||||
const PRESET_DEFAULT = `/// @ 0.13.3
|
||||
const PRESET_DEFAULT = `/// @ 0.14.0
|
||||
|
||||
var name = ""
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ Ui:render([
|
|||
])
|
||||
`;
|
||||
|
||||
const PRESET_OMIKUJI = `/// @ 0.13.3
|
||||
const PRESET_OMIKUJI = `/// @ 0.14.0
|
||||
// ユーザーごとに日替わりのおみくじのプリセット
|
||||
|
||||
// 選択肢
|
||||
|
|
@ -94,7 +94,7 @@ Ui:render([
|
|||
])
|
||||
`;
|
||||
|
||||
const PRESET_SHUFFLE = `/// @ 0.13.3
|
||||
const PRESET_SHUFFLE = `/// @ 0.14.0
|
||||
// 巻き戻し可能な文字シャッフルのプリセット
|
||||
|
||||
let string = "ペペロンチーノ"
|
||||
|
|
@ -173,7 +173,7 @@ var cursor = 0
|
|||
do()
|
||||
`;
|
||||
|
||||
const PRESET_QUIZ = `/// @ 0.13.3
|
||||
const PRESET_QUIZ = `/// @ 0.14.0
|
||||
let title = '地理クイズ'
|
||||
|
||||
let qas = [{
|
||||
|
|
@ -286,7 +286,7 @@ qaEls.push(Ui:C:container({
|
|||
Ui:render(qaEls)
|
||||
`;
|
||||
|
||||
const PRESET_TIMELINE = `/// @ 0.13.3
|
||||
const PRESET_TIMELINE = `/// @ 0.14.0
|
||||
// APIリクエストを行いローカルタイムラインを表示するプリセット
|
||||
|
||||
@fetch() {
|
||||
|
|
|
|||
|
|
@ -100,15 +100,15 @@
|
|||
</dl>
|
||||
</div>
|
||||
<div class="status">
|
||||
<MkA v-click-anime :to="userPage(user)">
|
||||
<MkA :to="userPage(user)">
|
||||
<b>{{ number(user.notesCount) }}</b>
|
||||
<span>{{ i18n.ts.notes }}</span>
|
||||
</MkA>
|
||||
<MkA v-click-anime :to="userPage(user, 'following')">
|
||||
<MkA v-if="isFfVisibleForMe(user)" :to="userPage(user, 'following')">
|
||||
<b>{{ number(user.followingCount) }}</b>
|
||||
<span>{{ i18n.ts.following }}</span>
|
||||
</MkA>
|
||||
<MkA v-click-anime :to="userPage(user, 'followers')">
|
||||
<MkA v-if="isFfVisibleForMe(user)" :to="userPage(user, 'followers')">
|
||||
<b>{{ number(user.followersCount) }}</b>
|
||||
<span>{{ i18n.ts.followers }}</span>
|
||||
</MkA>
|
||||
|
|
@ -160,6 +160,7 @@ import { dateString } from '@/filters/date';
|
|||
import { confetti } from '@/scripts/confetti';
|
||||
import MkNotes from '@/components/MkNotes.vue';
|
||||
import { api } from '@/os';
|
||||
import { isFfVisibleForMe } from '@/scripts/isFfVisibleForMe';
|
||||
|
||||
const XPhotos = defineAsyncComponent(() => import('./index.photos.vue'));
|
||||
const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
|
||||
|
|
|
|||
11
packages/frontend/src/scripts/isFfVisibleForMe.ts
Normal file
11
packages/frontend/src/scripts/isFfVisibleForMe.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import * as misskey from 'misskey-js';
|
||||
import { $i } from '@/account';
|
||||
|
||||
export function isFfVisibleForMe(user: misskey.entities.UserDetailed): boolean {
|
||||
if ($i && $i.id === user.id) return true;
|
||||
|
||||
if (user.ffVisibility === 'private') return false;
|
||||
if (user.ffVisibility === 'followers' && !user.isFollowing) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue