Merge tag '13.11.1' into merge-upstream
This commit is contained in:
@@ -45,7 +45,8 @@ export class CustomEmojiService {
|
||||
fetcher: () => this.emojisRepository.find({ where: { host: IsNull() } }).then(emojis => new Map(emojis.map(emoji => [emoji.name, emoji]))),
|
||||
toRedisConverter: (value) => JSON.stringify(value.values()),
|
||||
fromRedisConverter: (value) => {
|
||||
if (!Array.isArray(value)) return undefined;
|
||||
// 原因不明だが配列以外が入ってくることがあるため
|
||||
if (!Array.isArray(JSON.parse(value))) return undefined;
|
||||
return new Map(JSON.parse(value).map((x: Emoji) => [x.name, x]));
|
||||
}, // TODO: Date型の変換
|
||||
});
|
||||
|
@@ -29,6 +29,7 @@ export class FederatedInstanceService {
|
||||
toRedisConverter: (value) => JSON.stringify(value),
|
||||
fromRedisConverter: (value) => {
|
||||
const parsed = JSON.parse(value);
|
||||
if (parsed == null) return null;
|
||||
return {
|
||||
...parsed,
|
||||
firstRetrievedAt: new Date(parsed.firstRetrievedAt),
|
||||
|
@@ -3,10 +3,11 @@ import { ulid } from 'ulid';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { genAid, parseAid } from '@/misc/id/aid.js';
|
||||
import { genMeid } from '@/misc/id/meid.js';
|
||||
import { genMeidg } from '@/misc/id/meidg.js';
|
||||
import { genMeid, parseMeid } from '@/misc/id/meid.js';
|
||||
import { genMeidg, parseMeidg } from '@/misc/id/meidg.js';
|
||||
import { genObjectId } from '@/misc/id/object-id.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { parseUlid } from '@/misc/id/ulid.js';
|
||||
|
||||
@Injectable()
|
||||
export class IdService {
|
||||
@@ -37,11 +38,10 @@ export class IdService {
|
||||
public parse(id: string): { date: Date; } {
|
||||
switch (this.method) {
|
||||
case 'aid': return parseAid(id);
|
||||
// TODO
|
||||
//case 'meid':
|
||||
//case 'meidg':
|
||||
//case 'ulid':
|
||||
//case 'objectid':
|
||||
case 'objectid':
|
||||
case 'meid': return parseMeid(id);
|
||||
case 'meidg': return parseMeidg(id);
|
||||
case 'ulid': return parseUlid(id);
|
||||
default: throw new Error('unrecognized id generation method');
|
||||
}
|
||||
}
|
||||
|
@@ -186,7 +186,7 @@ class DeliverManager {
|
||||
|
||||
for (const following of followers) {
|
||||
const inbox = following.followerSharedInbox ?? following.followerInbox;
|
||||
inboxes.set(inbox, following.followerSharedInbox === null);
|
||||
inboxes.set(inbox, following.followerSharedInbox != null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,8 @@
|
||||
|
||||
import * as crypto from 'node:crypto';
|
||||
|
||||
export const aidRegExp = /^[0-9a-z]{10}$/;
|
||||
|
||||
const TIME2000 = 946684800000;
|
||||
let counter = crypto.randomBytes(2).readUInt16LE(0);
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
const CHARS = '0123456789abcdef';
|
||||
|
||||
// same as object-id
|
||||
export const meidRegExp = /^[0-9a-f]{24}$/;
|
||||
|
||||
function getTime(time: number) {
|
||||
if (time < 0) time = 0;
|
||||
if (time === 0) {
|
||||
@@ -24,3 +27,9 @@ function getRandom() {
|
||||
export function genMeid(date: Date): string {
|
||||
return getTime(date.getTime()) + getRandom();
|
||||
}
|
||||
|
||||
export function parseMeid(id: string): { date: Date; } {
|
||||
return {
|
||||
date: new Date(parseInt(id.slice(0, 12), 16) - 0x800000000000),
|
||||
};
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ const CHARS = '0123456789abcdef';
|
||||
// 4bit Fixed hex value 'g'
|
||||
// 44bit UNIX Time ms in Hex
|
||||
// 48bit Random value in Hex
|
||||
export const meidgRegExp = /^g[0-9a-f]{23}$/;
|
||||
|
||||
function getTime(time: number) {
|
||||
if (time < 0) time = 0;
|
||||
@@ -26,3 +27,9 @@ function getRandom() {
|
||||
export function genMeidg(date: Date): string {
|
||||
return 'g' + getTime(date.getTime()) + getRandom();
|
||||
}
|
||||
|
||||
export function parseMeidg(id: string): { date: Date; } {
|
||||
return {
|
||||
date: new Date(parseInt(id.slice(1, 12), 16)),
|
||||
};
|
||||
}
|
||||
|
@@ -1,5 +1,8 @@
|
||||
const CHARS = '0123456789abcdef';
|
||||
|
||||
// same as meid
|
||||
export const objectIdRegExp = /^[0-9a-f]{24}$/;
|
||||
|
||||
function getTime(time: number) {
|
||||
if (time < 0) time = 0;
|
||||
if (time === 0) {
|
||||
@@ -24,3 +27,9 @@ function getRandom() {
|
||||
export function genObjectId(date: Date): string {
|
||||
return getTime(date.getTime()) + getRandom();
|
||||
}
|
||||
|
||||
export function parseObjectId(id: string): { date: Date; } {
|
||||
return {
|
||||
date: new Date(parseInt(id.slice(0, 8), 16) * 1000),
|
||||
};
|
||||
}
|
||||
|
14
packages/backend/src/misc/id/ulid.ts
Normal file
14
packages/backend/src/misc/id/ulid.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// Crockford's Base32
|
||||
// https://github.com/ulid/spec#encoding
|
||||
const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
||||
|
||||
export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
|
||||
|
||||
export function parseUlid(id: string): { date: Date; } {
|
||||
const timestamp = id.slice(0, 10);
|
||||
let time = 0;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
time = time * 32 + CHARS.indexOf(timestamp[i]);
|
||||
}
|
||||
return { date: new Date(time) };
|
||||
}
|
@@ -75,13 +75,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
||||
|
||||
let timeline: Note[] = [];
|
||||
|
||||
const noteIdsRes = await this.redisClient.xrevrange(
|
||||
`channelTimeline:${channel.id}`,
|
||||
ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : '+',
|
||||
'-',
|
||||
'COUNT', ps.limit + 1); // untilIdに指定したものも含まれるため+1
|
||||
const limit = ps.limit + (ps.untilId ? 1 : 0); // untilIdに指定したものも含まれるため+1
|
||||
let noteIdsRes: [string, string[]][] = [];
|
||||
|
||||
if (!ps.sinceId && !ps.sinceDate) {
|
||||
noteIdsRes = await this.redisClient.xrevrange(
|
||||
`channelTimeline:${channel.id}`,
|
||||
ps.untilId ? this.idService.parse(ps.untilId).date.getTime() : ps.untilDate ?? '+',
|
||||
'-',
|
||||
'COUNT', limit);
|
||||
}
|
||||
|
||||
if (noteIdsRes.length === 0) {
|
||||
// redis から取得していないとき・取得数が足りないとき
|
||||
if (noteIdsRes.length < limit) {
|
||||
//#region Construct query
|
||||
const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
||||
.andWhere('note.channelId = :channelId', { channelId: channel.id })
|
||||
|
44
packages/backend/test/unit/misc/id.ts
Normal file
44
packages/backend/test/unit/misc/id.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { aidRegExp, genAid, parseAid } from '@/misc/id/aid.js';
|
||||
import { genMeid, meidRegExp, parseMeid } from '@/misc/id/meid.js';
|
||||
import { genMeidg, meidgRegExp, parseMeidg } from '@/misc/id/meidg.js';
|
||||
import { genObjectId, objectIdRegExp, parseObjectId } from '@/misc/id/object-id.js';
|
||||
import { ulidRegExp, parseUlid } from '@/misc/id/ulid.js';
|
||||
import { ulid } from 'ulid';
|
||||
import { describe, test, expect } from '@jest/globals';
|
||||
|
||||
describe('misc:id', () => {
|
||||
test('aid', () => {
|
||||
const date = new Date();
|
||||
const gotAid = genAid(date);
|
||||
expect(gotAid).toMatch(aidRegExp);
|
||||
expect(parseAid(gotAid).date.getTime()).toBe(date.getTime());
|
||||
});
|
||||
|
||||
test('meid', () => {
|
||||
const date = new Date();
|
||||
const gotMeid = genMeid(date);
|
||||
expect(gotMeid).toMatch(meidRegExp);
|
||||
expect(parseMeid(gotMeid).date.getTime()).toBe(date.getTime());
|
||||
});
|
||||
|
||||
test('meidg', () => {
|
||||
const date = new Date();
|
||||
const gotMeidg = genMeidg(date);
|
||||
expect(gotMeidg).toMatch(meidgRegExp);
|
||||
expect(parseMeidg(gotMeidg).date.getTime()).toBe(date.getTime());
|
||||
});
|
||||
|
||||
test('objectid', () => {
|
||||
const date = new Date();
|
||||
const gotObjectId = genObjectId(date);
|
||||
expect(gotObjectId).toMatch(objectIdRegExp);
|
||||
expect(Math.floor(parseObjectId(gotObjectId).date.getTime() / 1000)).toBe(Math.floor(date.getTime() / 1000));
|
||||
});
|
||||
|
||||
test('ulid', () => {
|
||||
const date = new Date();
|
||||
const gotUlid = ulid(date.getTime());
|
||||
expect(gotUlid).toMatch(ulidRegExp);
|
||||
expect(parseUlid(gotUlid).date.getTime()).toBe(date.getTime());
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user