Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
penginn-net committed Dec 27, 2024
1 parent 9f83972 commit 8f9229c
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 5 deletions.
17 changes: 17 additions & 0 deletions packages/backend/src/core/CustomEmojiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { query } from '@/misc/prelude/url.js';
import type { Serialized } from '@/types.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { DriveService } from '@/core/DriveService.js';
import { emojiCopyPermissions } from '@/types.js';

const parseEmojiStrRegexp = /^([-\w]+)(?:@([\w.-]+))?$/;

Expand Down Expand Up @@ -69,6 +70,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][];
copyPermission: 'allow' | 'deny' | 'conditional' | null,
usageInfo: string | null,
author: string | null,
description: string | null,
}, moderator?: MiUser): Promise<MiEmoji> {
// システムユーザーとして再アップロード
if (!data.driveFile.user?.isRoot) {
Expand All @@ -93,6 +98,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
isSensitive: data.isSensitive,
localOnly: data.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction,
copyPermission: data.copyPermission,
usageInfo: data.usageInfo,
author: data.author,
description: data.description,
});

if (data.host == null) {
Expand Down Expand Up @@ -127,6 +136,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
isSensitive?: boolean;
localOnly?: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][];
copyPermission?: 'allow' | 'deny' | 'conditional' | null,
usageInfo?: string | null,
author?: string | null,
description?: string | null,
}, moderator?: MiUser): Promise<
null
| 'NO_SUCH_EMOJI'
Expand Down Expand Up @@ -157,6 +170,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined,
type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined,
copyPermission: data.copyPermission,
usageInfo: data.usageInfo,
author: data.author,
description: data.description,
});

this.localEmojisCache.refresh();
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/core/activitypub/ApRendererService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@ export class ApRendererService {
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl,
},
...(emoji.copyPermission === null ? { } : { copyPermission: emoji.copyPermission }),
...(emoji.license === null ? { } : { license: emoji.license }),
keywords: emoji.aliases,
...(emoji.usageInfo === null ? { } : { usageInfo: emoji.usageInfo }),
...(emoji.author === null ? { } : { author: emoji.author }),
...(emoji.description === null ? { } : { description: emoji.description }),
};
}

Expand Down
19 changes: 15 additions & 4 deletions packages/backend/src/core/activitypub/models/ApNoteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,14 +492,14 @@ export class ApNoteService {
// eslint-disable-next-line no-param-reassign
host = this.utilityService.toPuny(host);

const eomjiTags = toArray(tags).filter(isEmoji);
const emojiTags = toArray(tags).filter(isEmoji);

const existingEmojis = await this.emojisRepository.findBy({
host,
name: In(eomjiTags.map(tag => tag.name.replaceAll(':', ''))),
name: In(emojiTags.map(tag => tag.name.replaceAll(':', ''))),
});

return await Promise.all(eomjiTags.map(async tag => {
return await Promise.all(emojiTags.map(async tag => {
const name = tag.name.replaceAll(':', '');
tag.icon = toSingle(tag.icon);

Expand All @@ -519,6 +519,12 @@ export class ApNoteService {
originalUrl: tag.icon.url,
publicUrl: tag.icon.url,
updatedAt: new Date(),
aliases: tag.keywords,
copyPermission: tag.copyPermission,
author: tag.author,
license: tag.license,
description: tag.description,
usageInfo: tag.usageInfo,
});

const emoji = await this.emojisRepository.findOneBy({ host, name });
Expand All @@ -539,7 +545,12 @@ export class ApNoteService {
originalUrl: tag.icon.url,
publicUrl: tag.icon.url,
updatedAt: new Date(),
aliases: [],
aliases: tag.keywords,
copyPermission: tag.copyPermission,
author: tag.author,
license: tag.license,
description: tag.description,
usageInfo: tag.usageInfo,
});
}));
}
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/core/activitypub/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ export interface IApEmoji extends IObject {
type: 'Emoji';
name: string;
updated: string;
copyPermission?: 'allow' | 'deny' | 'conditional';
license?: string;
keywords?: string[];
usageInfo?: string;
author?: string;
description?: string;
}

export const isEmoji = (object: IObject): object is IApEmoji =>
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/src/core/entities/EmojiEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export class EmojiEntityService {
isSensitive: emoji.isSensitive,
localOnly: emoji.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
copyPermission: emoji.copyPermission,
usageInfo: emoji.usageInfo,
author: emoji.author,
description: emoji.description,
};
}

Expand Down
26 changes: 26 additions & 0 deletions packages/backend/src/models/Emoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { PrimaryColumn, Entity, Index, Column } from 'typeorm';
import { id } from './util/id.js';
import {emojiCopyPermissions, searchableTypes} from "@/types.js";

