mirror of
https://github.com/hotomoe/hotomoe
synced 2024-12-18 16:48:09 +09:00
84 lines
2.1 KiB
TypeScript
84 lines
2.1 KiB
TypeScript
import { JSDOM } from 'jsdom';
|
|
import { toUnicode } from 'punycode';
|
|
import parseAcct from '../../acct/parse';
|
|
import config from '../../config';
|
|
import User, { validateUsername, isValidName, isValidDescription } from '../../models/user';
|
|
import webFinger from '../webfinger';
|
|
import Resolver from './resolver';
|
|
import uploadFromUrl from '../../services/drive/upload-from-url';
|
|
|
|
export default async (value, verifier?: string) => {
|
|
const id = value.id || value;
|
|
const localPrefix = config.url + '/@';
|
|
|
|
if (id.startsWith(localPrefix)) {
|
|
return User.findOne(parseAcct(id.slice(localPrefix)));
|
|
}
|
|
|
|
const resolver = new Resolver();
|
|
|
|
const object = await resolver.resolve(value) as any;
|
|
|
|
if (
|
|
object == null ||
|
|
object.type !== 'Person' ||
|
|
typeof object.preferredUsername !== 'string' ||
|
|
!validateUsername(object.preferredUsername) ||
|
|
(object.name != '' && !isValidName(object.name)) ||
|
|
!isValidDescription(object.summary)
|
|
) {
|
|
throw new Error('invalid person');
|
|
}
|
|
|
|
const finger = await webFinger(id, verifier);
|
|
|
|
const host = toUnicode(finger.subject.replace(/^.*?@/, ''));
|
|
const hostLower = host.replace(/[A-Z]+/, matched => matched.toLowerCase());
|
|
const summaryDOM = JSDOM.fragment(object.summary);
|
|
|
|
// Create user
|
|
const user = await User.insert({
|
|
avatarId: null,
|
|
bannerId: null,
|
|
createdAt: Date.parse(object.published) || null,
|
|
description: summaryDOM.textContent,
|
|
followersCount: 0,
|
|
followingCount: 0,
|
|
name: object.name,
|
|
postsCount: 0,
|
|
driveCapacity: 1024 * 1024 * 8, // 8MiB
|
|
username: object.preferredUsername,
|
|
usernameLower: object.preferredUsername.toLowerCase(),
|
|
host,
|
|
hostLower,
|
|
account: {
|
|
publicKey: {
|
|
id: object.publicKey.id,
|
|
publicKeyPem: object.publicKey.publicKeyPem
|
|
},
|
|
inbox: object.inbox,
|
|
uri: id,
|
|
},
|
|
});
|
|
|
|
const [avatarId, bannerId] = await Promise.all([
|
|
object.icon,
|
|
object.image
|
|
].map(async img => {
|
|
if (img === undefined) {
|
|
return null;
|
|
}
|
|
|
|
const file = await uploadFromUrl(img.url, user);
|
|
|
|
return file._id;
|
|
}));
|
|
|
|
User.update({ _id: user._id }, { $set: { avatarId, bannerId } });
|
|
|
|
user.avatarId = avatarId;
|
|
user.bannerId = bannerId;
|
|
|
|
return user;
|
|
};
|