summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/web
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/server/web')
-rw-r--r--packages/backend/src/server/web/ClientServerService.ts65
-rw-r--r--packages/backend/src/server/web/views/announcement.pug21
-rw-r--r--packages/backend/src/server/web/views/base.pug6
3 files changed, 85 insertions, 7 deletions
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index c14f6c9123..a2cb50ee9f 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -30,6 +30,7 @@ import type {
EndedPollNotificationQueue,
InboxQueue,
ObjectStorageQueue,
+ RelationshipQueue,
SystemQueue,
UserWebhookDeliverQueue,
SystemWebhookDeliverQueue,
@@ -41,13 +42,26 @@ import { MetaEntityService } from '@/core/entities/MetaEntityService.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, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
+import type {
+ AnnouncementsRepository,
+ ChannelsRepository,
+ ClipsRepository,
+ FlashsRepository,
+ GalleryPostsRepository,
+ MiMeta,
+ NotesRepository,
+ PagesRepository,
+ ReversiGamesRepository,
+ UserProfilesRepository,
+ UsersRepository,
+} from '@/models/_.js';
import type Logger from '@/logger.js';
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
import { bindThis } from '@/decorators.js';
import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
import { RoleService } from '@/core/RoleService.js';
import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
+import { AnnouncementEntityService } from '@/core/entities/AnnouncementEntityService.js';
import { FeedService } from './FeedService.js';
import { UrlPreviewService } from './UrlPreviewService.js';
import { ClientLoggerService } from './ClientLoggerService.js';
@@ -102,6 +116,9 @@ export class ClientServerService {
@Inject(DI.reversiGamesRepository)
private reversiGamesRepository: ReversiGamesRepository,
+ @Inject(DI.announcementsRepository)
+ private announcementsRepository: AnnouncementsRepository,
+
private flashEntityService: FlashEntityService,
private userEntityService: UserEntityService,
private noteEntityService: NoteEntityService,
@@ -111,6 +128,7 @@ export class ClientServerService {
private clipEntityService: ClipEntityService,
private channelEntityService: ChannelEntityService,
private reversiGameEntityService: ReversiGameEntityService,
+ private announcementEntityService: AnnouncementEntityService,
private urlPreviewService: UrlPreviewService,
private feedService: FeedService,
private roleService: RoleService,
@@ -121,6 +139,7 @@ export class ClientServerService {
@Inject('queue:deliver') public deliverQueue: DeliverQueue,
@Inject('queue:inbox') public inboxQueue: InboxQueue,
@Inject('queue:db') public dbQueue: DbQueue,
+ @Inject('queue:relationship') public relationshipQueue: RelationshipQueue,
@Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue,
@Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue,
@Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue,
@@ -251,6 +270,7 @@ export class ClientServerService {
this.deliverQueue,
this.inboxQueue,
this.dbQueue,
+ this.relationshipQueue,
this.objectStorageQueue,
this.userWebhookDeliverQueue,
this.systemWebhookDeliverQueue,
@@ -557,7 +577,7 @@ export class ClientServerService {
}
});
- //#region SSR (for crawlers)
+ //#region SSR
// User
fastify.get<{ Params: { user: string; sub?: string; } }>('/@:user/:sub?', async (request, reply) => {
const { username, host } = Acct.parse(request.params.user);
@@ -582,11 +602,17 @@ export class ClientServerService {
reply.header('X-Robots-Tag', 'noimageai');
reply.header('X-Robots-Tag', 'noai');
}
+
+ const _user = await this.userEntityService.pack(user);
+
return await reply.view('user', {
user, profile, me,
avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
sub: request.params.sub,
...await this.generateCommonPugData(this.meta),
+ clientCtx: htmlSafeJsonStringify({
+ user: _user,
+ }),
});
} else {
// リモートユーザーなので
@@ -616,12 +642,15 @@ export class ClientServerService {
fastify.get<{ Params: { note: string; } }>('/notes/:note', async (request, reply) => {
vary(reply.raw, 'Accept');
- const note = await this.notesRepository.findOneBy({
- id: request.params.note,
- visibility: In(['public', 'home']),
+ const note = await this.notesRepository.findOne({
+ where: {
+ id: request.params.note,
+ visibility: In(['public', 'home']),
+ },
+ relations: ['user'],
});
- if (note) {
+ if (note && !note.user!.requireSigninToViewContents) {
const _note = await this.noteEntityService.pack(note);
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId });
reply.header('Cache-Control', 'public, max-age=15');
@@ -636,6 +665,9 @@ export class ClientServerService {
// TODO: Let locale changeable by instance setting
summary: getNoteSummary(_note),
...await this.generateCommonPugData(this.meta),
+ clientCtx: htmlSafeJsonStringify({
+ note: _note,
+ }),
});
} else {
return await renderBase(reply);
@@ -724,6 +756,9 @@ export class ClientServerService {
profile,
avatarUrl: _clip.user.avatarUrl,
...await this.generateCommonPugData(this.meta),
+ clientCtx: htmlSafeJsonStringify({
+ clip: _clip,
+ }),
});
} else {
return await renderBase(reply);
@@ -788,6 +823,24 @@ export class ClientServerService {
return await renderBase(reply);
}
});
+
+ // 個別お知らせページ
+ fastify.get<{ Params: { announcementId: string; } }>('/announcements/:announcementId', async (request, reply) => {
+ const announcement = await this.announcementsRepository.findOneBy({
+ id: request.params.announcementId,
+ });
+
+ if (announcement) {
+ const _announcement = await this.announcementEntityService.pack(announcement);
+ reply.header('Cache-Control', 'public, max-age=3600');
+ return await reply.view('announcement', {
+ announcement: _announcement,
+ ...await this.generateCommonPugData(this.meta),
+ });
+ } else {
+ return await renderBase(reply);
+ }
+ });
//#endregion
//#region noindex pages
diff --git a/packages/backend/src/server/web/views/announcement.pug b/packages/backend/src/server/web/views/announcement.pug
new file mode 100644
index 0000000000..7a4052e8a4
--- /dev/null
+++ b/packages/backend/src/server/web/views/announcement.pug
@@ -0,0 +1,21 @@
+extends ./base
+
+block vars
+ - const title = announcement.title;
+ - const description = announcement.text.length > 100 ? announcement.text.slice(0, 100) + '…' : announcement.text;
+ - const url = `${config.url}/announcements/${announcement.id}`;
+
+block title
+ = `${title} | ${instanceName}`
+
+block desc
+ meta(name='description' content=description)
+
+block og
+ meta(property='og:type' content='article')
+ meta(property='og:title' content= title)
+ meta(property='og:description' content= description)
+ meta(property='og:url' content= url)
+ if announcement.imageUrl
+ meta(property='og:image' content=announcement.imageUrl)
+ meta(property='twitter:card' content='summary_large_image')
diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug
index 84c4832802..f57dbbbf4e 100644
--- a/packages/backend/src/server/web/views/base.pug
+++ b/packages/backend/src/server/web/views/base.pug
@@ -2,6 +2,7 @@ block vars
block loadClientEntry
- const entry = config.frontendEntry;
+ - const baseUrl = config.url;
doctype html
@@ -36,7 +37,7 @@ html
link(rel='icon' href= icon || '/favicon.ico')
link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png')
link(rel='manifest' href='/manifest.json')
- link(rel='search' type='application/opensearchdescription+xml' title=(title || "Sharkey") href=`${url}/opensearch.xml`)
+ link(rel='search' type='application/opensearchdescription+xml' title=(title || "Sharkey") href=`${baseUrl}/opensearch.xml`)
link(rel='prefetch' href=serverErrorImageUrl)
link(rel='prefetch' href=infoImageUrl)
link(rel='prefetch' href=notFoundImageUrl)
@@ -79,6 +80,9 @@ html
script(type='application/json' id='misskey_meta' data-generated-at=now)
!= metaJson
+ script(type='application/json' id='misskey_clientCtx' data-generated-at=now)
+ != clientCtx
+
script
include ../boot.js