mirror of
https://iceshrimp.dev/crimekillz/iceshrimp-161sh.git
synced 2024-11-22 04:03:49 +01:00
[mastodon-client] GET /v1/announcements, POST /v1/announcements/:id/dismiss
This commit is contained in:
parent
059a20f4b1
commit
44b72a2ecc
@ -0,0 +1,27 @@
|
||||
import { Announcement } from "@/models/entities/announcement.js";
|
||||
import { ILocalUser } from "@/models/entities/user.js";
|
||||
import { awaitAll } from "@/prelude/await-all";
|
||||
import { AnnouncementReads } from "@/models/index.js";
|
||||
import { MfmHelpers } from "@/server/api/mastodon/helpers/mfm.js";
|
||||
import mfm from "mfm-js";
|
||||
|
||||
export class AnnouncementConverter {
|
||||
public static encode(announcement: Announcement, isRead: boolean): MastodonEntity.Announcement {
|
||||
return {
|
||||
id: announcement.id,
|
||||
content: `<h1>${MfmHelpers.toHtml(mfm.parse(announcement.title), []) ?? 'Announcement'}</h1>${MfmHelpers.toHtml(mfm.parse(announcement.text), []) ?? ''}`,
|
||||
starts_at: null,
|
||||
ends_at: null,
|
||||
published: true,
|
||||
all_day: false,
|
||||
published_at: announcement.createdAt.toISOString(),
|
||||
updated_at: announcement.updatedAt?.toISOString() ?? announcement.createdAt.toISOString(),
|
||||
read: isRead,
|
||||
mentions: [], //FIXME
|
||||
statuses: [],
|
||||
tags: [],
|
||||
emojis: [], //FIXME
|
||||
reactions: [],
|
||||
};
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
import Router from "@koa/router";
|
||||
import { getClient } from "@/server/api/mastodon/index.js";
|
||||
import { convertId, IdType } from "@/misc/convert-id.js";
|
||||
import { convertAnnouncementId } from "@/server/api/mastodon/converters.js";
|
||||
import { MiscHelpers } from "@/server/api/mastodon/helpers/misc.js";
|
||||
import authenticate from "@/server/api/authenticate.js";
|
||||
import { argsToBools } from "@/server/api/mastodon/endpoints/timeline.js";
|
||||
import { Announcements } from "@/models/index.js";
|
||||
import { convertAnnouncementId } from "@/server/api/mastodon/converters.js";
|
||||
import { convertId, IdType } from "@/misc/convert-id.js";
|
||||
|
||||
export function setupEndpointsMisc(router: Router): void {
|
||||
router.get("/v1/custom_emojis", async (ctx) => {
|
||||
@ -30,36 +33,49 @@ export function setupEndpointsMisc(router: Router): void {
|
||||
});
|
||||
|
||||
router.get("/v1/announcements", async (ctx) => {
|
||||
const BASE_URL = `${ctx.request.protocol}://${ctx.request.hostname}`;
|
||||
const accessTokens = ctx.request.headers.authorization;
|
||||
const client = getClient(BASE_URL, accessTokens);
|
||||
try {
|
||||
const data = await client.getInstanceAnnouncements();
|
||||
ctx.body = data.data.map((announcement) =>
|
||||
convertAnnouncementId(announcement),
|
||||
);
|
||||
const auth = await authenticate(ctx.headers.authorization, null);
|
||||
const user = auth[0] ?? null;
|
||||
|
||||
if (!user) {
|
||||
ctx.status = 401;
|
||||
return;
|
||||
}
|
||||
|
||||
const args = argsToBools(ctx.query, ['with_dismissed']);
|
||||
ctx.body = await MiscHelpers.getAnnouncements(user, args['with_dismissed'])
|
||||
.then(p => p.map(x => convertAnnouncementId(x)));
|
||||
} catch (e: any) {
|
||||
console.error(e);
|
||||
ctx.status = 401;
|
||||
ctx.body = e.response.data;
|
||||
ctx.status = 500;
|
||||
ctx.body = { error: e.message };
|
||||
}
|
||||
});
|
||||
|
||||
router.post<{ Params: { id: string } }>(
|
||||
"/v1/announcements/:id/dismiss",
|
||||
async (ctx) => {
|
||||
const BASE_URL = `${ctx.request.protocol}://${ctx.request.hostname}`;
|
||||
const accessTokens = ctx.request.headers.authorization;
|
||||
const client = getClient(BASE_URL, accessTokens);
|
||||
try {
|
||||
const data = await client.dismissInstanceAnnouncement(
|
||||
convertId(ctx.params.id, IdType.IceshrimpId),
|
||||
);
|
||||
ctx.body = data.data;
|
||||
const auth = await authenticate(ctx.headers.authorization, null);
|
||||
const user = auth[0] ?? null;
|
||||
|
||||
if (!user) {
|
||||
ctx.status = 401;
|
||||
return;
|
||||
}
|
||||
|
||||
const id = convertId(ctx.params.id, IdType.IceshrimpId);
|
||||
const announcement = await Announcements.findOneBy({id: id});
|
||||
|
||||
if (!announcement) {
|
||||
ctx.status = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
await MiscHelpers.dismissAnnouncement(announcement, user);
|
||||
ctx.body = {};
|
||||
} catch (e: any) {
|
||||
console.error(e);
|
||||
ctx.status = 401;
|
||||
ctx.body = e.response.data;
|
||||
ctx.status = 500;
|
||||
ctx.body = { error: e.message };
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -1,11 +1,15 @@
|
||||
import config from "@/config/index.js";
|
||||
import { FILE_TYPE_BROWSERSAFE, MAX_NOTE_TEXT_LENGTH } from "@/const.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { Instances, Notes, Users } from "@/models/index.js";
|
||||
import { AnnouncementReads, Announcements, Instances, Notes, Users } from "@/models/index.js";
|
||||
import { IsNull } from "typeorm";
|
||||
import { awaitAll } from "@/prelude/await-all.js";
|
||||
import { UserConverter } from "@/server/api/mastodon/converters/user.js";
|
||||
import { convertAccountId } from "@/server/api/mastodon/converters.js";
|
||||
import { Announcement } from "@/models/entities/announcement.js";
|
||||
import { ILocalUser } from "@/models/entities/user.js";
|
||||
import { AnnouncementConverter } from "@/server/api/mastodon/converters/announcement.js";
|
||||
import { genId } from "@/misc/gen-id.js";
|
||||
|
||||
export class MiscHelpers {
|
||||
public static async getInstance(): Promise<MastodonEntity.Instance> {
|
||||
@ -81,4 +85,42 @@ export class MiscHelpers {
|
||||
|
||||
return awaitAll(res);
|
||||
}
|
||||
|
||||
public static async getAnnouncements(user: ILocalUser, includeRead: boolean = false): Promise<MastodonEntity.Announcement[]> {
|
||||
if (includeRead) {
|
||||
const [announcements, reads] = await Promise.all([
|
||||
Announcements.createQueryBuilder("announcement")
|
||||
.orderBy({"announcement.id": "DESC"})
|
||||
.getMany(),
|
||||
AnnouncementReads.findBy({userId: user.id})
|
||||
.then(p => p.map(x => x.announcementId))
|
||||
]);
|
||||
|
||||
return announcements.map(p => AnnouncementConverter.encode(p, reads.includes(p.id)));
|
||||
}
|
||||
|
||||
const sq = AnnouncementReads.createQueryBuilder("reads")
|
||||
.select("reads.announcementId")
|
||||
.where("reads.userId = :userId");
|
||||
|
||||
const query = Announcements.createQueryBuilder("announcement")
|
||||
.where(`announcement.id NOT IN (${sq.getQuery()})`)
|
||||
.orderBy({"announcement.id": "DESC"})
|
||||
.setParameter("userId", user.id);
|
||||
|
||||
return query.getMany()
|
||||
.then(p => p.map(x => AnnouncementConverter.encode(x, false)));
|
||||
}
|
||||
|
||||
public static async dismissAnnouncement(announcement: Announcement, user: ILocalUser): Promise<void> {
|
||||
const exists = await AnnouncementReads.exist({where: {userId: user.id, announcementId: announcement.id}});
|
||||
if (!exists) {
|
||||
await AnnouncementReads.insert({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
userId: user.id,
|
||||
announcementId: announcement.id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user