[mastodon-client] Respect minId query param

This commit is contained in:
Laura Hausmann 2023-09-18 23:12:04 +02:00
parent e90b679864
commit f825dcc811
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 52 additions and 15 deletions

View file

@ -7,7 +7,7 @@ import { Note } from "@/models/entities/note.js";
import { ILocalUser } from "@/models/entities/user.js"; import { ILocalUser } from "@/models/entities/user.js";
import querystring from "node:querystring"; import querystring from "node:querystring";
import { getNote } from "@/server/api/common/getters.js"; import { getNote } from "@/server/api/common/getters.js";
import { SelectQueryBuilder } from "typeorm"; import { ObjectLiteral, SelectQueryBuilder } from "typeorm";
export class NoteHelpers { export class NoteHelpers {
public static async getNoteDescendants(note: Note | string, user: ILocalUser | null, limit: number = 10, depth: number = 2): Promise<Note[]> { public static async getNoteDescendants(note: Note | string, user: ILocalUser | null, limit: number = 10, depth: number = 2): Promise<Note[]> {
@ -46,7 +46,44 @@ export class NoteHelpers {
return notes; return notes;
} }
public static async execQuery(query: SelectQueryBuilder<Note>, limit: number): Promise<Note[]> { public static makePaginationQuery<T extends ObjectLiteral>(
q: SelectQueryBuilder<T>,
sinceId?: string,
maxId?: string,
minId?: string
) {
if (sinceId && minId) throw new Error("Can't user both sinceId and minId params");
if (sinceId && maxId) {
q.andWhere(`${q.alias}.id > :sinceId`, { sinceId: sinceId });
q.andWhere(`${q.alias}.id < :maxId`, { maxId: maxId });
q.orderBy(`${q.alias}.id`, "DESC");
} if (minId && maxId) {
q.andWhere(`${q.alias}.id > :minId`, { minId: minId });
q.andWhere(`${q.alias}.id < :maxId`, { maxId: maxId });
q.orderBy(`${q.alias}.id`, "ASC");
} else if (sinceId) {
q.andWhere(`${q.alias}.id > :sinceId`, { sinceId: sinceId });
q.orderBy(`${q.alias}.id`, "DESC");
} else if (minId) {
q.andWhere(`${q.alias}.id > :minId`, { minId: minId });
q.orderBy(`${q.alias}.id`, "ASC");
} else if (maxId) {
q.andWhere(`${q.alias}.id < :maxId`, { maxId: maxId });
q.orderBy(`${q.alias}.id`, "DESC");
} else {
q.orderBy(`${q.alias}.id`, "DESC");
}
return q;
}
/**
*
* @param query
* @param limit
* @param reverse whether the result needs to be .reverse()'d. Set this to true when the parameter minId is not undefined in the original request.
*/
public static async execQuery(query: SelectQueryBuilder<Note>, limit: number, reverse: boolean): Promise<Note[]> {
// We fetch more than requested because some may be filtered out, and if there's less than // We fetch more than requested because some may be filtered out, and if there's less than
// requested, the pagination stops. // requested, the pagination stops.
const found = []; const found = [];
@ -67,6 +104,6 @@ export class NoteHelpers {
found.length = limit; found.length = limit;
} }
return found; return reverse ? found.reverse() : found;
} }
} }

View file

@ -31,11 +31,11 @@ export class TimelineHelpers {
.select("following.followeeId") .select("following.followeeId")
.where("following.followerId = :followerId", {followerId: user.id}); .where("following.followerId = :followerId", {followerId: user.id});
//FIXME respect minId const query = NoteHelpers.makePaginationQuery(
const query = makePaginationQuery(
Notes.createQueryBuilder("note"), Notes.createQueryBuilder("note"),
sinceId ?? minId, sinceId,
maxId, maxId,
minId
) )
.andWhere( .andWhere(
new Brackets((qb) => { new Brackets((qb) => {
@ -67,7 +67,7 @@ export class TimelineHelpers {
query.andWhere("note.visibility != 'hidden'"); query.andWhere("note.visibility != 'hidden'");
return NoteHelpers.execQuery(query, limit); return NoteHelpers.execQuery(query, limit, minId !== undefined);
} }
public static async getPublicTimeline(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 20, onlyMedia: boolean = false, local: boolean = false, remote: boolean = false): Promise<Note[]> { public static async getPublicTimeline(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 20, onlyMedia: boolean = false, local: boolean = false, remote: boolean = false): Promise<Note[]> {
@ -84,11 +84,11 @@ export class TimelineHelpers {
throw new Error("local and remote are mutually exclusive options"); throw new Error("local and remote are mutually exclusive options");
} }
//FIXME respect minId const query = NoteHelpers.makePaginationQuery(
const query = makePaginationQuery(
Notes.createQueryBuilder("note"), Notes.createQueryBuilder("note"),
sinceId ?? minId, sinceId,
maxId, maxId,
minId
) )
.andWhere("note.visibility = 'public'"); .andWhere("note.visibility = 'public'");
@ -121,6 +121,6 @@ export class TimelineHelpers {
query.andWhere("note.visibility != 'hidden'"); query.andWhere("note.visibility != 'hidden'");
return NoteHelpers.execQuery(query, limit); return NoteHelpers.execQuery(query, limit, minId !== undefined);
} }
} }

View file

@ -31,11 +31,11 @@ export class UserHelpers {
return []; return [];
} }
//FIXME respect minId const query = NoteHelpers.makePaginationQuery(
const query = makePaginationQuery(
Notes.createQueryBuilder("note"), Notes.createQueryBuilder("note"),
sinceId ?? minId, sinceId,
maxId, maxId,
minId
) )
.andWhere("note.userId = :userId", { userId: user.id }); .andWhere("note.userId = :userId", { userId: user.id });
@ -66,7 +66,7 @@ export class UserHelpers {
query.andWhere("note.visibility != 'hidden'"); query.andWhere("note.visibility != 'hidden'");
return NoteHelpers.execQuery(query, limit); return NoteHelpers.execQuery(query, limit, minId !== undefined);
} }
public static async getUserCached(id: string, cache: AccountCache = UserHelpers.getFreshAccountCache()): Promise<User> { public static async getUserCached(id: string, cache: AccountCache = UserHelpers.getFreshAccountCache()): Promise<User> {