diff options
Diffstat (limited to 'src/server/api/endpoints')
| -rw-r--r-- | src/server/api/endpoints/ap/show.ts | 116 | ||||
| -rw-r--r-- | src/server/api/endpoints/drive/files/check_existence.ts | 38 | ||||
| -rw-r--r-- | src/server/api/endpoints/games/reversi/match.ts | 6 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/regenerate_token.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update_client_setting.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update_home.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update_mobile_home.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/i/update_widget.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/messaging/messages/create.ts | 14 | ||||
| -rw-r--r-- | src/server/api/endpoints/meta.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/polls/vote.ts | 5 | ||||
| -rw-r--r-- | src/server/api/endpoints/notifications/mark_all_as_read.ts | 4 | ||||
| -rw-r--r-- | src/server/api/endpoints/users/recommendation.ts | 100 |
14 files changed, 249 insertions, 60 deletions
diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts new file mode 100644 index 0000000000..6cbd4ef87e --- /dev/null +++ b/src/server/api/endpoints/ap/show.ts @@ -0,0 +1,116 @@ +import $ from 'cafy'; +import getParams from '../../get-params'; +import config from '../../../../config'; +import * as mongo from 'mongodb'; +import User, { pack as packUser, IUser } from '../../../../models/user'; +import { createPerson } from '../../../../remote/activitypub/models/person'; +import Note, { pack as packNote, INote } from '../../../../models/note'; +import { createNote } from '../../../../remote/activitypub/models/note'; +import Resolver from '../../../../remote/activitypub/resolver'; + +export const meta = { + desc: { + 'ja-JP': 'URIを指定してActivityPubオブジェクトを参照します。' + }, + + requireCredential: false, + + params: { + uri: $.str.note({ + desc: { + 'ja-JP': 'ActivityPubオブジェクトのURI' + } + }), + }, +}; + +export default async (params: any) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; + + const object = await fetchAny(ps.uri); + if (object !== null) return object; + + throw new Error('object not found'); +}; + +/*** + * URIからUserかNoteを解決する + */ +async function fetchAny(uri: string) { + // URIがこのサーバーを指しているなら、ローカルユーザーIDとしてDBからフェッチ + if (uri.startsWith(config.url + '/')) { + const id = new mongo.ObjectID(uri.split('/').pop()); + const [ user, note ] = await Promise.all([ + User.findOne({ _id: id }), + Note.findOne({ _id: id }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // URI(AP Object id)としてDB検索 + { + const [ user, note ] = await Promise.all([ + User.findOne({ uri: uri }), + Note.findOne({ uri: uri }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // リモートから一旦オブジェクトフェッチ + const resolver = new Resolver(); + const object = await resolver.resolve(uri) as any; + + // /@user のような正規id以外で取得できるURIが指定されていた場合、ここで初めて正規URIが確定する + // これはDBに存在する可能性があるため再度DB検索 + if (uri !== object.id) { + const [ user, note ] = await Promise.all([ + User.findOne({ uri: object.id }), + Note.findOne({ uri: object.id }) + ]); + + const packed = await mergePack(user, note); + if (packed !== null) return packed; + } + + // それでもみつからなければ新規であるため登録 + if (object.type === 'Person') { + const user = await createPerson(object.id); + return { + type: 'User', + object: user + }; + } + + if (object.type === 'Note') { + const note = await createNote(object.id); + return { + type: 'Note', + object: note + }; + } + + return null; +} + +async function mergePack(user: IUser, note: INote) { + if (user !== null) { + return { + type: 'User', + object: await packUser(user, null, { detail: true }) + }; + } + + if (note !== null) { + return { + type: 'Note', + object: await packNote(note, null, { detail: true }) + }; + } + + return null; +} diff --git a/src/server/api/endpoints/drive/files/check_existence.ts b/src/server/api/endpoints/drive/files/check_existence.ts new file mode 100644 index 0000000000..73d75b7caf --- /dev/null +++ b/src/server/api/endpoints/drive/files/check_existence.ts @@ -0,0 +1,38 @@ +import $ from 'cafy'; +import DriveFile, { pack } from '../../../../../models/drive-file'; +import { ILocalUser } from '../../../../../models/user'; + +export const meta = { + desc: { + 'ja-JP': '与えられたMD5ハッシュ値を持つファイルがドライブに存在するかどうかを返します。', + 'en-US': 'Returns whether the file with the given MD5 hash exists in the user\'s drive.' + }, + + requireCredential: true, + + kind: 'drive-read', + + params: { + md5: $.str.note({ + desc: { + 'ja-JP': 'ファイルのMD5ハッシュ' + } + }) + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [md5, md5Err] = $.str.get(params.md5); + if (md5Err) return rej('invalid md5 param'); + + const file = await DriveFile.findOne({ + md5: md5, + 'metadata.userId': user._id + }); + + if (file === null) { + res({ file: null }); + } else { + res({ file: await pack(file) }); + } +}); diff --git a/src/server/api/endpoints/games/reversi/match.ts b/src/server/api/endpoints/games/reversi/match.ts index aba400af1d..d7483a0bfd 100644 --- a/src/server/api/endpoints/games/reversi/match.ts +++ b/src/server/api/endpoints/games/reversi/match.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching'; import ReversiGame, { pack as packGame } from '../../../../../models/games/reversi/game'; import User, { ILocalUser } from '../../../../../models/user'; -import { publishUserStream, publishReversiStream } from '../../../../../stream'; +import { publishMainStream, publishReversiStream } from '../../../../../stream'; import { eighteight } from '../../../../../games/reversi/maps'; export const meta = { @@ -58,7 +58,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = }); if (other == 0) { - publishUserStream(user._id, 'reversi_no_invites'); + publishMainStream(user._id, 'reversi_no_invites'); } } else { // Fetch child @@ -94,6 +94,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = // 招待 publishReversiStream(child._id, 'invited', packed); - publishUserStream(child._id, 'reversi_invited', packed); + publishMainStream(child._id, 'reversiInvited', packed); } }); diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts index fe4a5cd118..2d85f06cfa 100644 --- a/src/server/api/endpoints/i/regenerate_token.ts +++ b/src/server/api/endpoints/i/regenerate_token.ts @@ -1,7 +1,7 @@ import $ from 'cafy'; import * as bcrypt from 'bcryptjs'; import User, { ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; import generateUserToken from '../../common/generate-native-user-token'; export const meta = { @@ -33,5 +33,5 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, res(); // Publish event - publishUserStream(user._id, 'my_token_regenerated'); + publishMainStream(user._id, 'myTokenRegenerated'); }); diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts index c1be0b6ebc..548ce5cadb 100644 --- a/src/server/api/endpoints/i/update.ts +++ b/src/server/api/endpoints/i/update.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; import DriveFile from '../../../../models/drive-file'; import acceptAllFollowRequests from '../../../../services/following/requests/accept-all'; import { IApp } from '../../../../models/app'; @@ -177,7 +177,7 @@ export default async (params: any, user: ILocalUser, app: IApp) => new Promise(a res(iObj); // Publish meUpdated event - publishUserStream(user._id, 'meUpdated', iObj); + publishMainStream(user._id, 'meUpdated', iObj); // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認 if (user.isLocked && ps.isLocked === false) { diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts index aed93c792f..2c05299dff 100644 --- a/src/server/api/endpoints/i/update_client_setting.ts +++ b/src/server/api/endpoints/i/update_client_setting.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; export const meta = { requireCredential: true, @@ -26,7 +26,7 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, res(); // Publish event - publishUserStream(user._id, 'clientSettingUpdated', { + publishMainStream(user._id, 'clientSettingUpdated', { key: name, value }); diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts index ffca9b90b3..27afc9fe5a 100644 --- a/src/server/api/endpoints/i/update_home.ts +++ b/src/server/api/endpoints/i/update_home.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; export const meta = { requireCredential: true, @@ -25,5 +25,5 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, res(); - publishUserStream(user._id, 'home_updated', home); + publishMainStream(user._id, 'homeUpdated', home); }); diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts index 0b72fbe2c1..1d4df389e4 100644 --- a/src/server/api/endpoints/i/update_mobile_home.ts +++ b/src/server/api/endpoints/i/update_mobile_home.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; export const meta = { requireCredential: true, @@ -24,5 +24,5 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, res(); - publishUserStream(user._id, 'mobile_home_updated', home); + publishMainStream(user._id, 'mobileHomeUpdated', home); }); diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts index 5cbe7c07a3..92499493eb 100644 --- a/src/server/api/endpoints/i/update_widget.ts +++ b/src/server/api/endpoints/i/update_widget.ts @@ -1,6 +1,6 @@ import $ from 'cafy'; import User, { ILocalUser } from '../../../../models/user'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; export const meta = { requireCredential: true, @@ -73,7 +73,7 @@ export default async (params: any, user: ILocalUser) => new Promise(async (res, //#endregion if (widget) { - publishUserStream(user._id, 'widgetUpdated', { + publishMainStream(user._id, 'widgetUpdated', { id, data }); diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts index 9a49e09248..cb115cf987 100644 --- a/src/server/api/endpoints/messaging/messages/create.ts +++ b/src/server/api/endpoints/messaging/messages/create.ts @@ -6,7 +6,7 @@ import User, { ILocalUser } from '../../../../../models/user'; import Mute from '../../../../../models/mute'; import DriveFile from '../../../../../models/drive-file'; import { pack } from '../../../../../models/messaging-message'; -import { publishUserStream } from '../../../../../stream'; +import { publishMainStream } from '../../../../../stream'; import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../stream'; import pushSw from '../../../../../push-sw'; @@ -88,12 +88,12 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = // 自分のストリーム publishMessagingStream(message.userId, message.recipientId, 'message', messageObj); publishMessagingIndexStream(message.userId, 'message', messageObj); - publishUserStream(message.userId, 'messaging_message', messageObj); + publishMainStream(message.userId, 'messagingMessage', messageObj); // 相手のストリーム publishMessagingStream(message.recipientId, message.userId, 'message', messageObj); publishMessagingIndexStream(message.recipientId, 'message', messageObj); - publishUserStream(message.recipientId, 'messaging_message', messageObj); + publishMainStream(message.recipientId, 'messagingMessage', messageObj); // Update flag User.update({ _id: recipient._id }, { @@ -102,7 +102,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = } }); - // 3秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する + // 2秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する setTimeout(async () => { const freshMessage = await Message.findOne({ _id: message._id }, { isRead: true }); if (!freshMessage.isRead) { @@ -117,10 +117,10 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = } //#endregion - publishUserStream(message.recipientId, 'unread_messaging_message', messageObj); - pushSw(message.recipientId, 'unread_messaging_message', messageObj); + publishMainStream(message.recipientId, 'unreadMessagingMessage', messageObj); + pushSw(message.recipientId, 'unreadMessagingMessage', messageObj); } - }, 3000); + }, 2000); // 履歴作成(自分) History.update({ diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index 9baf3c252f..c76d7f2e8f 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -32,7 +32,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => model: os.cpus()[0].model, cores: os.cpus().length }, - broadcasts: meta.broadcasts, + broadcasts: meta.broadcasts || [], disableRegistration: meta.disableRegistration, disableLocalTimeline: meta.disableLocalTimeline, driveCapacityPerLocalUserMb: config.localDriveCapacityMb, diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts index ab80e7f5d0..3b78d62fd3 100644 --- a/src/server/api/endpoints/notes/polls/vote.ts +++ b/src/server/api/endpoints/notes/polls/vote.ts @@ -72,7 +72,10 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = $inc: inc }); - publishNoteStream(note._id, 'poll_voted'); + publishNoteStream(note._id, 'pollVoted', { + choice: choice, + userId: user._id.toHexString() + }); // Notify notify(note.userId, user._id, 'poll_vote', { diff --git a/src/server/api/endpoints/notifications/mark_all_as_read.ts b/src/server/api/endpoints/notifications/mark_all_as_read.ts index e2bde777b3..6487cd8b48 100644 --- a/src/server/api/endpoints/notifications/mark_all_as_read.ts +++ b/src/server/api/endpoints/notifications/mark_all_as_read.ts @@ -1,5 +1,5 @@ import Notification from '../../../../models/notification'; -import { publishUserStream } from '../../../../stream'; +import { publishMainStream } from '../../../../stream'; import User, { ILocalUser } from '../../../../models/user'; export const meta = { @@ -40,5 +40,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = }); // 全ての通知を読みましたよというイベントを発行 - publishUserStream(user._id, 'read_all_notifications'); + publishMainStream(user._id, 'readAllNotifications'); }); diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index e0a5cb9e36..6538a303b8 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -3,6 +3,8 @@ import $ from 'cafy'; import User, { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; import Mute from '../../../../models/mute'; +import * as request from 'request' +import config from '../../../../config' export const meta = { desc: { @@ -15,44 +17,74 @@ export const meta = { }; export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) return rej('invalid limit param'); + if (config.user_recommendation && config.user_recommendation.external) { + const userName = me.username + const hostName = config.hostname + const limit = params.limit + const offset = params.offset + const timeout = config.user_recommendation.timeout + const engine = config.user_recommendation.engine + const url = engine + .replace('{{host}}', hostName) + .replace('{{user}}', userName) + .replace('{{limit}}', limit) + .replace('{{offset}}', offset) + request( + { + url: url, + timeout: timeout, + json: true, + followRedirect: true, + followAllRedirects: true + }, + (error: any, response: any, body: any) => { + if (!error && response.statusCode == 200) { + res(body) + } else { + res([]) + } + } + ) + } else { + // Get 'limit' parameter + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); + if (limitErr) return rej('invalid limit param'); - // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); - if (offsetErr) return rej('invalid offset param'); + // Get 'offset' parameter + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); + if (offsetErr) return rej('invalid offset param'); - // ID list of the user itself and other users who the user follows - const followingIds = await getFriendIds(me._id); + // ID list of the user itself and other users who the user follows + const followingIds = await getFriendIds(me._id); - // ミュートしているユーザーを取得 - const mutedUserIds = (await Mute.find({ - muterId: me._id - })).map(m => m.muteeId); + // ミュートしているユーザーを取得 + const mutedUserIds = (await Mute.find({ + muterId: me._id + })).map(m => m.muteeId); - const users = await User - .find({ - _id: { - $nin: followingIds.concat(mutedUserIds) - }, - isLocked: false, - $or: [{ - lastUsedAt: { - $gte: new Date(Date.now() - ms('7days')) - } + const users = await User + .find({ + _id: { + $nin: followingIds.concat(mutedUserIds) + }, + isLocked: false, + $or: [{ + lastUsedAt: { + $gte: new Date(Date.now() - ms('7days')) + } + }, { + host: null + }] }, { - host: null - }] - }, { - limit: limit, - skip: offset, - sort: { - followersCount: -1 - } - }); + limit: limit, + skip: offset, + sort: { + followersCount: -1 + } + }); - // Serialize - res(await Promise.all(users.map(async user => - await pack(user, me, { detail: true })))); + // Serialize + res(await Promise.all(users.map(async user => + await pack(user, me, { detail: true })))); + } }); |