mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-25 11:27:31 -07:00
[mastodon-client] Unread notifications
This commit is contained in:
parent
b8b6206b4e
commit
557dd37fe8
4 changed files with 47 additions and 7 deletions
|
@ -1,11 +1,13 @@
|
|||
import Router from "@koa/router";
|
||||
import { convertId, IdType } from "../../index.js";
|
||||
import { convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "./timeline.js";
|
||||
import { convertNotification } from "../converters.js";
|
||||
import { convertConversation, convertNotification } from "../converters.js";
|
||||
import authenticate from "@/server/api/authenticate.js";
|
||||
import { UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||
import { NotificationHelpers } from "@/server/api/mastodon/helpers/notification.js";
|
||||
import { NotificationConverter } from "@/server/api/mastodon/converters/notification.js";
|
||||
import { TimelineHelpers } from "@/server/api/mastodon/helpers/timeline.js";
|
||||
import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||
|
||||
export function setupEndpointsNotifications(router: Router): void {
|
||||
router.get("/v1/notifications", async (ctx) => {
|
||||
|
@ -99,4 +101,18 @@ export function setupEndpointsNotifications(router: Router): void {
|
|||
ctx.body = e.response.data;
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/v1/conversations/:id/read", async (ctx, reply) => {
|
||||
const auth = await authenticate(ctx.headers.authorization, null);
|
||||
const user = auth[0] ?? undefined;
|
||||
|
||||
if (!user) {
|
||||
ctx.status = 401;
|
||||
return;
|
||||
}
|
||||
|
||||
const id = convertId(ctx.params.id, IdType.IceshrimpId);
|
||||
await NotificationHelpers.markConversationAsRead(id, user);
|
||||
ctx.body = {};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -177,9 +177,6 @@ export function setupEndpointsTimeline(router: Router): void {
|
|||
},
|
||||
);
|
||||
router.get("/v1/conversations", async (ctx, reply) => {
|
||||
const BASE_URL = `${ctx.protocol}://${ctx.hostname}`;
|
||||
const accessTokens = ctx.headers.authorization;
|
||||
const client = getClient(BASE_URL, accessTokens);
|
||||
try {
|
||||
const auth = await authenticate(ctx.headers.authorization, null);
|
||||
const user = auth[0] ?? undefined;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ILocalUser } from "@/models/entities/user.js";
|
||||
import { Notifications } from "@/models/index.js";
|
||||
import { Notes, Notifications } from "@/models/index.js";
|
||||
import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||
import { Notification } from "@/models/entities/notification.js";
|
||||
|
||||
|
@ -46,6 +46,24 @@ export class NotificationHelpers {
|
|||
await Notifications.update({notifieeId: user.id}, {isRead: true});
|
||||
}
|
||||
|
||||
public static async markConversationAsRead(id: string, user: ILocalUser): Promise<void> {
|
||||
const notesQuery = Notes.createQueryBuilder("note")
|
||||
.select("note.id")
|
||||
.andWhere("COALESCE(note.threadId, note.id) = :conversationId");
|
||||
|
||||
await Notifications.createQueryBuilder("notification")
|
||||
.where(`notification."noteId" IN (${notesQuery.getQuery()})`)
|
||||
.andWhere(`notification."notifieeId" = :userId`)
|
||||
.andWhere(`notification."isRead" = FALSE`)
|
||||
.andWhere("notification.type IN (:...types)")
|
||||
.setParameter("userId", user.id)
|
||||
.setParameter("conversationId", id)
|
||||
.setParameter("types", ['reply', 'mention'])
|
||||
.update()
|
||||
.set({isRead: true})
|
||||
.execute();
|
||||
}
|
||||
|
||||
private static decodeTypes(types: string[]) {
|
||||
const result: string[] = [];
|
||||
if (types.includes('follow')) result.push('follow');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Note } from "@/models/entities/note.js";
|
||||
import { ILocalUser, User } from "@/models/entities/user.js";
|
||||
import { Followings, Notes, UserListJoinings } from "@/models/index.js";
|
||||
import { Followings, Notes, Notifications, UserListJoinings } from "@/models/index.js";
|
||||
import { Brackets } from "typeorm";
|
||||
import { generateChannelQuery } from "@/server/api/common/generate-channel-query.js";
|
||||
import { generateRepliesQuery } from "@/server/api/common/generate-replies-query.js";
|
||||
|
@ -187,12 +187,21 @@ export class TimelineHelpers {
|
|||
const userIds = unique([c.userId].concat(c.visibleUserIds).filter(p => p != user.id));
|
||||
const users = userIds.map(id => UserHelpers.getUserCached(id, cache).catch(_ => null));
|
||||
const accounts = Promise.all(users).then(u => UserConverter.encodeMany(u.filter(u => u) as User[], cache));
|
||||
const unread = Notifications.createQueryBuilder('notification')
|
||||
.where("notification.noteId = :noteId")
|
||||
.andWhere("notification.notifieeId = :userId")
|
||||
.andWhere("notification.isRead = FALSE")
|
||||
.andWhere("notification.type IN (:...types)")
|
||||
.setParameter("noteId", c.id)
|
||||
.setParameter("userId", user.id)
|
||||
.setParameter("types", ['reply', 'mention'])
|
||||
.getExists();
|
||||
|
||||
return {
|
||||
id: c.threadId ?? c.id,
|
||||
accounts: accounts.then(u => u.length > 0 ? u : UserConverter.encodeMany([user], cache)), // failsafe to prevent apps from crashing case when all participant users have been deleted
|
||||
last_status: NoteConverter.encode(c, user, cache),
|
||||
unread: false //FIXME implement this (also the /v1/conversations/:id/read endpoint)
|
||||
unread: unread
|
||||
}
|
||||
});
|
||||
const res = {
|
||||
|
|
Loading…
Reference in a new issue