fix: wrong json subtype
This commit is contained in:
parent
b40e20a207
commit
ada1698ead
|
|
@ -40,7 +40,7 @@ import { RoleService } from '@/core/RoleService.js';
|
||||||
import { FeedService } from './FeedService.js';
|
import { FeedService } from './FeedService.js';
|
||||||
import { UrlPreviewService } from './UrlPreviewService.js';
|
import { UrlPreviewService } from './UrlPreviewService.js';
|
||||||
import { ClientLoggerService } from './ClientLoggerService.js';
|
import { ClientLoggerService } from './ClientLoggerService.js';
|
||||||
import type { FastifyInstance, FastifyPluginOptions, FastifyReply, FastifyRequest } from 'fastify';
|
import type { FastifyInstance, FastifyPluginOptions, FastifyReply } from 'fastify';
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
|
|
@ -416,51 +416,20 @@ export class ClientServerService {
|
||||||
// URL preview endpoint
|
// URL preview endpoint
|
||||||
fastify.get<{ Querystring: { url: string; lang: string; } }>('/url', (request, reply) => this.urlPreviewService.handle(request, reply));
|
fastify.get<{ Querystring: { url: string; lang: string; } }>('/url', (request, reply) => this.urlPreviewService.handle(request, reply));
|
||||||
|
|
||||||
const feedHandler = (
|
|
||||||
feedType: 'atom' | 'rss' | 'json',
|
|
||||||
options?: {
|
|
||||||
withReplies?: boolean;
|
|
||||||
withFiles?: boolean;
|
|
||||||
},
|
|
||||||
) => async (
|
|
||||||
request: FastifyRequest<{ Params: { user: string; } }>,
|
|
||||||
reply: FastifyReply,
|
|
||||||
) => {
|
|
||||||
const { username, host } = Acct.parse(request.params.user);
|
|
||||||
const user = await this.usersRepository.findOneBy({
|
|
||||||
usernameLower: username.toLowerCase(),
|
|
||||||
host: host ?? IsNull(),
|
|
||||||
isSuspended: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const feed = user && await this.feedService.packFeed(user, options);
|
|
||||||
|
|
||||||
if (feed) {
|
|
||||||
reply.header('Content-Type', `application/${feedType}+xml; charset=utf-8`);
|
|
||||||
|
|
||||||
if (feedType === 'atom') return feed.atom1();
|
|
||||||
else if (feedType === 'rss') return feed.rss2();
|
|
||||||
else return feed.json1();
|
|
||||||
} else {
|
|
||||||
reply.code(404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Atom
|
// Atom
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.atom', feedHandler('atom'));
|
fastify.get<{ Params: { user: string; } }>('/@:user.atom', this.feedService.handle('atom'));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.atom', feedHandler('atom', { withReplies: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.atom', this.feedService.handle('atom', { withReplies: true }));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.atom', feedHandler('atom', { withFiles: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.atom', this.feedService.handle('atom', { withFiles: true }));
|
||||||
|
|
||||||
// RSS
|
// RSS
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.rss', feedHandler('rss'));
|
fastify.get<{ Params: { user: string; } }>('/@:user.rss', this.feedService.handle('rss'));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.rss', feedHandler('rss', { withReplies: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.rss', this.feedService.handle('rss', { withReplies: true }));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.rss', feedHandler('rss', { withFiles: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.rss', this.feedService.handle('rss', { withFiles: true }));
|
||||||
|
|
||||||
// JSON
|
// JSON
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.json', feedHandler('json'));
|
fastify.get<{ Params: { user: string; } }>('/@:user.json', this.feedService.handle('json'));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.json', feedHandler('json', { withReplies: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_replies.json', this.feedService.handle('json', { withReplies: true }));
|
||||||
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.json', feedHandler('json', { withFiles: true }));
|
fastify.get<{ Params: { user: string; } }>('/@:user.with_files.json', this.feedService.handle('json', { withFiles: true }));
|
||||||
|
|
||||||
//#region SSR (for crawlers)
|
//#region SSR (for crawlers)
|
||||||
// User
|
// User
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,15 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Equal, In, IsNull, Not } from 'typeorm';
|
import { Equal, In, IsNull, Not } from 'typeorm';
|
||||||
import { Feed } from 'feed';
|
import { Feed } from 'feed';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { DriveFilesRepository, NotesRepository, UserProfilesRepository } from '@/models/_.js';
|
import * as Acct from '@/misc/acct.js';
|
||||||
|
import type { DriveFilesRepository, NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/User.js';
|
||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { IdService } from '@/core/IdService.js';
|
import { IdService } from '@/core/IdService.js';
|
||||||
|
import type { FastifyReply, FastifyRequest } from 'fastify';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FeedService {
|
export class FeedService {
|
||||||
|
|
@ -21,6 +23,9 @@ export class FeedService {
|
||||||
@Inject(DI.config)
|
@Inject(DI.config)
|
||||||
private config: Config,
|
private config: Config,
|
||||||
|
|
||||||
|
@Inject(DI.usersRepository)
|
||||||
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
@Inject(DI.userProfilesRepository)
|
@Inject(DI.userProfilesRepository)
|
||||||
private userProfilesRepository: UserProfilesRepository,
|
private userProfilesRepository: UserProfilesRepository,
|
||||||
|
|
||||||
|
|
@ -37,7 +42,7 @@ export class FeedService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async packFeed(
|
private async packFeed(
|
||||||
user: MiUser,
|
user: MiUser,
|
||||||
options?: {
|
options?: {
|
||||||
withReplies?: boolean;
|
withReplies?: boolean;
|
||||||
|
|
@ -72,6 +77,8 @@ export class FeedService {
|
||||||
take: 20,
|
take: 20,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const optionLink = opts.withReplies ? '.with_replies' : opts.withFiles ? '.with_files' : '';
|
||||||
|
|
||||||
const feed = new Feed({
|
const feed = new Feed({
|
||||||
id: author.link,
|
id: author.link,
|
||||||
title: `${author.name} (@${user.username}@${this.config.host})`,
|
title: `${author.name} (@${user.username}@${this.config.host})`,
|
||||||
|
|
@ -81,8 +88,8 @@ export class FeedService {
|
||||||
link: author.link,
|
link: author.link,
|
||||||
image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
image: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
|
||||||
feedLinks: {
|
feedLinks: {
|
||||||
json: `${author.link}.json`,
|
json: `${author.link + optionLink}.json`,
|
||||||
atom: `${author.link}.atom`,
|
atom: `${author.link + optionLink}.atom`,
|
||||||
},
|
},
|
||||||
author,
|
author,
|
||||||
copyright: user.name ?? user.username,
|
copyright: user.name ?? user.username,
|
||||||
|
|
@ -106,4 +113,42 @@ export class FeedService {
|
||||||
|
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public handle(
|
||||||
|
feedType: 'atom' | 'rss' | 'json',
|
||||||
|
options?: {
|
||||||
|
withReplies?: boolean;
|
||||||
|
withFiles?: boolean;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
return async (
|
||||||
|
request: FastifyRequest<{ Params: { user: string; } }>,
|
||||||
|
reply: FastifyReply,
|
||||||
|
) => {
|
||||||
|
const { username, host } = Acct.parse(request.params.user);
|
||||||
|
const user = await this.usersRepository.findOneBy({
|
||||||
|
usernameLower: username.toLowerCase(),
|
||||||
|
host: host ?? IsNull(),
|
||||||
|
isSuspended: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const feed = user && await this.packFeed(user, options);
|
||||||
|
|
||||||
|
if (feed) {
|
||||||
|
const subtype = feedType === 'atom' || feedType === 'rss'
|
||||||
|
? `${feedType}+xml`
|
||||||
|
: feedType;
|
||||||
|
|
||||||
|
reply.header('Content-Type', `application/${subtype}; charset=utf-8`);
|
||||||
|
|
||||||
|
if (feedType === 'atom') return feed.atom1();
|
||||||
|
else if (feedType === 'rss') return feed.rss2();
|
||||||
|
else return feed.json1();
|
||||||
|
} else {
|
||||||
|
reply.code(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue