外部サービス認証情報の配信 (#3975)
* Update person.ts * Update person.ts * Update person.ts * Update person.ts * Create original model * Make type formal * Update person.ts * Follow @mei23's review refs: https://github.com/syuilo/misskey/pull/3975#pullrequestreview-195770172
This commit is contained in:
parent
4632eecb76
commit
e2f7e82cac
4 changed files with 88 additions and 20 deletions
5
src/remote/activitypub/models/identifier.ts
Normal file
5
src/remote/activitypub/models/identifier.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export type IIdentifier = {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
};
|
|
@ -19,6 +19,7 @@ import getDriveFileUrl from '../../../misc/get-drive-file-url';
|
||||||
import { IEmoji } from '../../../models/emoji';
|
import { IEmoji } from '../../../models/emoji';
|
||||||
import { ITag } from './tag';
|
import { ITag } from './tag';
|
||||||
import Following from '../../../models/following';
|
import Following from '../../../models/following';
|
||||||
|
import { IIdentifier } from './identifier';
|
||||||
|
|
||||||
const log = debug('misskey:activitypub');
|
const log = debug('misskey:activitypub');
|
||||||
|
|
||||||
|
@ -137,9 +138,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
|
||||||
|
|
||||||
const host = toUnicode(new URL(object.id).hostname.toLowerCase());
|
const host = toUnicode(new URL(object.id).hostname.toLowerCase());
|
||||||
|
|
||||||
const fields = await extractFields(person.attachment).catch(e => {
|
const { fields, services } = analyzeAttachments(person.attachment);
|
||||||
console.log(`cat not extract fields: ${e}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
const isBot = object.type == 'Service';
|
const isBot = object.type == 'Service';
|
||||||
|
|
||||||
|
@ -171,7 +170,8 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
|
||||||
uri: person.id,
|
uri: person.id,
|
||||||
url: person.url,
|
url: person.url,
|
||||||
fields,
|
fields,
|
||||||
isBot: isBot,
|
...services,
|
||||||
|
isBot,
|
||||||
isCat: (person as any).isCat === true
|
isCat: (person as any).isCat === true
|
||||||
}) as IRemoteUser;
|
}) as IRemoteUser;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -332,9 +332,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
|
||||||
|
|
||||||
const emojiNames = emojis.map(emoji => emoji.name);
|
const emojiNames = emojis.map(emoji => emoji.name);
|
||||||
|
|
||||||
const fields = await extractFields(person.attachment).catch(e => {
|
const { fields, services } = analyzeAttachments(person.attachment);
|
||||||
console.log(`cat not extract fields: ${e}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
const updates = {
|
const updates = {
|
||||||
lastFetchedAt: new Date(),
|
lastFetchedAt: new Date(),
|
||||||
|
@ -350,6 +348,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
|
||||||
url: person.url,
|
url: person.url,
|
||||||
endpoints: person.endpoints,
|
endpoints: person.endpoints,
|
||||||
fields,
|
fields,
|
||||||
|
...services,
|
||||||
isBot: object.type == 'Service',
|
isBot: object.type == 'Service',
|
||||||
isCat: (person as any).isCat === true,
|
isCat: (person as any).isCat === true,
|
||||||
isLocked: person.manuallyApprovesFollowers,
|
isLocked: person.manuallyApprovesFollowers,
|
||||||
|
@ -413,16 +412,61 @@ export async function resolvePerson(uri: string, verifier?: string, resolver?: R
|
||||||
return await createPerson(uri, resolver);
|
return await createPerson(uri, resolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function extractFields(attachments: ITag[]) {
|
const isPropertyValue = (x: {
|
||||||
if (!attachments) return [];
|
type: string,
|
||||||
|
name?: string,
|
||||||
|
value?: string
|
||||||
|
}) =>
|
||||||
|
x &&
|
||||||
|
x.type === 'PropertyValue' &&
|
||||||
|
typeof x.name === 'string' &&
|
||||||
|
typeof x.value === 'string';
|
||||||
|
|
||||||
return attachments.filter(a => a.type === 'PropertyValue' && a.name && a.value)
|
const services: {
|
||||||
.map(a => {
|
[x: string]: (id: string, username: string) => any
|
||||||
return {
|
} = {
|
||||||
name: a.name,
|
'misskey:authentication:twitter': (userId, screenName) => ({ userId, screenName }),
|
||||||
value: htmlToMFM(a.value)
|
'misskey:authentication:github': (id, login) => ({ id, login }),
|
||||||
};
|
'misskey:authentication:discord': (id, name) => $discord(id, name)
|
||||||
|
};
|
||||||
|
|
||||||
|
const $discord = (id: string, name: string) => {
|
||||||
|
if (typeof name !== 'string')
|
||||||
|
name = 'unknown#0000';
|
||||||
|
const [username, discriminator] = name.split('#');
|
||||||
|
return { id, username, discriminator };
|
||||||
|
};
|
||||||
|
|
||||||
|
function addService(target: { [x: string]: any }, source: IIdentifier) {
|
||||||
|
const service = services[source.name];
|
||||||
|
|
||||||
|
if (typeof source.value !== 'string')
|
||||||
|
source.value = 'unknown';
|
||||||
|
|
||||||
|
const [id, username] = source.value.split('@');
|
||||||
|
|
||||||
|
if (service)
|
||||||
|
target[source.name.split(':')[2]] = service(id, username);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function analyzeAttachments(attachments: ITag[]) {
|
||||||
|
const fields: {
|
||||||
|
name: string,
|
||||||
|
value: string
|
||||||
|
}[] = [];
|
||||||
|
const services: { [x: string]: any } = {};
|
||||||
|
|
||||||
|
if (Array.isArray(attachments))
|
||||||
|
for (const attachment of attachments.filter(isPropertyValue))
|
||||||
|
if (isPropertyValue(attachment.identifier))
|
||||||
|
addService(services, attachment.identifier);
|
||||||
|
else
|
||||||
|
fields.push({
|
||||||
|
name: attachment.name,
|
||||||
|
value: htmlToMFM(attachment.value)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { fields, services };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateFeatured(userId: mongo.ObjectID) {
|
export async function updateFeatured(userId: mongo.ObjectID) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { IIcon } from './icon';
|
import { IIcon } from './icon';
|
||||||
|
import { IIdentifier } from './identifier';
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* tag (ActivityPub)
|
* tag (ActivityPub)
|
||||||
|
@ -10,4 +11,5 @@ export type ITag = {
|
||||||
value?: string;
|
value?: string;
|
||||||
updated?: Date;
|
updated?: Date;
|
||||||
icon?: IIcon;
|
icon?: IIcon;
|
||||||
|
identifier?: IIdentifier;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@ import parse from '../../../mfm/parse';
|
||||||
import DriveFile from '../../../models/drive-file';
|
import DriveFile from '../../../models/drive-file';
|
||||||
import { getEmojis } from './note';
|
import { getEmojis } from './note';
|
||||||
import renderEmoji from './emoji';
|
import renderEmoji from './emoji';
|
||||||
|
import { IIdentifier } from '../models/identifier';
|
||||||
|
|
||||||
export default async (user: ILocalUser) => {
|
export default async (user: ILocalUser) => {
|
||||||
const id = `${config.url}/users/${user._id}`;
|
const id = `${config.url}/users/${user._id}`;
|
||||||
|
@ -20,14 +21,20 @@ export default async (user: ILocalUser) => {
|
||||||
type: string,
|
type: string,
|
||||||
name: string,
|
name: string,
|
||||||
value: string,
|
value: string,
|
||||||
verified_at?: string
|
verified_at?: string,
|
||||||
|
identifier?: IIdentifier
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
if (user.twitter) {
|
if (user.twitter) {
|
||||||
attachment.push({
|
attachment.push({
|
||||||
type: 'PropertyValue',
|
type: 'PropertyValue',
|
||||||
name: 'Twitter',
|
name: 'Twitter',
|
||||||
value: `<a href="https://twitter.com/intent/user?user_id=${user.twitter.userId}" rel="me nofollow noopener" target="_blank"><span>@${user.twitter.screenName}</span></a>`
|
value: `<a href="https://twitter.com/intent/user?user_id=${user.twitter.userId}" rel="me nofollow noopener" target="_blank"><span>@${user.twitter.screenName}</span></a>`,
|
||||||
|
identifier: {
|
||||||
|
type: 'PropertyValue',
|
||||||
|
name: 'misskey:authentication:twitter',
|
||||||
|
value: `${user.twitter.userId}@${user.twitter.screenName}`
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +42,12 @@ export default async (user: ILocalUser) => {
|
||||||
attachment.push({
|
attachment.push({
|
||||||
type: 'PropertyValue',
|
type: 'PropertyValue',
|
||||||
name: 'GitHub',
|
name: 'GitHub',
|
||||||
value: `<a href="https://github.com/${user.github.login}" rel="me nofollow noopener" target="_blank"><span>@${user.github.login}</span></a>`
|
value: `<a href="https://github.com/${user.github.login}" rel="me nofollow noopener" target="_blank"><span>@${user.github.login}</span></a>`,
|
||||||
|
identifier: {
|
||||||
|
type: 'PropertyValue',
|
||||||
|
name: 'misskey:authentication:github',
|
||||||
|
value: `${user.github.id}@${user.github.login}`
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +55,12 @@ export default async (user: ILocalUser) => {
|
||||||
attachment.push({
|
attachment.push({
|
||||||
type: 'PropertyValue',
|
type: 'PropertyValue',
|
||||||
name: 'Discord',
|
name: 'Discord',
|
||||||
value: `<a href="https://discordapp.com/users/${user.discord.id}" rel="me nofollow noopener" target="_blank"><span>${user.discord.username}#${user.discord.discriminator}</span></a>`
|
value: `<a href="https://discordapp.com/users/${user.discord.id}" rel="me nofollow noopener" target="_blank"><span>${user.discord.username}#${user.discord.discriminator}</span></a>`,
|
||||||
|
identifier: {
|
||||||
|
type: 'PropertyValue',
|
||||||
|
name: 'misskey:authentication:discord',
|
||||||
|
value: `${user.discord.id}@${user.discord.username}#${user.discord.discriminator}`
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue