diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index 7ef178403b..263b15cc5e 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -26,9 +26,10 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; -import type { ChannelsRepository, ClipsRepository, EmojisRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { ChannelsRepository, ClipsRepository, EmojisRepository, FlashsRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import { deepClone } from '@/misc/clone.js'; import { bindThis } from '@/decorators.js'; +import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import manifest from './manifest.json' assert { type: 'json' }; import { FeedService } from './FeedService.js'; import { UrlPreviewService } from './UrlPreviewService.js'; @@ -73,6 +74,10 @@ export class ClientServerService { @Inject(DI.emojisRepository) private emojisRepository: EmojisRepository, + @Inject(DI.flashsRepository) + private flashsRepository: FlashsRepository, + + private flashEntityService: FlashEntityService, private userEntityService: UserEntityService, private noteEntityService: NoteEntityService, private pageEntityService: PageEntityService, @@ -545,6 +550,30 @@ export class ClientServerService { } }); + // Flash + fastify.get<{ Params: { id: string; } }>('/play/:id', async (request, reply) => { + const flash = await this.flashsRepository.findOneBy({ + id: request.params.id, + }); + + if (flash) { + const _flash = await this.flashEntityService.pack(flash); + const profile = await this.userProfilesRepository.findOneByOrFail({ userId: flash.userId }); + const meta = await this.metaService.fetch(); + reply.header('Cache-Control', 'public, max-age=15'); + return await reply.view('flash', { + flash: _flash, + profile, + avatarUrl: await this.userEntityService.getAvatarUrl(await this.usersRepository.findOneByOrFail({ id: flash.userId })), + instanceName: meta.name ?? 'Misskey', + icon: meta.iconUrl, + themeColor: meta.themeColor, + }); + } else { + return await renderBase(reply); + } + }); + // Clip // TODO: 非publicなclipのハンドリング fastify.get<{ Params: { clip: string; } }>('/clips/:clip', async (request, reply) => { diff --git a/packages/backend/src/server/web/views/flash.pug b/packages/backend/src/server/web/views/flash.pug new file mode 100644 index 0000000000..dc529b21df --- /dev/null +++ b/packages/backend/src/server/web/views/flash.pug @@ -0,0 +1,31 @@ +extends ./base + +block vars + - const user = flash.user; + - const title = flash.title; + - const url = `${config.url}/play/${flash.id}`; + +block title + = `${title} | ${instanceName}` + +block desc + meta(name='description' content= flash.summary) + +block og + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= flash.summary) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) + +block meta + if profile.noCrawle + meta(name='robots' content='noindex') + + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:page-id' content=page.id) + + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`)