factor out tuple logic into from-tuple.ts

This commit is contained in:
Hazelnoot 2024-10-15 14:03:57 -04:00
parent 4e592fb1c9
commit 86a693b182
6 changed files with 33 additions and 12 deletions

View file

@ -59,7 +59,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
} }
@bindThis @bindThis
public parseUri(value: string | IObject): UriParseResult { public parseUri(value: string | IObject | [string | IObject]): UriParseResult {
const separator = '/'; const separator = '/';
const uri = new URL(getApId(value)); const uri = new URL(getApId(value));
@ -78,7 +78,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
* AP Note => Misskey Note in DB * AP Note => Misskey Note in DB
*/ */
@bindThis @bindThis
public async getNoteFromApId(value: string | IObject): Promise<MiNote | null> { public async getNoteFromApId(value: string | IObject | [string | IObject]): Promise<MiNote | null> {
const parsed = this.parseUri(value); const parsed = this.parseUri(value);
if (parsed.local) { if (parsed.local) {
@ -99,9 +99,6 @@ export class ApDbResolverService implements OnApplicationShutdown {
*/ */
@bindThis @bindThis
public async getUserFromApId(value: string | IObject | [string | IObject]): Promise<MiLocalUser | MiRemoteUser | null> { public async getUserFromApId(value: string | IObject | [string | IObject]): Promise<MiLocalUser | MiRemoteUser | null> {
// eslint-disable-next-line no-param-reassign
if (Array.isArray(value)) value = value[0];
const parsed = this.parseUri(value); const parsed = this.parseUri(value);
if (parsed.local) { if (parsed.local) {

View file

@ -41,6 +41,7 @@ import { ApPersonService } from './models/ApPersonService.js';
import { ApQuestionService } from './models/ApQuestionService.js'; import { ApQuestionService } from './models/ApQuestionService.js';
import type { Resolver } from './ApResolverService.js'; import type { Resolver } from './ApResolverService.js';
import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IReject, IRemove, IUndo, IUpdate, IMove, IPost } from './type.js'; import type { IAccept, IAdd, IAnnounce, IBlock, ICreate, IDelete, IFlag, IFollow, ILike, IObject, IReject, IRemove, IUndo, IUpdate, IMove, IPost } from './type.js';
import { fromTuple } from '@/misc/from-tuple.js';
@Injectable() @Injectable()
export class ApInboxService { export class ApInboxService {
@ -253,7 +254,7 @@ export class ApInboxService {
} }
if (activity.target === actor.featured) { if (activity.target === actor.featured) {
const object = Array.isArray(activity.object) ? activity.object[0] : activity.object; const object = fromTuple(activity.object);
const note = await this.apNoteService.resolveNote(object); const note = await this.apNoteService.resolveNote(object);
if (note == null) return 'note not found'; if (note == null) return 'note not found';
await this.notePiningService.addPinned(actor, note.id); await this.notePiningService.addPinned(actor, note.id);
@ -271,7 +272,7 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver(); const resolver = this.apResolverService.createResolver();
const activityObject = Array.isArray(activity.object) ? activity.object[0] : activity.object; const activityObject = fromTuple(activity.object);
if (!activityObject) return 'skip: activity has no object property'; if (!activityObject) return 'skip: activity has no object property';
const targetUri = getApId(activityObject); const targetUri = getApId(activityObject);
if (targetUri.startsWith('bear:')) return 'skip: bearcaps url not supported.'; if (targetUri.startsWith('bear:')) return 'skip: bearcaps url not supported.';
@ -372,7 +373,7 @@ export class ApInboxService {
this.logger.info(`Create: ${uri}`); this.logger.info(`Create: ${uri}`);
const activityObject = Array.isArray(activity.object) ? activity.object[0] : activity.object; const activityObject = fromTuple(activity.object);
if (!activityObject) return 'skip: activity has no object property'; if (!activityObject) return 'skip: activity has no object property';
const targetUri = getApId(activityObject); const targetUri = getApId(activityObject);
if (targetUri.startsWith('bear:')) return 'skip: bearcaps url not supported.'; if (targetUri.startsWith('bear:')) return 'skip: bearcaps url not supported.';
@ -451,7 +452,7 @@ export class ApInboxService {
// 削除対象objectのtype // 削除対象objectのtype
let formerType: string | undefined; let formerType: string | undefined;
const activityObject = Array.isArray(activity.object) ? activity.object[0] : activity.object; const activityObject = fromTuple(activity.object);
if (typeof activityObject === 'string') { if (typeof activityObject === 'string') {
// typeが不明だけど、どうせ消えてるのでremote resolveしない // typeが不明だけど、どうせ消えてるのでremote resolveしない
formerType = undefined; formerType = undefined;
@ -619,7 +620,7 @@ export class ApInboxService {
} }
if (activity.target === actor.featured) { if (activity.target === actor.featured) {
const activityObject = Array.isArray(activity.object) ? activity.object[0] : activity.object; const activityObject = fromTuple(activity.object);
const note = await this.apNoteService.resolveNote(activityObject); const note = await this.apNoteService.resolveNote(activityObject);
if (note == null) return 'note not found'; if (note == null) return 'note not found';
await this.notePiningService.removePinned(actor, note.id); await this.notePiningService.removePinned(actor, note.id);

View file

@ -21,6 +21,7 @@ import { ApDbResolverService } from './ApDbResolverService.js';
import { ApRendererService } from './ApRendererService.js'; import { ApRendererService } from './ApRendererService.js';
import { ApRequestService } from './ApRequestService.js'; import { ApRequestService } from './ApRequestService.js';
import type { IObject, ICollection, IOrderedCollection } from './type.js'; import type { IObject, ICollection, IOrderedCollection } from './type.js';
import { fromTuple } from '@/misc/from-tuple.js';
export class Resolver { export class Resolver {
private history: Set<string>; private history: Set<string>;
@ -69,7 +70,7 @@ export class Resolver {
@bindThis @bindThis
public async resolve(value: string | IObject | [string | IObject]): Promise<IObject> { public async resolve(value: string | IObject | [string | IObject]): Promise<IObject> {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
if (Array.isArray(value)) value = value[0]; value = fromTuple(value);
if (typeof value !== 'string') { if (typeof value !== 'string') {
return value; return value;

View file

@ -3,6 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { fromTuple } from '@/misc/from-tuple.js';
export type Obj = { [x: string]: any }; export type Obj = { [x: string]: any };
export type ApObject = IObject | string | (IObject | string)[]; export type ApObject = IObject | string | (IObject | string)[];
@ -54,7 +56,7 @@ export function getOneApId(value: ApObject): string {
*/ */
export function getApId(value: string | IObject | [string | IObject]): string { export function getApId(value: string | IObject | [string | IObject]): string {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
if (Array.isArray(value)) value = value[0]; value = fromTuple(value);
if (typeof value === 'string') return value; if (typeof value === 'string') return value;
if (typeof value.id === 'string') return value.id; if (typeof value.id === 'string') return value.id;

View file

@ -0,0 +1,7 @@
export function fromTuple<T>(value: T | [T]): T {
if (Array.isArray(value)) {
return value[0];
}
return value;
}

View file

@ -0,0 +1,13 @@
import { fromTuple } from '@/misc/from-tuple.js';
describe(fromTuple, () => {
it('should return value when value is not an array', () => {
const value = fromTuple('abc');
expect(value).toBe('abc');
});
it('should return first element when value is an array', () => {
const value = fromTuple(['abc']);
expect(value).toBe('abc');
});
});