diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2019-04-14 20:38:55 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2019-04-14 20:38:55 +0900 |
| commit | d66e4b7ff97d512e2a2523815e2eef170456b37f (patch) | |
| tree | 59ae1a102d88b5c2c2236b734ea4a584b4f9ba46 /src/misc | |
| parent | 10.100.0 (diff) | |
| parent | 11.0.0 (diff) | |
| download | misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.tar.gz misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.tar.bz2 misskey-d66e4b7ff97d512e2a2523815e2eef170456b37f.zip | |
Merge branch 'develop'
Diffstat (limited to 'src/misc')
| -rw-r--r-- | src/misc/acct/render.ts | 2 | ||||
| -rw-r--r-- | src/misc/acct/type.ts | 2 | ||||
| -rw-r--r-- | src/misc/cafy-id.ts | 29 | ||||
| -rw-r--r-- | src/misc/check-mongodb.ts | 37 | ||||
| -rw-r--r-- | src/misc/convert-host.ts | 17 | ||||
| -rw-r--r-- | src/misc/detect-mine.ts | 2 | ||||
| -rw-r--r-- | src/misc/donwload-url.ts | 3 | ||||
| -rw-r--r-- | src/misc/fetch-meta.ts | 42 | ||||
| -rw-r--r-- | src/misc/fetch-proxy-account.ts | 9 | ||||
| -rw-r--r-- | src/misc/gen-id.ts | 19 | ||||
| -rw-r--r-- | src/misc/get-drive-file-url.ts | 31 | ||||
| -rw-r--r-- | src/misc/get-notification-summary.ts | 2 | ||||
| -rw-r--r-- | src/misc/get-user-name.ts | 4 | ||||
| -rw-r--r-- | src/misc/get-user-summary.ts | 18 | ||||
| -rw-r--r-- | src/misc/id/aid.ts | 23 | ||||
| -rw-r--r-- | src/misc/id/meid.ts | 26 | ||||
| -rw-r--r-- | src/misc/id/object-id.ts | 26 | ||||
| -rw-r--r-- | src/misc/identifiable-error.ts | 2 | ||||
| -rw-r--r-- | src/misc/is-duplicate-key-value-error.ts | 3 | ||||
| -rw-r--r-- | src/misc/is-objectid.ts | 5 | ||||
| -rw-r--r-- | src/misc/is-quote.ts | 6 | ||||
| -rw-r--r-- | src/misc/nyaize.ts | 9 | ||||
| -rw-r--r-- | src/misc/reaction-lib.ts | 6 | ||||
| -rw-r--r-- | src/misc/schema.ts | 4 | ||||
| -rw-r--r-- | src/misc/should-mute-this-note.ts | 13 |
25 files changed, 156 insertions, 184 deletions
diff --git a/src/misc/acct/render.ts b/src/misc/acct/render.ts index 67e063fcb3..094eceffe9 100644 --- a/src/misc/acct/render.ts +++ b/src/misc/acct/render.ts @@ -1,5 +1,5 @@ import Acct from './type'; export default (user: Acct) => { - return user.host === null ? user.username : `${user.username}@${user.host}`; + return user.host == null ? user.username : `${user.username}@${user.host}`; }; diff --git a/src/misc/acct/type.ts b/src/misc/acct/type.ts index c88a920c69..7f31257400 100644 --- a/src/misc/acct/type.ts +++ b/src/misc/acct/type.ts @@ -1,6 +1,6 @@ type Acct = { username: string; - host: string; + host: string | null; }; export default Acct; diff --git a/src/misc/cafy-id.ts b/src/misc/cafy-id.ts index bc8fe4ea2b..39886611e1 100644 --- a/src/misc/cafy-id.ts +++ b/src/misc/cafy-id.ts @@ -1,38 +1,13 @@ -import * as mongo from 'mongodb'; import { Context } from 'cafy'; -import isObjectId from './is-objectid'; -export const isAnId = (x: any) => mongo.ObjectID.isValid(x); -export const isNotAnId = (x: any) => !isAnId(x); -export const transform = (x: string | mongo.ObjectID): mongo.ObjectID => { - if (x === undefined) return undefined; - if (x === null) return null; - - if (isAnId(x) && !isObjectId(x)) { - return new mongo.ObjectID(x); - } else { - return x as mongo.ObjectID; - } -}; -export const transformMany = (xs: (string | mongo.ObjectID)[]): mongo.ObjectID[] => { - if (xs == null) return null; - - return xs.map(x => transform(x)); -}; - -export type ObjectId = mongo.ObjectID; - -/** - * ID - */ -export default class ID<Maybe = string> extends Context<string | Maybe> { +export class ID<Maybe = string> extends Context<string | (Maybe extends {} ? string : Maybe)> { public readonly name = 'ID'; constructor(optional = false, nullable = false) { super(optional, nullable); this.push((v: any) => { - if (!isObjectId(v) && isNotAnId(v)) { + if (typeof v !== 'string') { return new Error('must-be-an-id'); } return true; diff --git a/src/misc/check-mongodb.ts b/src/misc/check-mongodb.ts deleted file mode 100644 index 8e03db5d42..0000000000 --- a/src/misc/check-mongodb.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { nativeDbConn } from '../db/mongodb'; -import { Config } from '../config/types'; -import Logger from '../services/logger'; -import { lessThan } from '../prelude/array'; - -const requiredMongoDBVersion = [3, 6]; - -export function checkMongoDB(config: Config, logger: Logger) { - return new Promise((res, rej) => { - const mongoDBLogger = logger.createSubLogger('db'); - const u = config.mongodb.user ? encodeURIComponent(config.mongodb.user) : null; - const p = config.mongodb.pass ? encodeURIComponent(config.mongodb.pass) : null; - const uri = `mongodb://${u && p ? `${u}:****@` : ''}${config.mongodb.host}:${config.mongodb.port}/${config.mongodb.db}`; - mongoDBLogger.info(`Connecting to ${uri} ...`); - - nativeDbConn().then(db => { - mongoDBLogger.succ('Connectivity confirmed'); - - db.admin().serverInfo().then(x => { - const version = x.version as string; - mongoDBLogger.info(`Version: ${version}`); - if (lessThan(version.split('.').map(x => parseInt(x, 10)), requiredMongoDBVersion)) { - mongoDBLogger.error(`MongoDB version is less than ${requiredMongoDBVersion.join('.')}. Please upgrade it.`); - rej('outdated version'); - } else { - res(); - } - }).catch(err => { - mongoDBLogger.error(`Failed to fetch server info: ${err.message}`); - rej(err); - }); - }).catch(err => { - mongoDBLogger.error(err.message); - rej(err); - }); - }); -} diff --git a/src/misc/convert-host.ts b/src/misc/convert-host.ts index 8f2f1c7aba..a5fb15c66f 100644 --- a/src/misc/convert-host.ts +++ b/src/misc/convert-host.ts @@ -1,27 +1,26 @@ import config from '../config'; -import { toUnicode, toASCII } from 'punycode'; +import { toASCII } from 'punycode'; import { URL } from 'url'; -export function getFullApAccount(username: string, host: string) { - return host ? `${username}@${toApHost(host)}` : `${username}@${toApHost(config.host)}`; +export function getFullApAccount(username: string, host: string | null) { + return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`; } export function isSelfHost(host: string) { if (host == null) return true; - return toApHost(config.host) === toApHost(host); + return toPuny(config.host) === toPuny(host); } export function extractDbHost(uri: string) { const url = new URL(uri); - return toDbHost(url.hostname); + return toPuny(url.hostname); } -export function toDbHost(host: string) { - if (host == null) return null; - return toUnicode(host.toLowerCase()); +export function toPuny(host: string) { + return toASCII(host.toLowerCase()); } -export function toApHost(host: string) { +export function toPunyNullable(host: string | null | undefined): string | null { if (host == null) return null; return toASCII(host.toLowerCase()); } diff --git a/src/misc/detect-mine.ts b/src/misc/detect-mine.ts index bbf49efc10..70d58ffe21 100644 --- a/src/misc/detect-mine.ts +++ b/src/misc/detect-mine.ts @@ -3,7 +3,7 @@ import fileType from 'file-type'; import checkSvg from '../misc/check-svg'; export async function detectMine(path: string) { - return new Promise<[string, string]>((res, rej) => { + return new Promise<[string, string | null]>((res, rej) => { const readable = fs.createReadStream(path); readable .on('error', rej) diff --git a/src/misc/donwload-url.ts b/src/misc/donwload-url.ts index 0dd4e4ef5d..167e01fdd1 100644 --- a/src/misc/donwload-url.ts +++ b/src/misc/donwload-url.ts @@ -1,5 +1,4 @@ import * as fs from 'fs'; -import * as URL from 'url'; import * as request from 'request'; import config from '../config'; import chalk from 'chalk'; @@ -26,7 +25,7 @@ export async function downloadUrl(url: string, path: string) { rej(error); }); - const requestUrl = URL.parse(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url; + const requestUrl = new URL(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url; const req = request({ url: requestUrl, diff --git a/src/misc/fetch-meta.ts b/src/misc/fetch-meta.ts index 3584a819bf..cf1fc474ce 100644 --- a/src/misc/fetch-meta.ts +++ b/src/misc/fetch-meta.ts @@ -1,32 +1,14 @@ -import Meta, { IMeta } from '../models/meta'; +import { Meta } from '../models/entities/meta'; +import { Metas } from '../models'; +import { genId } from './gen-id'; -const defaultMeta: any = { - name: 'Misskey', - maintainer: {}, - langs: [], - cacheRemoteFiles: true, - localDriveCapacityMb: 256, - remoteDriveCapacityMb: 8, - hidedTags: [], - stats: { - originalNotesCount: 0, - originalUsersCount: 0 - }, - maxNoteTextLength: 1000, - enableEmojiReaction: true, - enableTwitterIntegration: false, - enableGithubIntegration: false, - enableDiscordIntegration: false, - enableExternalUserRecommendation: false, - externalUserRecommendationEngine: 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}', - externalUserRecommendationTimeout: 300000, - mascotImageUrl: '/assets/ai.png', - errorImageUrl: 'https://ai.misskey.xyz/aiart/yubitun.png', - enableServiceWorker: false -}; - -export default async function(): Promise<IMeta> { - const meta = await Meta.findOne({}); - - return Object.assign({}, defaultMeta, meta); +export default async function(): Promise<Meta> { + const meta = await Metas.findOne(); + if (meta) { + return meta; + } else { + return Metas.save({ + id: genId(), + } as Meta); + } } diff --git a/src/misc/fetch-proxy-account.ts b/src/misc/fetch-proxy-account.ts new file mode 100644 index 0000000000..17b021e91e --- /dev/null +++ b/src/misc/fetch-proxy-account.ts @@ -0,0 +1,9 @@ +import fetchMeta from './fetch-meta'; +import { ILocalUser } from '../models/entities/user'; +import { Users } from '../models'; +import { ensure } from '../prelude/ensure'; + +export async function fetchProxyAccount(): Promise<ILocalUser> { + const meta = await fetchMeta(); + return await Users.findOne({ username: meta.proxyAccount!, host: null }).then(ensure) as ILocalUser; +} diff --git a/src/misc/gen-id.ts b/src/misc/gen-id.ts new file mode 100644 index 0000000000..99cb70b3fb --- /dev/null +++ b/src/misc/gen-id.ts @@ -0,0 +1,19 @@ +import { ulid } from 'ulid'; +import { genAid } from './id/aid'; +import { genMeid } from './id/meid'; +import { genObjectId } from './id/object-id'; +import config from '../config'; + +const metohd = config.id.toLowerCase(); + +export function genId(date?: Date): string { + if (!date || (date > new Date())) date = new Date(); + + switch (metohd) { + case 'aid': return genAid(date); + case 'meid': return genMeid(date); + case 'ulid': return ulid(date.getTime()); + case 'objectid': return genObjectId(date); + default: throw new Error('unknown id generation method'); + } +} diff --git a/src/misc/get-drive-file-url.ts b/src/misc/get-drive-file-url.ts deleted file mode 100644 index f2b0f8b001..0000000000 --- a/src/misc/get-drive-file-url.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { IDriveFile } from '../models/drive-file'; -import config from '../config'; - -export default function(file: IDriveFile, thumbnail = false): string { - if (file == null) return null; - - const isImage = file.contentType && file.contentType.startsWith('image/'); - - if (file.metadata.withoutChunks) { - if (thumbnail) { - return file.metadata.thumbnailUrl || file.metadata.webpublicUrl || (isImage ? file.metadata.url : '/assets/thumbnail-not-available.png'); - } else { - return file.metadata.webpublicUrl || file.metadata.url; - } - } else { - if (thumbnail) { - return `${config.driveUrl}/${file._id}?thumbnail`; - } else { - return `${config.driveUrl}/${file._id}?web`; - } - } -} - -export function getOriginalUrl(file: IDriveFile) { - if (file.metadata && file.metadata.url) { - return file.metadata.url; - } - - const accessKey = file.metadata ? file.metadata.accessKey : null; - return `${config.driveUrl}/${file._id}${accessKey ? '?original=' + accessKey : ''}`; -} diff --git a/src/misc/get-notification-summary.ts b/src/misc/get-notification-summary.ts index 71d4973ce9..b20711c605 100644 --- a/src/misc/get-notification-summary.ts +++ b/src/misc/get-notification-summary.ts @@ -20,7 +20,7 @@ export default function(notification: any): string { return `引用されました:\n${getUserName(notification.user)}「${getNoteSummary(notification.note)}」`; case 'reaction': return `リアクションされました:\n${getUserName(notification.user)} <${getReactionEmoji(notification.reaction)}>「${getNoteSummary(notification.note)}」`; - case 'poll_vote': + case 'pollVote': return `投票されました:\n${getUserName(notification.user)}「${getNoteSummary(notification.note)}」`; default: return `<不明な通知タイプ: ${notification.type}>`; diff --git a/src/misc/get-user-name.ts b/src/misc/get-user-name.ts index eab9f87ef0..b6b45118b0 100644 --- a/src/misc/get-user-name.ts +++ b/src/misc/get-user-name.ts @@ -1,5 +1,5 @@ -import { IUser } from '../models/user'; +import { User } from '../models/entities/user'; -export default function(user: IUser): string { +export default function(user: User): string { return user.name || user.username; } diff --git a/src/misc/get-user-summary.ts b/src/misc/get-user-summary.ts deleted file mode 100644 index 09cf5ebadc..0000000000 --- a/src/misc/get-user-summary.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { IUser, isLocalUser } from '../models/user'; -import getAcct from './acct/render'; -import getUserName from './get-user-name'; - -/** - * ユーザーを表す文字列を取得します。 - * @param user ユーザー - */ -export default function(user: IUser): string { - let string = `${getUserName(user)} (@${getAcct(user)})\n` + - `${user.notesCount}投稿、${user.followingCount}フォロー、${user.followersCount}フォロワー\n`; - - if (isLocalUser(user)) { - string += `場所: ${user.profile.location}、誕生日: ${user.profile.birthday}\n`; - } - - return string + `「${user.description}」`; -} diff --git a/src/misc/id/aid.ts b/src/misc/id/aid.ts new file mode 100644 index 0000000000..530d84e582 --- /dev/null +++ b/src/misc/id/aid.ts @@ -0,0 +1,23 @@ +// AID +// 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さ2の[ノイズ文字列] + +import * as cluster from 'cluster'; + +const TIME2000 = 946684800000; +let counter = process.pid + (cluster.isMaster ? 0 : cluster.worker.id); + +function getTime(time: number) { + time = time - TIME2000; + if (time < 0) time = 0; + + return time.toString(36).padStart(8, '0'); +} + +function getNoise() { + return counter.toString(36).padStart(2, '0').slice(-2); +} + +export function genAid(date: Date): string { + counter++; + return getTime(date.getTime()) + getNoise(); +} diff --git a/src/misc/id/meid.ts b/src/misc/id/meid.ts new file mode 100644 index 0000000000..d4dc73b4f1 --- /dev/null +++ b/src/misc/id/meid.ts @@ -0,0 +1,26 @@ +const CHARS = '0123456789abcdef'; + +function getTime(time: number) { + if (time < 0) time = 0; + if (time === 0) { + return CHARS[0]; + } + + time += 0x800000000000; + + return time.toString(16).padStart(12, CHARS[0]); +} + +function getRandom() { + let str = ''; + + for (let i = 0; i < 12; i++) { + str += CHARS[Math.floor(Math.random() * CHARS.length)]; + } + + return str; +} + +export function genMeid(date: Date): string { + return 'f' + getTime(date.getTime()) + getRandom(); +} diff --git a/src/misc/id/object-id.ts b/src/misc/id/object-id.ts new file mode 100644 index 0000000000..392ea43301 --- /dev/null +++ b/src/misc/id/object-id.ts @@ -0,0 +1,26 @@ +const CHARS = '0123456789abcdef'; + +function getTime(time: number) { + if (time < 0) time = 0; + if (time === 0) { + return CHARS[0]; + } + + time = Math.floor(time / 1000); + + return time.toString(16).padStart(8, CHARS[0]); +} + +function getRandom() { + let str = ''; + + for (let i = 0; i < 16; i++) { + str += CHARS[Math.floor(Math.random() * CHARS.length)]; + } + + return str; +} + +export function genObjectId(date: Date): string { + return getTime(date.getTime()) + getRandom(); +} diff --git a/src/misc/identifiable-error.ts b/src/misc/identifiable-error.ts index 1edd26cd18..2d7c6bd0c6 100644 --- a/src/misc/identifiable-error.ts +++ b/src/misc/identifiable-error.ts @@ -7,7 +7,7 @@ export class IdentifiableError extends Error { constructor(id: string, message?: string) { super(message); - this.message = message; + this.message = message || ''; this.id = id; } } diff --git a/src/misc/is-duplicate-key-value-error.ts b/src/misc/is-duplicate-key-value-error.ts new file mode 100644 index 0000000000..23d8ceb1b7 --- /dev/null +++ b/src/misc/is-duplicate-key-value-error.ts @@ -0,0 +1,3 @@ +export function isDuplicateKeyValueError(e: Error): boolean { + return e.message.startsWith('duplicate key value'); +} diff --git a/src/misc/is-objectid.ts b/src/misc/is-objectid.ts deleted file mode 100644 index a77c4ee2d5..0000000000 --- a/src/misc/is-objectid.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ObjectID } from 'mongodb'; - -export default function(x: any): x is ObjectID { - return x && typeof x === 'object' && (x.hasOwnProperty('toHexString') || x.hasOwnProperty('_bsontype')); -} diff --git a/src/misc/is-quote.ts b/src/misc/is-quote.ts index a99b8f6434..0a2a72f4a0 100644 --- a/src/misc/is-quote.ts +++ b/src/misc/is-quote.ts @@ -1,5 +1,5 @@ -import { INote } from '../models/note'; +import { Note } from '../models/entities/note'; -export default function(note: INote): boolean { - return note.renoteId != null && (note.text != null || note.poll != null || (note.fileIds != null && note.fileIds.length > 0)); +export default function(note: Note): boolean { + return note.renoteId != null && (note.text != null || note.hasPoll || (note.fileIds != null && note.fileIds.length > 0)); } diff --git a/src/misc/nyaize.ts b/src/misc/nyaize.ts new file mode 100644 index 0000000000..918e7d63fd --- /dev/null +++ b/src/misc/nyaize.ts @@ -0,0 +1,9 @@ +export function nyaize(text: string): string { + return text + // ja-JP + .replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ') + // ko-KR + .replace(/[나-낳]/g, match => String.fromCharCode( + match.codePointAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0) + )); +} diff --git a/src/misc/reaction-lib.ts b/src/misc/reaction-lib.ts index 7e5a1b0bc0..008991454b 100644 --- a/src/misc/reaction-lib.ts +++ b/src/misc/reaction-lib.ts @@ -1,6 +1,6 @@ -import Emoji from '../models/emoji'; import { emojiRegex } from './emoji-regex'; import fetchMeta from './fetch-meta'; +import { Emojis } from '../models'; const basic10: Record<string, string> = { '👍': 'like', @@ -20,7 +20,7 @@ export async function getFallbackReaction(): Promise<string> { return meta.useStarForReactionFallback ? 'star' : 'like'; } -export async function toDbReaction(reaction: string, enableEmoji = true): Promise<string> { +export async function toDbReaction(reaction?: string | null, enableEmoji = true): Promise<string> { if (reaction == null) return await getFallbackReaction(); // 既存の文字列リアクションはそのまま @@ -49,7 +49,7 @@ export async function toDbReaction(reaction: string, enableEmoji = true): Promis const custom = reaction.match(/^:([\w+-]+):$/); if (custom) { - const emoji = await Emoji.findOne({ + const emoji = await Emojis.findOne({ host: null, name: custom[1], }); diff --git a/src/misc/schema.ts b/src/misc/schema.ts index e5c24dd468..7c17953d97 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -19,8 +19,8 @@ type MyType<T extends Schema> = { export type SchemaType<p extends Schema> = p['type'] extends 'number' ? number : p['type'] extends 'string' ? string : - p['type'] extends 'array' ? MyType<p['items']>[] : - p['type'] extends 'object' ? ObjType<p['properties']> : + p['type'] extends 'array' ? MyType<NonNullable<p['items']>>[] : + p['type'] extends 'object' ? ObjType<NonNullable<p['properties']>> : any; export function convertOpenApiSchema(schema: Schema) { diff --git a/src/misc/should-mute-this-note.ts b/src/misc/should-mute-this-note.ts index b1d29c6a28..8f606a2943 100644 --- a/src/misc/should-mute-this-note.ts +++ b/src/misc/should-mute-this-note.ts @@ -1,20 +1,13 @@ -import * as mongo from 'mongodb'; -import isObjectId from './is-objectid'; - -function toString(id: any) { - return isObjectId(id) ? (id as mongo.ObjectID).toHexString() : id; -} - export default function(note: any, mutedUserIds: string[]): boolean { - if (mutedUserIds.includes(toString(note.userId))) { + if (mutedUserIds.includes(note.userId)) { return true; } - if (note.reply != null && mutedUserIds.includes(toString(note.reply.userId))) { + if (note.reply != null && mutedUserIds.includes(note.reply.userId)) { return true; } - if (note.renote != null && mutedUserIds.includes(toString(note.renote.userId))) { + if (note.renote != null && mutedUserIds.includes(note.renote.userId)) { return true; } |