mirror of
https://iceshrimp.dev/crimekillz/trashposs
synced 2024-11-22 08:53:48 +01:00
[mastodon-client] Unread notifications
This commit is contained in:
parent
b8b6206b4e
commit
557dd37fe8
@ -1,11 +1,13 @@
|
|||||||
import Router from "@koa/router";
|
import Router from "@koa/router";
|
||||||
import { convertId, IdType } from "../../index.js";
|
import { convertId, IdType } from "../../index.js";
|
||||||
import { convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "./timeline.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 authenticate from "@/server/api/authenticate.js";
|
||||||
import { UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
import { UserHelpers } from "@/server/api/mastodon/helpers/user.js";
|
||||||
import { NotificationHelpers } from "@/server/api/mastodon/helpers/notification.js";
|
import { NotificationHelpers } from "@/server/api/mastodon/helpers/notification.js";
|
||||||
import { NotificationConverter } from "@/server/api/mastodon/converters/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 {
|
export function setupEndpointsNotifications(router: Router): void {
|
||||||
router.get("/v1/notifications", async (ctx) => {
|
router.get("/v1/notifications", async (ctx) => {
|
||||||
@ -99,4 +101,18 @@ export function setupEndpointsNotifications(router: Router): void {
|
|||||||
ctx.body = e.response.data;
|
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) => {
|
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 {
|
try {
|
||||||
const auth = await authenticate(ctx.headers.authorization, null);
|
const auth = await authenticate(ctx.headers.authorization, null);
|
||||||
const user = auth[0] ?? undefined;
|
const user = auth[0] ?? undefined;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ILocalUser } from "@/models/entities/user.js";
|
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 { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js";
|
||||||
import { Notification } from "@/models/entities/notification.js";
|
import { Notification } from "@/models/entities/notification.js";
|
||||||
|
|
||||||
@ -46,6 +46,24 @@ export class NotificationHelpers {
|
|||||||
await Notifications.update({notifieeId: user.id}, {isRead: true});
|
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[]) {
|
private static decodeTypes(types: string[]) {
|
||||||
const result: string[] = [];
|
const result: string[] = [];
|
||||||
if (types.includes('follow')) result.push('follow');
|
if (types.includes('follow')) result.push('follow');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Note } from "@/models/entities/note.js";
|
import { Note } from "@/models/entities/note.js";
|
||||||
import { ILocalUser, User } from "@/models/entities/user.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 { Brackets } from "typeorm";
|
||||||
import { generateChannelQuery } from "@/server/api/common/generate-channel-query.js";
|
import { generateChannelQuery } from "@/server/api/common/generate-channel-query.js";
|
||||||
import { generateRepliesQuery } from "@/server/api/common/generate-replies-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 userIds = unique([c.userId].concat(c.visibleUserIds).filter(p => p != user.id));
|
||||||
const users = userIds.map(id => UserHelpers.getUserCached(id, cache).catch(_ => null));
|
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 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 {
|
return {
|
||||||
id: c.threadId ?? c.id,
|
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
|
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),
|
last_status: NoteConverter.encode(c, user, cache),
|
||||||
unread: false //FIXME implement this (also the /v1/conversations/:id/read endpoint)
|
unread: unread
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const res = {
|
const res = {
|
||||||
|
Loading…
Reference in New Issue
Block a user