Check failure on line 8 in packages/backend/src/models/Emoji.ts

View workflow job for this annotation

GitHub Actions / lint (backend)

A space is required after '{'

Check failure on line 8 in packages/backend/src/models/Emoji.ts

View workflow job for this annotation

GitHub Actions / lint (backend)

A space is required before '}'

@Entity('emoji')
@Index(['name', 'host'], { unique: true })
Expand Down Expand Up @@ -76,6 +77,31 @@ export class MiEmoji {
})
public isSensitive: boolean;

@Column('varchar', {
length: 512,
default: 'null',
})
public usageInfo: string | null;

@Column('varchar', {
length: 512,
default: 'null',
})
public description: string | null;

@Column('varchar', {
length: 128,
default: 'null',
})
public author: string | null;

@Column('enum',
{
enum: emojiCopyPermissions,
nullable: true,
})
public copyPermission: typeof emojiCopyPermissions[number] | null;

// TODO: 定期ジョブで存在しなくなったロールIDを除去するようにする
@Column('varchar', {
array: true, length: 128, default: '{}',
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/src/models/json-schema/emoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { emojiCopyPermissions } from '@/types.js';

export const packedEmojiSimpleSchema = {
type: 'object',
properties: {
Expand Down Expand Up @@ -102,5 +104,9 @@ export const packedEmojiDetailedSchema = {
format: 'id',
},
},
copyPermission: { type: 'string', enum: emojiCopyPermissions, nullable: true, },
usageInfo: { type: 'string', nullable: true, },
author: { type: 'string', nullable: true, },
description: { type: 'string', nullable: true, },
},
} as const;
10 changes: 10 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/emoji/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DI } from '@/di-symbols.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { ApiError } from '../../../error.js';
import { emojiCopyPermissions } from '@/types.js';

export const meta = {
tags: ['admin'],
Expand Down Expand Up @@ -56,6 +57,11 @@ export const paramDef = {
roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
type: 'string',
} },

copyPermission: { type: 'string', enum: emojiCopyPermissions, nullable: true, default: null, description: 'この絵文字を外部サーバーへコピーすることの許可' },
usageInfo: { type: 'string', nullable: true, description: '使用する際の説明' },
author: { type: 'string', nullable: true, description: '作者情報' },
description: { type: 'string', nullable: true, description: '絵文字の説明' },
},
required: ['name', 'fileId'],
} as const;
Expand Down Expand Up @@ -88,6 +94,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSensitive: ps.isSensitive ?? false,
localOnly: ps.localOnly ?? false,
roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [],
copyPermission: ps.copyPermission ?? null,
usageInfo: ps.copyPermission ?? null,
author: ps.copyPermission ?? null,
description: ps.copyPermission ?? null,
}, me);

return this.emojiEntityService.packDetailed(emoji);
Expand Down
9 changes: 9 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/emoji/adds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { secureRndstr } from '@/misc/secure-rndstr.js';
import { ApiError } from '../../../error.js';
import { emojiCopyPermissions } from '@/types.js';

export const meta = {
tags: ['admin'],
Expand Down Expand Up @@ -57,6 +58,10 @@ export const paramDef = {
roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: {
type: 'string',
} },
copyPermission: { type: 'string', enum: emojiCopyPermissions, nullable: true, default: null, description: 'この絵文字を外部サーバーへコピーすることの許可' },
usageInfo: { type: 'string', nullable: true, description: '使用する際の説明' },
author: { type: 'string', nullable: true, description: '作者情報' },
description: { type: 'string', nullable: true, description: '絵文字の説明' },
},
required: ['fileId'],
} as const;
Expand Down Expand Up @@ -92,6 +97,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSensitive: ps.isSensitive ?? false,
localOnly: ps.localOnly ?? false,
roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [],
copyPermission: ps.copyPermission,
usageInfo: ps.usageInfo ?? null,
author: ps.author ?? null,
description: ps.description ?? null,
}, me);

return this.emojiEntityService.packDetailed(emoji);
Expand Down
17 changes: 17 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DI } from '@/di-symbols.js';
import { DriveService } from '@/core/DriveService.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { emojiCopyPermissions } from '@/types.js';
import { ApiError } from '../../../error.js';

export const meta = {
Expand All @@ -31,6 +32,16 @@ export const meta = {
code: 'DUPLICATE_NAME',
id: 'f7a3462c-4e6e-4069-8421-b9bd4f4c3975',
},
copyIsNotAllowed: {
message: 'Copy is not allowed this emoji.',
code: 'NOT_ALLOWED',
id: '1beadfcc-3882-f3c9-ee57-ded45e4741e4',
},
seeUsageInfo: {
message: 'see Usage information.',
code: 'SeeUsageInfo',
id: '28d9031e-ddbc-5ba3-c435-fcb5259e8408',
},
},

