diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-11-02 03:32:24 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-11-02 03:32:24 +0900 |
| commit | 931bdc6aace5e7aa71ffdfb470e208ead78a2a53 (patch) | |
| tree | eee6d7bf5f5480b883bb601517b4d9db03f31e9f /src/server/api/endpoints/notes | |
| parent | Refactoring (diff) | |
| download | sharkey-931bdc6aace5e7aa71ffdfb470e208ead78a2a53.tar.gz sharkey-931bdc6aace5e7aa71ffdfb470e208ead78a2a53.tar.bz2 sharkey-931bdc6aace5e7aa71ffdfb470e208ead78a2a53.zip | |
Refactoring, Clean up and bug fixes
Diffstat (limited to 'src/server/api/endpoints/notes')
21 files changed, 518 insertions, 397 deletions
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts index 0c23f9e5fc..c7be6d6e3f 100644 --- a/src/server/api/endpoints/notes/conversation.ts +++ b/src/server/api/endpoints/notes/conversation.ts @@ -1,26 +1,41 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note, { packMany, INote } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; -/** - * Show conversation of a note - */ -export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); +export const meta = { + desc: { + 'ja-JP': '指定した投稿の文脈を取得します。', + 'en-US': 'Show conversation of a note.' + }, + + requireCredential: false, + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + }, - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) return rej('invalid limit param'); + limit: { + validator: $.num.optional.range(1, 100), + default: 10 + }, - // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); - if (offsetErr) return rej('invalid offset param'); + offset: { + validator: $.num.optional.min(0), + default: 0 + }, + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Lookup note const note = await Note.findOne({ - _id: noteId + _id: ps.noteId }); if (note === null) { @@ -34,11 +49,11 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = i++; const p = await Note.findOne({ _id: id }); - if (i > offset) { + if (i > ps.offset) { conversation.push(p); } - if (conversation.length == limit) { + if (conversation.length == ps.limit) { return; } @@ -51,6 +66,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = await get(note.replyId); } - // Serialize res(await packMany(conversation, user)); }); diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 432561da38..9eff8c27bf 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform, transformMany } from '../../../../misc/cafy-id'; const ms = require('ms'); import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note'; import User, { ILocalUser, IUser } from '../../../../models/user'; @@ -24,84 +24,106 @@ export const meta = { kind: 'note-write', params: { - visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({ + visibility: { + validator: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']), default: 'public', desc: { 'ja-JP': '投稿の公開範囲' } - }), + }, - visibleUserIds: $.arr($.type(ID)).optional.unique().min(1).note({ + visibleUserIds: { + validator: $.arr($.type(ID)).optional.unique().min(1), + transform: transformMany, desc: { 'ja-JP': '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー' } - }), + }, - text: $.str.optional.nullable.pipe(isValidText).note({ - default: null, + text: { + validator: $.str.optional.nullable.pipe(isValidText), + default: null as any, desc: { 'ja-JP': '投稿内容' } - }), + }, - cw: $.str.optional.nullable.pipe(isValidCw).note({ + cw: { + validator: $.str.optional.nullable.pipe(isValidCw), desc: { 'ja-JP': 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。' } - }), + }, - viaMobile: $.bool.optional.note({ + viaMobile: { + validator: $.bool.optional, default: false, desc: { 'ja-JP': 'モバイルデバイスからの投稿か否か。' } - }), + }, - geo: $.obj({ - coordinates: $.arr().length(2) - .item(0, $.num.range(-180, 180)) - .item(1, $.num.range(-90, 90)), - altitude: $.num.nullable, - accuracy: $.num.nullable, - altitudeAccuracy: $.num.nullable, - heading: $.num.nullable.range(0, 360), - speed: $.num.nullable - }).optional.nullable.strict().note({ + geo: { + validator: $.obj({ + coordinates: $.arr().length(2) + .item(0, $.num.range(-180, 180)) + .item(1, $.num.range(-90, 90)), + altitude: $.num.nullable, + accuracy: $.num.nullable, + altitudeAccuracy: $.num.nullable, + heading: $.num.nullable.range(0, 360), + speed: $.num.nullable + }).optional.nullable.strict(), desc: { 'ja-JP': '位置情報' }, ref: 'geo' - }), + }, - fileIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({ + fileIds: { + validator: $.arr($.type(ID)).optional.unique().range(1, 4), + transform: transformMany, desc: { 'ja-JP': '添付するファイル' } - }), + }, - mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({ + mediaIds: { + validator: $.arr($.type(ID)).optional.unique().range(1, 4), + transform: transformMany, desc: { 'ja-JP': '添付するファイル (このパラメータは廃止予定です。代わりに fileIds を使ってください。)' } - }), + }, - renoteId: $.type(ID).optional.note({ + replyId: { + validator: $.type(ID).optional, + transform: transform, + desc: { + 'ja-JP': '返信対象' + } + }, + + renoteId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': 'Renote対象' } - }), + }, - poll: $.obj({ - choices: $.arr($.str) - .unique() - .range(2, 10) - .each(c => c.length > 0 && c.length < 50) - }).optional.strict().note({ + poll: { + validator: $.obj({ + choices: $.arr($.str) + .unique() + .range(2, 10) + .each(c => c.length > 0 && c.length < 50) + }).optional.strict(), desc: { 'ja-JP': 'アンケート' }, ref: 'poll' - }) + } }, res: { @@ -117,15 +139,12 @@ export const meta = { } }; -/** - * Create a note - */ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { const [ps, psErr] = getParams(meta, params); if (psErr) return rej(psErr); let visibleUsers: IUser[] = []; - if (ps.visibleUserIds !== undefined) { + if (ps.visibleUserIds) { visibleUsers = await Promise.all(ps.visibleUserIds.map(id => User.findOne({ _id: id }))); @@ -145,7 +164,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( } let renote: INote = null; - if (ps.renoteId !== undefined) { + if (ps.renoteId != null) { // Fetch renote to note renote = await Note.findOne({ _id: ps.renoteId @@ -158,15 +177,11 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( } } - // Get 'replyId' parameter - const [replyId, replyIdErr] = $.type(ID).optional.get(params.replyId); - if (replyIdErr) return rej('invalid replyId'); - let reply: INote = null; - if (replyId !== undefined) { + if (ps.replyId != null) { // Fetch reply reply = await Note.findOne({ - _id: replyId + _id: ps.replyId }); if (reply === null) { @@ -188,7 +203,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( } // テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー - if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) { + if ((ps.text == null) && files === null && renote === null && ps.poll == null) { return rej('text, fileIds, renoteId or poll is required'); } diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts index 160d5c4cf6..580cb344e1 100644 --- a/src/server/api/endpoints/notes/delete.ts +++ b/src/server/api/endpoints/notes/delete.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import deleteNote from '../../../../services/note/delete'; import User, { ILocalUser } from '../../../../models/user'; @@ -17,12 +17,14 @@ export const meta = { kind: 'note-write', params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿のID', 'en-US': 'Target note ID.' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts index 76673e248a..e489c77761 100644 --- a/src/server/api/endpoints/notes/favorites/create.ts +++ b/src/server/api/endpoints/notes/favorites/create.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; @@ -17,12 +17,14 @@ export const meta = { kind: 'favorite-write', params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿のID', 'en-US': 'Target note ID.' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts index 70e1ca8ccf..ac1b35d194 100644 --- a/src/server/api/endpoints/notes/favorites/delete.ts +++ b/src/server/api/endpoints/notes/favorites/delete.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id'; import Favorite from '../../../../../models/favorite'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; @@ -17,12 +17,14 @@ export const meta = { kind: 'favorite-write', params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿のID', 'en-US': 'Target note ID.' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts index 363170ead6..c031308824 100644 --- a/src/server/api/endpoints/notes/featured.ts +++ b/src/server/api/endpoints/notes/featured.ts @@ -13,12 +13,13 @@ export const meta = { requireCredential: false, params: { - limit: $.num.optional.range(1, 30).note({ + limit: { + validator: $.num.optional.range(1, 30), default: 10, desc: { 'ja-JP': '最大数' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 8a6c848943..fa7a76f12e 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { packMany } from '../../../../models/note'; @@ -12,29 +12,42 @@ export const meta = { }, params: { - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'ファイルが添付された投稿に限定するか否か' } - }), + }, - mediaOnly: $.bool.optional.note({ + mediaOnly: { + validator: $.bool.optional, desc: { 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), + }, - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10 - }), + }, - sinceId: $.type(ID).optional.note({}), + sinceId: { + validator: $.type(ID).optional, + transform: transform, + }, - untilId: $.type(ID).optional.note({}), + untilId: { + validator: $.type(ID).optional, + transform: transform, + }, - sinceDate: $.num.optional.note({}), + sinceDate: { + validator: $.num.optional + }, - untilDate: $.num.optional.note({}), + untilDate: { + validator: $.num.optional + }, } }; diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index b2ea9c60ac..0008144823 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { getFriends } from '../../common/get-friends'; @@ -13,69 +13,81 @@ export const meta = { }, params: { - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10, desc: { 'ja-JP': '最大数' } - }), + }, - sinceId: $.type(ID).optional.note({ + sinceId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します' } - }), + }, - untilId: $.type(ID).optional.note({ + untilId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します' } - }), + }, - sinceDate: $.num.optional.note({ + sinceDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - untilDate: $.num.optional.note({ + untilDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - includeMyRenotes: $.bool.optional.note({ + includeMyRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': '自分の行ったRenoteを含めるかどうか' } - }), + }, - includeRenotedMyNotes: $.bool.optional.note({ + includeRenotedMyNotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされた自分の投稿を含めるかどうか' } - }), + }, - includeLocalRenotes: $.bool.optional.note({ + includeLocalRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか' } - }), + }, - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' } - }), + }, - mediaOnly: $.bool.optional.note({ + mediaOnly: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), + }, } }; diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 510564129c..78ddf00626 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { packMany } from '../../../../models/note'; @@ -12,42 +12,57 @@ export const meta = { }, params: { - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'ファイルが添付された投稿に限定するか否か' } - }), + }, - mediaOnly: $.bool.optional.note({ + mediaOnly: { + validator: $.bool.optional, desc: { 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), + }, - fileType: $.arr($.str).optional.note({ + fileType: { + validator: $.arr($.str).optional, desc: { 'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します' } - }), + }, - excludeNsfw: $.bool.optional.note({ + excludeNsfw: { + validator: $.bool.optional, default: false, desc: { 'ja-JP': 'true にすると、NSFW指定されたファイルを除外します(fileTypeが指定されている場合のみ有効)' } - }), + }, - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10 - }), + }, - sinceId: $.type(ID).optional.note({}), + sinceId: { + validator: $.type(ID).optional, + transform: transform, + }, - untilId: $.type(ID).optional.note({}), + untilId: { + validator: $.type(ID).optional, + transform: transform, + }, - sinceDate: $.num.optional.note({}), + sinceDate: { + validator: $.num.optional, + }, - untilDate: $.num.optional.note({}), + untilDate: { + validator: $.num.optional, + }, } }; diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index c66421284c..3fc3977075 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import { getFriendIds } from '../../common/get-friends'; import { packMany } from '../../../../models/note'; @@ -15,22 +15,29 @@ export const meta = { requireCredential: true, params: { - following: $.bool.optional.note({ + following: { + validator: $.bool.optional, default: false - }), + }, - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10 - }), + }, - sinceId: $.type(ID).optional.note({ - }), + sinceId: { + validator: $.type(ID).optional, + transform: transform, + }, - untilId: $.type(ID).optional.note({ - }), + untilId: { + validator: $.type(ID).optional, + transform: transform, + }, - visibility: $.str.optional.note({ - }), + visibility: { + validator: $.str.optional, + }, } }; diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts index 3b78d62fd3..32dcefec7b 100644 --- a/src/server/api/endpoints/notes/polls/vote.ts +++ b/src/server/api/endpoints/notes/polls/vote.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id'; import Vote from '../../../../../models/poll-vote'; import Note from '../../../../../models/note'; import Watching from '../../../../../models/note-watching'; @@ -6,6 +6,7 @@ import watch from '../../../../../services/note/watch'; import { publishNoteStream } from '../../../../../stream'; import notify from '../../../../../notify'; import { ILocalUser } from '../../../../../models/user'; +import getParams from '../../../get-params'; export const meta = { desc: { @@ -15,17 +16,27 @@ export const meta = { requireCredential: true, - kind: 'vote-write' + kind: 'vote-write', + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + }, + + choice: { + validator: $.num + }, + } }; export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Get votee const note = await Note.findOne({ - _id: noteId + _id: ps.noteId }); if (note === null) { @@ -36,12 +47,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = return rej('poll not found'); } - // Get 'choice' parameter - const [choice, choiceError] = - $.num - .pipe(c => note.poll.choices.some(x => x.id == c)) - .get(params.choice); - if (choiceError) return rej('invalid choice param'); + if (!note.poll.choices.some(x => x.id == ps.choice)) return rej('invalid choice param'); // if already voted const exist = await Vote.findOne({ @@ -58,14 +64,14 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = createdAt: new Date(), noteId: note._id, userId: user._id, - choice: choice + choice: ps.choice }); // Send response res(); const inc: any = {}; - inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == choice)}.votes`] = 1; + inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == ps.choice)}.votes`] = 1; // Increment votes count await Note.update({ _id: note._id }, { @@ -73,14 +79,14 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = }); publishNoteStream(note._id, 'pollVoted', { - choice: choice, + choice: ps.choice, userId: user._id.toHexString() }); // Notify notify(note.userId, user._id, 'poll_vote', { noteId: note._id, - choice: choice + choice: ps.choice }); // Fetch watchers @@ -99,7 +105,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = watchers.forEach(watcher => { notify(watcher.userId, user._id, 'poll_vote', { noteId: note._id, - choice: choice + choice: ps.choice }); }); }); diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts index 5f23068cd6..1ab5afaba1 100644 --- a/src/server/api/endpoints/notes/reactions.ts +++ b/src/server/api/endpoints/notes/reactions.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Reaction, { pack } from '../../../../models/note-reaction'; import { ILocalUser } from '../../../../models/user'; @@ -13,26 +13,34 @@ export const meta = { requireCredential: false, params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿のID', 'en-US': 'The ID of the target note' } - }), + }, - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10 - }), + }, - offset: $.num.optional.note({ + offset: { + validator: $.num.optional, default: 0 - }), + }, - sinceId: $.type(ID).optional.note({ - }), + sinceId: { + validator: $.type(ID).optional, + transform: transform, + }, - untilId: $.type(ID).optional.note({ - }), + untilId: { + validator: $.type(ID).optional, + transform: transform, + }, } }; diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts index aa9ab07384..f2b06473a5 100644 --- a/src/server/api/endpoints/notes/reactions/create.ts +++ b/src/server/api/endpoints/notes/reactions/create.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id'; import Note from '../../../../../models/note'; import create from '../../../../../services/note/reaction/create'; import { validateReaction } from '../../../../../models/note-reaction'; @@ -18,17 +18,20 @@ export const meta = { kind: 'reaction-write', params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿' } - }), + }, - reaction: $.str.pipe(validateReaction.ok).note({ + reaction: { + validator: $.str.pipe(validateReaction.ok), desc: { 'ja-JP': 'リアクションの種類' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts index 598eb65364..2a2577dfe6 100644 --- a/src/server/api/endpoints/notes/reactions/delete.ts +++ b/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,7 +1,8 @@ -import $ from 'cafy'; import ID from '../../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id'; import Reaction from '../../../../../models/note-reaction'; import Note from '../../../../../models/note'; import { ILocalUser } from '../../../../../models/user'; +import getParams from '../../../get-params'; export const meta = { desc: { @@ -11,17 +12,23 @@ export const meta = { requireCredential: true, - kind: 'reaction-write' + kind: 'reaction-write', + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + }, + } }; export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Fetch unreactee const note = await Note.findOne({ - _id: noteId + _id: ps.noteId }); if (note === null) { @@ -48,7 +55,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = } }); - // Send response res(); const dec: any = {}; diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts new file mode 100644 index 0000000000..ff926806eb --- /dev/null +++ b/src/server/api/endpoints/notes/renotes.ts @@ -0,0 +1,81 @@ +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; +import Note, { packMany } from '../../../../models/note'; +import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; + +export const meta = { + desc: { + 'ja-JP': '指定した投稿のRenote一覧を取得します。', + 'en-US': 'Show a renotes of a note.' + }, + + requireCredential: false, + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + }, + + limit: { + validator: $.num.optional.range(1, 100), + default: 10 + }, + + sinceId: { + validator: $.type(ID).optional, + transform: transform, + }, + + untilId: { + validator: $.type(ID).optional, + transform: transform, + } + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); + + // Check if both of sinceId and untilId is specified + if (ps.sinceId && ps.untilId) { + return rej('cannot set sinceId and untilId'); + } + + // Lookup note + const note = await Note.findOne({ + _id: ps.noteId + }); + + if (note === null) { + return rej('note not found'); + } + + const sort = { + _id: -1 + }; + + const query = { + renoteId: note._id + } as any; + + if (ps.sinceId) { + sort._id = 1; + query._id = { + $gt: ps.sinceId + }; + } else if (ps.untilId) { + query._id = { + $lt: ps.untilId + }; + } + + const renotes = await Note + .find(query, { + limit: ps.limit, + sort: sort + }); + + res(await packMany(renotes, user)); +}); diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts index b2f8f94f69..86a75c1cab 100644 --- a/src/server/api/endpoints/notes/replies.ts +++ b/src/server/api/endpoints/notes/replies.ts @@ -1,34 +1,48 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note, { packMany } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; -/** - * Get replies of a note - */ -export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); +export const meta = { + desc: { + 'ja-JP': '指定した投稿への返信を取得します。', + 'en-US': 'Get replies of a note.' + }, + + requireCredential: false, + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + }, - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) return rej('invalid limit param'); + limit: { + validator: $.num.optional.range(1, 100), + default: 10 + }, - // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); - if (offsetErr) return rej('invalid offset param'); + offset: { + validator: $.num.optional.min(0), + default: 0 + }, + } +}; + +export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) return rej(psErr); // Lookup note const note = await Note.findOne({ - _id: noteId + _id: ps.noteId }); if (note === null) { return rej('note not found'); } - const ids = (note._replyIds || []).slice(offset, offset + limit); + const ids = (note._replyIds || []).slice(ps.offset, ps.offset + ps.limit); - // Serialize res(await packMany(ids, user)); }); diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts deleted file mode 100644 index 2c6e1a499f..0000000000 --- a/src/server/api/endpoints/notes/reposts.ts +++ /dev/null @@ -1,66 +0,0 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; -import Note, { packMany } from '../../../../models/note'; -import { ILocalUser } from '../../../../models/user'; - -/** - * Show a renotes of a note - */ -export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => { - // Get 'noteId' parameter - const [noteId, noteIdErr] = $.type(ID).get(params.noteId); - if (noteIdErr) return rej('invalid noteId param'); - - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) return rej('invalid limit param'); - - // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); - if (sinceIdErr) return rej('invalid sinceId param'); - - // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); - if (untilIdErr) return rej('invalid untilId param'); - - // Check if both of sinceId and untilId is specified - if (sinceId && untilId) { - return rej('cannot set sinceId and untilId'); - } - - // Lookup note - const note = await Note.findOne({ - _id: noteId - }); - - if (note === null) { - return rej('note not found'); - } - - // Construct query - const sort = { - _id: -1 - }; - const query = { - renoteId: note._id - } as any; - if (sinceId) { - sort._id = 1; - query._id = { - $gt: sinceId - }; - } else if (untilId) { - query._id = { - $lt: untilId - }; - } - - // Issue query - const renotes = await Note - .find(query, { - limit: limit, - sort: sort - }); - - // Serialize - res(await packMany(renotes, user)); -}); diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts index e7fa15f768..99a6dce834 100644 --- a/src/server/api/endpoints/notes/search_by_tag.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -1,11 +1,10 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; -import User, { ILocalUser } from '../../../../models/user'; +import { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; import { getFriendIds } from '../../common/get-friends'; import { packMany } from '../../../../models/note'; import getParams from '../../get-params'; -import { erase } from '../../../../prelude/array'; export const meta = { desc: { @@ -13,99 +12,94 @@ export const meta = { }, params: { - tag: $.str.optional.note({ + tag: { + validator: $.str.optional, desc: { 'ja-JP': 'タグ' } - }), + }, - query: $.arr($.arr($.str)).optional.note({ + query: { + validator: $.arr($.arr($.str)).optional, desc: { 'ja-JP': 'クエリ' } - }), + }, - includeUserIds: $.arr($.type(ID)).optional.note({ - default: [] - }), + following: { + validator: $.bool.optional.nullable, + default: null as any + }, - excludeUserIds: $.arr($.type(ID)).optional.note({ - default: [] - }), - - includeUserUsernames: $.arr($.str).optional.note({ - default: [] - }), - - excludeUserUsernames: $.arr($.str).optional.note({ - default: [] - }), - - following: $.bool.optional.nullable.note({ - default: null - }), - - mute: $.str.optional.note({ + mute: { + validator: $.str.optional, default: 'mute_all' - }), - - reply: $.bool.optional.nullable.note({ - default: null, + }, + reply: { + validator: $.bool.optional.nullable, + default: null as any, desc: { 'ja-JP': '返信に限定するか否か' } - }), - - renote: $.bool.optional.nullable.note({ - default: null, + }, + renote: { + validator: $.bool.optional.nullable, + default: null as any, desc: { 'ja-JP': 'Renoteに限定するか否か' } - }), + }, - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' } - }), - - media: $.bool.optional.nullable.note({ - default: null, + }, + media: { + validator: $.bool.optional.nullable, + default: null as any, desc: { 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), - - poll: $.bool.optional.nullable.note({ - default: null, + }, + poll: { + validator: $.bool.optional.nullable, + default: null as any, desc: { 'ja-JP': 'アンケートが添付された投稿に限定するか否か' } - }), + }, - untilId: $.type(ID).optional.note({ + untilId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します' } - }), + }, - sinceDate: $.num.optional.note({ - }), + sinceDate: { + validator: $.num.optional, + }, - untilDate: $.num.optional.note({ - }), + untilDate: { + validator: $.num.optional, + }, - offset: $.num.optional.min(0).note({ + offset: { + validator: $.num.optional.min(0), default: 0 - }), + }, - limit: $.num.optional.range(1, 30).note({ + limit: { + validator: $.num.optional.range(1, 30), default: 10 - }), + }, } }; @@ -113,28 +107,6 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => const [ps, psErr] = getParams(meta, params); if (psErr) return rej(psErr); - if (ps.includeUserUsernames != null) { - const ids = erase(null, await Promise.all(ps.includeUserUsernames.map(async (username) => { - const _user = await User.findOne({ - usernameLower: username.toLowerCase() - }); - return _user ? _user._id : null; - }))); - - ids.forEach(id => ps.includeUserIds.push(id)); - } - - if (ps.excludeUserUsernames != null) { - const ids = erase(null, await Promise.all(ps.excludeUserUsernames.map(async (username) => { - const _user = await User.findOne({ - usernameLower: username.toLowerCase() - }); - return _user ? _user._id : null; - }))); - - ids.forEach(id => ps.excludeUserIds.push(id)); - } - const q: any = { $and: [ps.tag ? { tagsLower: ps.tag.toLowerCase() @@ -150,20 +122,6 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => const push = (x: any) => q.$and.push(x); - if (ps.includeUserIds && ps.includeUserIds.length != 0) { - push({ - userId: { - $in: ps.includeUserIds - } - }); - } else if (ps.excludeUserIds && ps.excludeUserIds.length != 0) { - push({ - userId: { - $nin: ps.excludeUserIds - } - }); - } - if (ps.following != null && me != null) { const ids = await getFriendIds(me._id, false); push({ diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts index e84a948c97..8b426c0053 100644 --- a/src/server/api/endpoints/notes/show.ts +++ b/src/server/api/endpoints/notes/show.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note, { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; @@ -14,12 +14,14 @@ export const meta = { requireCredential: false, params: { - noteId: $.type(ID).note({ + noteId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': '対象の投稿のID', 'en-US': 'Target note ID.' } - }) + } } }; diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 31a4978407..8834645fc8 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { getFriends } from '../../common/get-friends'; @@ -16,69 +16,81 @@ export const meta = { requireCredential: true, params: { - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10, desc: { 'ja-JP': '最大数' } - }), + }, - sinceId: $.type(ID).optional.note({ + sinceId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します' } - }), + }, - untilId: $.type(ID).optional.note({ + untilId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します' } - }), + }, - sinceDate: $.num.optional.note({ + sinceDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - untilDate: $.num.optional.note({ + untilDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - includeMyRenotes: $.bool.optional.note({ + includeMyRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': '自分の行ったRenoteを含めるかどうか' } - }), + }, - includeRenotedMyNotes: $.bool.optional.note({ + includeRenotedMyNotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされた自分の投稿を含めるかどうか' } - }), + }, - includeLocalRenotes: $.bool.optional.note({ + includeLocalRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか' } - }), + }, - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' } - }), + }, - mediaOnly: $.bool.optional.note({ + mediaOnly: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), + }, } }; diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index 7dddc4834e..3bdcc6c121 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -1,4 +1,4 @@ -import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { packMany } from '../../../../models/note'; @@ -15,75 +15,89 @@ export const meta = { requireCredential: true, params: { - listId: $.type(ID).note({ + listId: { + validator: $.type(ID), + transform: transform, desc: { 'ja-JP': 'リストのID' } - }), + }, - limit: $.num.optional.range(1, 100).note({ + limit: { + validator: $.num.optional.range(1, 100), default: 10, desc: { 'ja-JP': '最大数' } - }), + }, - sinceId: $.type(ID).optional.note({ + sinceId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します' } - }), + }, - untilId: $.type(ID).optional.note({ + untilId: { + validator: $.type(ID).optional, + transform: transform, desc: { 'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します' } - }), + }, - sinceDate: $.num.optional.note({ + sinceDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - untilDate: $.num.optional.note({ + untilDate: { + validator: $.num.optional, desc: { 'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' } - }), + }, - includeMyRenotes: $.bool.optional.note({ + includeMyRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': '自分の行ったRenoteを含めるかどうか' } - }), + }, - includeRenotedMyNotes: $.bool.optional.note({ + includeRenotedMyNotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされた自分の投稿を含めるかどうか' } - }), + }, - includeLocalRenotes: $.bool.optional.note({ + includeLocalRenotes: { + validator: $.bool.optional, default: true, desc: { 'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか' } - }), + }, - withFiles: $.bool.optional.note({ + withFiles: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' } - }), + }, - mediaOnly: $.bool.optional.note({ + mediaOnly: { + validator: $.bool.optional, desc: { 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } - }), + }, } }; |