res: {
Expand Down Expand Up @@ -71,6 +82,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.noSuchEmoji);
}

if (emoji.copyPermission === emojiCopyPermissions[1]) throw new ApiError(meta.errors.copyIsNotAllowed);

let driveFile: MiDriveFile;

try {
Expand All @@ -95,6 +108,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isSensitive: emoji.isSensitive,
localOnly: emoji.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
copyPermission: emoji.copyPermission,
usageInfo: emoji.usageInfo,
author: emoji.author,
description: emoji.description,
}, me);

return this.emojiEntityService.packDetailed(addedEmoji);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { UtilityService } from '@/core/UtilityService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { DI } from '@/di-symbols.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
import { emojiCopyPermissions } from "@/types.js";

export const meta = {
tags: ['admin'],
Expand Down Expand Up @@ -56,6 +57,10 @@ export const meta = {
type: 'string',
optional: false, nullable: false,
},
copyPermission: { type: 'string', enum: emojiCopyPermissions, nullable: true, default: null, description: 'この絵文字を外部サーバーへコピーすることの許可' },
usageInfo: { type: 'string', nullable: true, description: '使用する際の説明' },
author: { type: 'string', nullable: true, description: '作者情報' },
description: { type: 'string', nullable: true, description: '絵文字の説明' },
},
},
},
Expand Down
16 changes: 16 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/emoji/steal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DriveService } from '@/core/DriveService.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { ApiError } from '../../../error.js';
import {emojiCopyPermissions} from "@/types.js";

Check failure on line 16 in packages/backend/src/server/api/endpoints/admin/emoji/steal.ts

View workflow job for this annotation

GitHub Actions / lint (backend)

A space is required after '{'

Check failure on line 16 in packages/backend/src/server/api/endpoints/admin/emoji/steal.ts

View workflow job for this annotation

GitHub Actions / lint (backend)

A space is required before '}'

export const meta = {
tags: ['admin'],
Expand All @@ -37,6 +38,16 @@ export const meta = {
code: 'LOCAL_EMOJI_ALREADY_EXISTS',
id: 'c7262375-102c-41c6-be6b-4f81166a8a5b',
},
copyIsNotAllowed: {
message: 'Copy is not allowed this emoji.',
code: 'NOT_ALLOWED',
id: '1beadfcc-3882-f3c9-ee57-ded45e4741e4',
},
seeUsageInfo: {
message: 'see Usage information.',
code: 'SeeUsageInfo',
id: '28d9031e-ddbc-5ba3-c435-fcb5259e8408',
},
},

res: {
Expand Down Expand Up @@ -79,6 +90,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (emoji == null) {
throw new ApiError(meta.errors.noSuchEmoji);
}
if (emoji.copyPermission === emojiCopyPermissions[1]) throw new ApiError(meta.errors.copyIsNotAllowed);

if (localEmoji != null) {
throw new ApiError(meta.errors.localEmojiAlreadyExists);
Expand Down Expand Up @@ -108,6 +120,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
isSensitive: emoji.isSensitive,
localOnly: emoji.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
copyPermission: emoji.copyPermission,
usageInfo: emoji.usageInfo,
author: emoji.author,
description: emoji.description,
}, me);

return this.emojiEntityService.packDetailed(addedEmoji);
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const;
export const followingVisibilities = ['public', 'followers', 'private'] as const;
export const followersVisibilities = ['public', 'followers', 'private'] as const;
export const searchableTypes = ['public', 'followersAndReacted', 'reactedOnly', 'private'] as const;

export const emojiCopyPermissions = ['allow', 'deny', 'conditional'] as const;
/**
* ユーザーがエクスポートできるものの種類
*
Expand Down
15 changes: 15 additions & 0 deletions packages/frontend/src/pages/custom-emojis-manager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ const edit = (emoji) => {
};

const importEmoji = async(emoji) => {
if (emoji.copyPermission && emoji.copyPermission !== 'allow') {
if (emoji.copyPermission === 'deny') {
await os.alert({ type: 'error',
title: '作成者によりこの絵文字のコピーは禁止されています',
});
return;
}

const { canceled } = await os.confirm({
type: 'warning',
title: 'ライセンスを確認してください' + emoji.copyPermission === 'conditional' ? '' : emoji.copyPermission,
text: emoji.license,
});
if (canceled) return;
}
let res = await os.apiWithDialog('admin/emoji/copy', {
emojiId: emoji.id,
});
Expand Down

0 comments on commit 8f9229c

Please sign in to comment.