From a1b82e97230eab994c06fc7c902e71539664d3d7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 5 Sep 2018 19:32:46 +0900 Subject: #2620 --- src/server/api/endpoints/notes/create.ts | 23 ++++++++++++++-------- src/server/api/endpoints/notes/global-timeline.ts | 10 +++++----- src/server/api/endpoints/notes/hybrid-timeline.ts | 12 +++++------ src/server/api/endpoints/notes/local-timeline.ts | 10 +++++----- src/server/api/endpoints/notes/search_by_tag.ts | 6 +++--- src/server/api/endpoints/notes/timeline.ts | 12 +++++------ src/server/api/endpoints/notes/trend.ts | 2 +- .../api/endpoints/notes/user-list-timeline.ts | 12 +++++------ 8 files changed, 47 insertions(+), 40 deletions(-) (limited to 'src/server/api/endpoints/notes') diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 04f5f7562e..47b53c943b 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -71,9 +71,15 @@ export const meta = { ref: 'geo' }), + fileIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({ + desc: { + 'ja-JP': '添付するファイル' + } + }), + mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({ desc: { - 'ja-JP': '添付するメディア' + 'ja-JP': '添付するファイル (このパラメータは廃止予定です。代わりに fileIds を使ってください。)' } }), @@ -124,15 +130,16 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( } let files: IDriveFile[] = []; - if (ps.mediaIds !== undefined) { + const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null; + if (fileIds != null) { // Fetch files // forEach だと途中でエラーなどがあっても return できないので // 敢えて for を使っています。 - for (const mediaId of ps.mediaIds) { + for (const fileId of fileIds) { // Fetch file // SELECT _id const entity = await DriveFile.findOne({ - _id: mediaId, + _id: fileId, 'metadata.userId': user._id }); @@ -155,7 +162,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( if (renote == null) { return rej('renoteee is not found'); - } else if (renote.renoteId && !renote.text && !renote.mediaIds) { + } else if (renote.renoteId && !renote.text && !renote.fileIds) { return rej('cannot renote to renote'); } } @@ -176,7 +183,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async ( } // 返信対象が引用でないRenoteだったらエラー - if (reply.renoteId && !reply.text && !reply.mediaIds) { + if (reply.renoteId && !reply.text && !reply.fileIds) { return rej('cannot reply to renote'); } } @@ -191,13 +198,13 @@ 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) { - return rej('text, mediaIds, renoteId or poll is required'); + return rej('text, fileIds, renoteId or poll is required'); } // 投稿を作成 const note = await create(user, { createdAt: new Date(), - media: files, + files: files, poll: ps.poll, text: ps.text, reply, diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 8f7233e308..554245a0f4 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -33,9 +33,9 @@ export default async (params: any, user: ILocalUser) => { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly); - if (mediaOnlyErr) throw 'invalid mediaOnly param'; + // Get 'withFiles' parameter + const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles); + if (withFilesErr) throw 'invalid withFiles param'; // ミュートしているユーザーを取得 const mutedUserIds = user ? (await Mute.find({ @@ -68,8 +68,8 @@ export default async (params: any, user: ILocalUser) => { }; } - if (mediaOnly) { - query.mediaIds = { $exists: true, $ne: [] }; + if (withFiles) { + query.fileIds = { $exists: true, $ne: [] }; } if (sinceId) { diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index 2dbb1190c1..1060792683 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -66,7 +66,7 @@ export const meta = { } }), - mediaOnly: $.bool.optional.note({ + withFiles: $.bool.optional.note({ desc: { 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' } @@ -164,7 +164,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -180,7 +180,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -196,16 +196,16 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] }); } - if (ps.mediaOnly) { + if (ps.withFiles) { query.$and.push({ - mediaIds: { $exists: true, $ne: [] } + fileIds: { $exists: true, $ne: [] } }); } diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index bbcc6303ca..018e636ab5 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -33,9 +33,9 @@ export default async (params: any, user: ILocalUser) => { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - // Get 'mediaOnly' parameter - const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly); - if (mediaOnlyErr) throw 'invalid mediaOnly param'; + // Get 'withFiles' parameter + const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles); + if (withFilesErr) throw 'invalid withFiles param'; // ミュートしているユーザーを取得 const mutedUserIds = user ? (await Mute.find({ @@ -69,8 +69,8 @@ export default async (params: any, user: ILocalUser) => { }; } - if (mediaOnly) { - query.mediaIds = { $exists: true, $ne: [] }; + if (withFiles) { + query.fileIds = { $exists: true, $ne: [] }; } if (sinceId) { diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts index e092275fe8..317a0726d3 100644 --- a/src/server/api/endpoints/notes/search_by_tag.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -247,7 +247,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => if (media != null) { if (media) { push({ - mediaIds: { + fileIds: { $exists: true, $ne: null } @@ -255,11 +255,11 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } else { push({ $or: [{ - mediaIds: { + fileIds: { $exists: false } }, { - mediaIds: null + fileIds: null }] }); } diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 099bf2010b..145f648c56 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -67,7 +67,7 @@ export const meta = { } }), - mediaOnly: $.bool.optional.note({ + withFiles: $.bool.optional.note({ desc: { 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' } @@ -154,7 +154,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -170,7 +170,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -186,16 +186,16 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] }); } - if (ps.mediaOnly) { + if (ps.withFiles) { query.$and.push({ - mediaIds: { $exists: true, $ne: [] } + fileIds: { $exists: true, $ne: [] } }); } diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts index 7a0a098f28..9f55ed3243 100644 --- a/src/server/api/endpoints/notes/trend.ts +++ b/src/server/api/endpoints/notes/trend.ts @@ -52,7 +52,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = } if (media != undefined) { - query.mediaIds = media ? { $exists: true, $ne: null } : null; + query.fileIds = media ? { $exists: true, $ne: null } : null; } if (poll != undefined) { diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index a7b43014ed..e00a7de371 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -73,7 +73,7 @@ export const meta = { } }), - mediaOnly: $.bool.optional.note({ + withFiles: $.bool.optional.note({ desc: { 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' } @@ -160,7 +160,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -176,7 +176,7 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] @@ -192,16 +192,16 @@ export default async (params: any, user: ILocalUser) => { }, { text: { $ne: null } }, { - mediaIds: { $ne: [] } + fileIds: { $ne: [] } }, { poll: { $ne: null } }] }); } - if (ps.mediaOnly) { + if (ps.withFiles) { query.$and.push({ - mediaIds: { $exists: true, $ne: [] } + fileIds: { $exists: true, $ne: [] } }); } -- cgit v1.2.3-freya From 37058e3480041a922ac5c193e4cc3bc29fd663ae Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 5 Sep 2018 19:35:57 +0900 Subject: Fix parameter name --- src/server/api/endpoints/notes/search_by_tag.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/server/api/endpoints/notes') diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts index 317a0726d3..f982dc01e9 100644 --- a/src/server/api/endpoints/notes/search_by_tag.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -45,9 +45,9 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => const [renote = null, renoteErr] = $.bool.optional.nullable.get(params.renote); if (renoteErr) return rej('invalid renote param'); - // Get 'media' parameter - const [media = null, mediaErr] = $.bool.optional.nullable.get(params.media); - if (mediaErr) return rej('invalid media param'); + // Get 'withFiles' parameter + const [withFiles = null, withFilesErr] = $.bool.optional.nullable.get(params.withFiles); + if (withFilesErr) return rej('invalid withFiles param'); // Get 'poll' parameter const [poll = null, pollErr] = $.bool.optional.nullable.get(params.poll); @@ -244,8 +244,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } - if (media != null) { - if (media) { + if (withFiles != null) { + if (withFiles) { push({ fileIds: { $exists: true, -- cgit v1.2.3-freya From b5ff2abdb9ee0c086c8970c738cce5d61761f8f5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 5 Sep 2018 23:55:51 +0900 Subject: 互換性のためのコードを追加 & #2623 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/api/endpoints/notes.ts | 128 +++++++------- src/server/api/endpoints/notes/global-timeline.ts | 77 +++++---- src/server/api/endpoints/notes/hybrid-timeline.ts | 12 +- src/server/api/endpoints/notes/local-timeline.ts | 77 +++++---- src/server/api/endpoints/notes/search_by_tag.ts | 185 ++++++++++++--------- src/server/api/endpoints/notes/timeline.ts | 12 +- .../api/endpoints/notes/user-list-timeline.ts | 12 +- src/server/api/endpoints/users/notes.ts | 178 +++++++++++++------- 8 files changed, 416 insertions(+), 265 deletions(-) (limited to 'src/server/api/endpoints/notes') diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts index 4d15e9483f..5fa58d19de 100644 --- a/src/server/api/endpoints/notes.ts +++ b/src/server/api/endpoints/notes.ts @@ -1,51 +1,65 @@ -/** - * Module dependencies - */ import $ from 'cafy'; import ID from '../../../misc/cafy-id'; import Note, { pack } from '../../../models/note'; +import getParams from '../get-params'; + +export const meta = { + desc: { + 'ja-JP': '投稿を取得します。' + }, + + params: { + local: $.bool.optional.note({ + desc: { + 'ja-JP': 'ローカルの投稿に限定するか否か' + } + }), + + reply: $.bool.optional.note({ + desc: { + 'ja-JP': '返信に限定するか否か' + } + }), + + renote: $.bool.optional.note({ + desc: { + 'ja-JP': 'Renoteに限定するか否か' + } + }), + + withFiles: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か' + } + }), + + media: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' + } + }), + + poll: $.bool.optional.note({ + desc: { + 'ja-JP': 'アンケートが添付された投稿に限定するか否か' + } + }), + + limit: $.num.optional.range(1, 100).note({ + default: 10 + }), + + sinceId: $.type(ID).optional.note({}), + + untilId: $.type(ID).optional.note({}), + } +}; -/** - * Get all notes - */ export default (params: any) => new Promise(async (res, rej) => { - // Get 'local' parameter - const [local, localErr] = $.bool.optional.get(params.local); - if (localErr) return rej('invalid local param'); - - // Get 'reply' parameter - const [reply, replyErr] = $.bool.optional.get(params.reply); - if (replyErr) return rej('invalid reply param'); - - // Get 'renote' parameter - const [renote, renoteErr] = $.bool.optional.get(params.renote); - if (renoteErr) return rej('invalid renote param'); - - // Get 'files' parameter - const [files, filesErr] = $.bool.optional.get(params.files); - if (filesErr) return rej('invalid files param'); - - // Get 'poll' parameter - const [poll, pollErr] = $.bool.optional.get(params.poll); - if (pollErr) return rej('invalid poll param'); - - // Get 'bot' parameter - //const [bot, botErr] = $.bool.optional.get(params.bot); - //if (botErr) return rej('invalid bot 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'); + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; // Check if both of sinceId and untilId is specified - if (sinceId && untilId) { + if (ps.sinceId && ps.untilId) { return rej('cannot set sinceId and untilId'); } @@ -56,35 +70,37 @@ export default (params: any) => new Promise(async (res, rej) => { const query = { visibility: 'public' } as any; - if (sinceId) { + if (ps.sinceId) { sort._id = 1; query._id = { - $gt: sinceId + $gt: ps.sinceId }; - } else if (untilId) { + } else if (ps.untilId) { query._id = { - $lt: untilId + $lt: ps.untilId }; } - if (local) { + if (ps.local) { query['_user.host'] = null; } - if (reply != undefined) { - query.replyId = reply ? { $exists: true, $ne: null } : null; + if (ps.reply != undefined) { + query.replyId = ps.reply ? { $exists: true, $ne: null } : null; } - if (renote != undefined) { - query.renoteId = renote ? { $exists: true, $ne: null } : null; + if (ps.renote != undefined) { + query.renoteId = ps.renote ? { $exists: true, $ne: null } : null; } - if (files != undefined) { - query.fileIds = files ? { $exists: true, $ne: null } : []; + const withFiles = ps.withFiles != undefined ? ps.withFiles : ps.media; + + if (withFiles) { + query.fileIds = withFiles ? { $exists: true, $ne: null } : []; } - if (poll != undefined) { - query.poll = poll ? { $exists: true, $ne: null } : null; + if (ps.poll != undefined) { + query.poll = ps.poll ? { $exists: true, $ne: null } : null; } // TODO @@ -95,7 +111,7 @@ export default (params: any) => new Promise(async (res, rej) => { // Issue query const notes = await Note .find(query, { - limit: limit, + limit: ps.limit, sort: sort }); diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 554245a0f4..e70fc5d76f 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -3,40 +3,49 @@ import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; -/** - * Get timeline of global - */ -export default async (params: any, user: ILocalUser) => { - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) throw 'invalid limit param'; +export const meta = { + desc: { + 'ja-JP': 'グローバルタイムラインを取得します。' + }, + + params: { + withFiles: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' + } + }), + + limit: $.num.optional.range(1, 100).note({ + default: 10 + }), + + sinceId: $.type(ID).optional.note({}), - // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); - if (sinceIdErr) throw 'invalid sinceId param'; + untilId: $.type(ID).optional.note({}), - // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); - if (untilIdErr) throw 'invalid untilId param'; + sinceDate: $.num.optional.note({}), - // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); - if (sinceDateErr) throw 'invalid sinceDate param'; + untilDate: $.num.optional.note({}), + } +}; - // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); - if (untilDateErr) throw 'invalid untilDate param'; +export default async (params: any, user: ILocalUser) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) { + if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - // Get 'withFiles' parameter - const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles); - if (withFilesErr) throw 'invalid withFiles param'; - // ミュートしているユーザーを取得 const mutedUserIds = user ? (await Mute.find({ muterId: user._id @@ -68,27 +77,29 @@ export default async (params: any, user: ILocalUser) => { }; } + const withFiles = ps.withFiles != null ? ps.withFiles : ps.mediaOnly; + if (withFiles) { query.fileIds = { $exists: true, $ne: [] }; } - if (sinceId) { + if (ps.sinceId) { sort._id = 1; query._id = { - $gt: sinceId + $gt: ps.sinceId }; - } else if (untilId) { + } else if (ps.untilId) { query._id = { - $lt: untilId + $lt: ps.untilId }; - } else if (sinceDate) { + } else if (ps.sinceDate) { sort._id = 1; query.createdAt = { - $gt: new Date(sinceDate) + $gt: new Date(ps.sinceDate) }; - } else if (untilDate) { + } else if (ps.untilDate) { query.createdAt = { - $lt: new Date(untilDate) + $lt: new Date(ps.untilDate) }; } //#endregion @@ -96,7 +107,7 @@ export default async (params: any, user: ILocalUser) => { // Issue query const timeline = await Note .find(query, { - limit: limit, + limit: ps.limit, sort: sort }); diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index 1060792683..16cec86797 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -7,8 +7,6 @@ import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; export const meta = { - name: 'notes/hybrid-timeline', - desc: { 'ja-JP': 'ハイブリッドタイムラインを取得します。' }, @@ -68,7 +66,13 @@ export const meta = { withFiles: $.bool.optional.note({ desc: { - 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } }), } @@ -203,7 +207,7 @@ export default async (params: any, user: ILocalUser) => { }); } - if (ps.withFiles) { + if (ps.withFiles || ps.mediaOnly) { query.$and.push({ fileIds: { $exists: true, $ne: [] } }); diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 018e636ab5..2458a70556 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -3,40 +3,49 @@ import Note from '../../../../models/note'; import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; -/** - * Get timeline of local - */ -export default async (params: any, user: ILocalUser) => { - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) throw 'invalid limit param'; +export const meta = { + desc: { + 'ja-JP': 'ローカルタイムラインを取得します。' + }, + + params: { + withFiles: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' + } + }), + + limit: $.num.optional.range(1, 100).note({ + default: 10 + }), + + sinceId: $.type(ID).optional.note({}), - // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId); - if (sinceIdErr) throw 'invalid sinceId param'; + untilId: $.type(ID).optional.note({}), - // Get 'untilId' parameter - const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId); - if (untilIdErr) throw 'invalid untilId param'; + sinceDate: $.num.optional.note({}), - // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); - if (sinceDateErr) throw 'invalid sinceDate param'; + untilDate: $.num.optional.note({}), + } +}; - // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); - if (untilDateErr) throw 'invalid untilDate param'; +export default async (params: any, user: ILocalUser) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) { + if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - // Get 'withFiles' parameter - const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles); - if (withFilesErr) throw 'invalid withFiles param'; - // ミュートしているユーザーを取得 const mutedUserIds = user ? (await Mute.find({ muterId: user._id @@ -69,27 +78,29 @@ export default async (params: any, user: ILocalUser) => { }; } + const withFiles = ps.withFiles != null ? ps.withFiles : ps.mediaOnly; + if (withFiles) { query.fileIds = { $exists: true, $ne: [] }; } - if (sinceId) { + if (ps.sinceId) { sort._id = 1; query._id = { - $gt: sinceId + $gt: ps.sinceId }; - } else if (untilId) { + } else if (ps.untilId) { query._id = { - $lt: untilId + $lt: ps.untilId }; - } else if (sinceDate) { + } else if (ps.sinceDate) { sort._id = 1; query.createdAt = { - $gt: new Date(sinceDate) + $gt: new Date(ps.sinceDate) }; - } else if (untilDate) { + } else if (ps.untilDate) { query.createdAt = { - $lt: new Date(untilDate) + $lt: new Date(ps.untilDate) }; } //#endregion @@ -97,7 +108,7 @@ export default async (params: any, user: ILocalUser) => { // Issue query const timeline = await Note .find(query, { - limit: limit, + limit: ps.limit, sort: sort }); diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts index f982dc01e9..82f11a9775 100644 --- a/src/server/api/endpoints/notes/search_by_tag.ts +++ b/src/server/api/endpoints/notes/search_by_tag.ts @@ -4,119 +4,152 @@ import User, { ILocalUser } from '../../../../models/user'; import Mute from '../../../../models/mute'; import { getFriendIds } from '../../common/get-friends'; import { pack } from '../../../../models/note'; +import getParams from '../../get-params'; -/** - * Search notes by tag - */ -export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { - // Get 'tag' parameter - const [tag, tagError] = $.str.get(params.tag); - if (tagError) return rej('invalid tag param'); +export const meta = { + desc: { + 'ja-JP': '指定されたタグが付けられた投稿を取得します。' + }, + + params: { + tag: $.str.note({ + desc: { + 'ja-JP': 'タグ' + } + }), + + includeUserIds: $.arr($.type(ID)).optional.note({ + default: [] + }), + + 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({ + default: 'mute_all' + }), - // Get 'includeUserIds' parameter - const [includeUserIds = [], includeUserIdsErr] = $.arr($.type(ID)).optional.get(params.includeUserIds); - if (includeUserIdsErr) return rej('invalid includeUserIds param'); + reply: $.bool.optional.nullable.note({ + default: null, - // Get 'excludeUserIds' parameter - const [excludeUserIds = [], excludeUserIdsErr] = $.arr($.type(ID)).optional.get(params.excludeUserIds); - if (excludeUserIdsErr) return rej('invalid excludeUserIds param'); + desc: { + 'ja-JP': '返信に限定するか否か' + } + }), - // Get 'includeUserUsernames' parameter - const [includeUserUsernames = [], includeUserUsernamesErr] = $.arr($.str).optional.get(params.includeUserUsernames); - if (includeUserUsernamesErr) return rej('invalid includeUserUsernames param'); + renote: $.bool.optional.nullable.note({ + default: null, - // Get 'excludeUserUsernames' parameter - const [excludeUserUsernames = [], excludeUserUsernamesErr] = $.arr($.str).optional.get(params.excludeUserUsernames); - if (excludeUserUsernamesErr) return rej('invalid excludeUserUsernames param'); + desc: { + 'ja-JP': 'Renoteに限定するか否か' + } + }), - // Get 'following' parameter - const [following = null, followingErr] = $.bool.optional.nullable.get(params.following); - if (followingErr) return rej('invalid following param'); + withFiles: $.bool.optional.nullable.note({ + default: null, - // Get 'mute' parameter - const [mute = 'mute_all', muteErr] = $.str.optional.get(params.mute); - if (muteErr) return rej('invalid mute param'); + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か' + } + }), - // Get 'reply' parameter - const [reply = null, replyErr] = $.bool.optional.nullable.get(params.reply); - if (replyErr) return rej('invalid reply param'); + media: $.bool.optional.nullable.note({ + default: null, - // Get 'renote' parameter - const [renote = null, renoteErr] = $.bool.optional.nullable.get(params.renote); - if (renoteErr) return rej('invalid renote param'); + desc: { + 'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' + } + }), - // Get 'withFiles' parameter - const [withFiles = null, withFilesErr] = $.bool.optional.nullable.get(params.withFiles); - if (withFilesErr) return rej('invalid withFiles param'); + poll: $.bool.optional.nullable.note({ + default: null, - // Get 'poll' parameter - const [poll = null, pollErr] = $.bool.optional.nullable.get(params.poll); - if (pollErr) return rej('invalid poll param'); + desc: { + 'ja-JP': 'アンケートが添付された投稿に限定するか否か' + } + }), - // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); - if (sinceDateErr) throw 'invalid sinceDate param'; + sinceDate: $.num.optional.note({ + }), - // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); - if (untilDateErr) throw 'invalid untilDate param'; + untilDate: $.num.optional.note({ + }), - // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); - if (offsetErr) return rej('invalid offset param'); + offset: $.num.optional.min(0).note({ + default: 0 + }), - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 30).get(params.limit); - if (limitErr) return rej('invalid limit param'); + limit: $.num.optional.range(1, 30).note({ + default: 10 + }), + } +}; + +export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; - if (includeUserUsernames != null) { - const ids = (await Promise.all(includeUserUsernames.map(async (username) => { + if (ps.includeUserUsernames != null) { + const ids = (await Promise.all(ps.includeUserUsernames.map(async (username) => { const _user = await User.findOne({ usernameLower: username.toLowerCase() }); return _user ? _user._id : null; }))).filter(id => id != null); - ids.forEach(id => includeUserIds.push(id)); + ids.forEach(id => ps.includeUserIds.push(id)); } - if (excludeUserUsernames != null) { - const ids = (await Promise.all(excludeUserUsernames.map(async (username) => { + if (ps.excludeUserUsernames != null) { + const ids = (await Promise.all(ps.excludeUserUsernames.map(async (username) => { const _user = await User.findOne({ usernameLower: username.toLowerCase() }); return _user ? _user._id : null; }))).filter(id => id != null); - ids.forEach(id => excludeUserIds.push(id)); + ids.forEach(id => ps.excludeUserIds.push(id)); } let q: any = { $and: [{ - tagsLower: tag.toLowerCase() + tagsLower: ps.tag.toLowerCase() }] }; const push = (x: any) => q.$and.push(x); - if (includeUserIds && includeUserIds.length != 0) { + if (ps.includeUserIds && ps.includeUserIds.length != 0) { push({ userId: { - $in: includeUserIds + $in: ps.includeUserIds } }); - } else if (excludeUserIds && excludeUserIds.length != 0) { + } else if (ps.excludeUserIds && ps.excludeUserIds.length != 0) { push({ userId: { - $nin: excludeUserIds + $nin: ps.excludeUserIds } }); } - if (following != null && me != null) { + if (ps.following != null && me != null) { const ids = await getFriendIds(me._id, false); push({ - userId: following ? { + userId: ps.following ? { $in: ids } : { $nin: ids.concat(me._id) @@ -131,7 +164,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => }); const mutedUserIds = mutes.map(m => m.muteeId); - switch (mute) { + switch (ps.mute) { case 'mute_all': push({ userId: { @@ -202,8 +235,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } - if (reply != null) { - if (reply) { + if (ps.reply != null) { + if (ps.reply) { push({ replyId: { $exists: true, @@ -223,8 +256,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } - if (renote != null) { - if (renote) { + if (ps.renote != null) { + if (ps.renote) { push({ renoteId: { $exists: true, @@ -244,6 +277,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } + const withFiles = ps.withFiles != null ? ps.withFiles : ps.media; + if (withFiles != null) { if (withFiles) { push({ @@ -265,8 +300,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } - if (poll != null) { - if (poll) { + if (ps.poll != null) { + if (ps.poll) { push({ poll: { $exists: true, @@ -286,18 +321,18 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } } - if (sinceDate) { + if (ps.sinceDate) { push({ createdAt: { - $gt: new Date(sinceDate) + $gt: new Date(ps.sinceDate) } }); } - if (untilDate) { + if (ps.untilDate) { push({ createdAt: { - $lt: new Date(untilDate) + $lt: new Date(ps.untilDate) } }); } @@ -312,8 +347,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => sort: { _id: -1 }, - limit: limit, - skip: offset + limit: ps.limit, + skip: ps.offset }); // Serialize diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 145f648c56..089e7a182a 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -69,7 +69,13 @@ export const meta = { withFiles: $.bool.optional.note({ desc: { - 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } }), } @@ -193,7 +199,9 @@ export default async (params: any, user: ILocalUser) => { }); } - if (ps.withFiles) { + const withFiles = ps.withFiles != null ? ps.withFiles : ps.mediaOnly; + + if (withFiles) { query.$and.push({ fileIds: { $exists: true, $ne: [] } }); diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index e00a7de371..61192d7d3e 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -75,7 +75,13 @@ export const meta = { withFiles: $.bool.optional.note({ desc: { - 'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します' + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' + } + }), + + mediaOnly: $.bool.optional.note({ + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' } }), } @@ -199,7 +205,9 @@ export default async (params: any, user: ILocalUser) => { }); } - if (ps.withFiles) { + const withFiles = ps.withFiles != null ? ps.withFiles : ps.mediaOnly; + + if (withFiles) { query.$and.push({ fileIds: { $exists: true, $ne: [] } }); diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index d894e52dba..42c31189d6 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -2,63 +2,121 @@ import $ from 'cafy'; import ID from '../../../../misc/cafy-id'; import getHostLower from '../../common/get-host-lower'; import Note, { pack } from '../../../../models/note'; import User, { ILocalUser } from '../../../../models/user'; +import getParams from '../../get-params'; + +export const meta = { + desc: { + 'ja-JP': '指定したユーザーのタイムラインを取得します。' + }, + + params: { + userId: $.type(ID).optional.note({ + desc: { + 'ja-JP': 'ユーザーID' + } + }), + + username: $.str.optional.note({ + desc: { + 'ja-JP': 'ユーザー名' + } + }), + + host: $.str.optional.note({ + }), + + includeReplies: $.bool.optional.note({ + default: true, + + desc: { + 'ja-JP': 'リプライを含めるか否か' + } + }), + + limit: $.num.optional.range(1, 100).note({ + default: 10, + desc: { + 'ja-JP': '最大数' + } + }), + + sinceId: $.type(ID).optional.note({ + desc: { + 'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します' + } + }), + + untilId: $.type(ID).optional.note({ + desc: { + 'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します' + } + }), + + sinceDate: $.num.optional.note({ + desc: { + 'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + untilDate: $.num.optional.note({ + desc: { + 'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }), + + includeMyRenotes: $.bool.optional.note({ + default: true, + desc: { + 'ja-JP': '自分の行ったRenoteを含めるかどうか' + } + }), + + includeRenotedMyNotes: $.bool.optional.note({ + default: true, + desc: { + 'ja-JP': 'Renoteされた自分の投稿を含めるかどうか' + } + }), + + includeLocalRenotes: $.bool.optional.note({ + default: true, + desc: { + 'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか' + } + }), + + withFiles: $.bool.optional.note({ + default: false, + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' + } + }), + + mediaOnly: $.bool.optional.note({ + default: false, + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)' + } + }), + } +}; -/** - * Get notes of a user - */ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { - // Get 'userId' parameter - const [userId, userIdErr] = $.type(ID).optional.get(params.userId); - if (userIdErr) return rej('invalid userId param'); - - // Get 'username' parameter - const [username, usernameErr] = $.str.optional.get(params.username); - if (usernameErr) return rej('invalid username param'); + const [ps, psErr] = getParams(meta, params); + if (psErr) throw psErr; - if (userId === undefined && username === undefined) { + if (ps.userId === undefined && ps.username === undefined) { return rej('userId or username is required'); } - // Get 'host' parameter - const [host, hostErr] = $.str.optional.get(params.host); - if (hostErr) return rej('invalid host param'); - - // Get 'includeReplies' parameter - const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies); - if (includeRepliesErr) return rej('invalid includeReplies param'); - - // Get 'withFiles' parameter - const [withFiles = false, withFilesErr] = $.bool.optional.get(params.withFiles); - if (withFilesErr) return rej('invalid withFiles 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'); - - // Get 'sinceDate' parameter - const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate); - if (sinceDateErr) throw 'invalid sinceDate param'; - - // Get 'untilDate' parameter - const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate); - if (untilDateErr) throw 'invalid untilDate param'; - // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) { + if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } - const q = userId !== undefined - ? { _id: userId } - : { usernameLower: username.toLowerCase(), host: getHostLower(host) } ; + const q = ps.userId !== undefined + ? { _id: ps.userId } + : { usernameLower: ps.username.toLowerCase(), host: getHostLower(ps.host) } ; // Lookup user const user = await User.findOne(q, { @@ -80,30 +138,32 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => userId: user._id } as any; - if (sinceId) { + if (ps.sinceId) { sort._id = 1; query._id = { - $gt: sinceId + $gt: ps.sinceId }; - } else if (untilId) { + } else if (ps.untilId) { query._id = { - $lt: untilId + $lt: ps.untilId }; - } else if (sinceDate) { + } else if (ps.sinceDate) { sort._id = 1; query.createdAt = { - $gt: new Date(sinceDate) + $gt: new Date(ps.sinceDate) }; - } else if (untilDate) { + } else if (ps.untilDate) { query.createdAt = { - $lt: new Date(untilDate) + $lt: new Date(ps.untilDate) }; } - if (!includeReplies) { + if (!ps.includeReplies) { query.replyId = null; } + const withFiles = ps.withFiles != null ? ps.withFiles : ps.mediaOnly; + if (withFiles) { query.fileIds = { $exists: true, @@ -115,12 +175,10 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => // Issue query const notes = await Note .find(query, { - limit: limit, + limit: ps.limit, sort: sort }); // Serialize - res(await Promise.all(notes.map(async (note) => - await pack(note, me) - ))); + res(await Promise.all(notes.map(note => pack(note, me)))); }); -- cgit v1.2.3-freya From 395cfa61089efc4ab3ea1b6c6842521bad31efed Mon Sep 17 00:00:00 2001 From: Aya Morisawa Date: Thu, 6 Sep 2018 02:16:08 +0900 Subject: Resolve #2625 (#2627) --- src/client/app/desktop/views/pages/deck/deck.column.vue | 3 ++- src/games/reversi/core.ts | 6 ++++-- src/prelude/array.ts | 7 +++++++ src/server/activitypub/outbox.ts | 3 ++- src/server/api/endpoints/notes/global-timeline.ts | 3 ++- src/server/api/endpoints/notes/hybrid-timeline.ts | 3 ++- src/server/api/endpoints/notes/local-timeline.ts | 3 ++- src/server/api/endpoints/notes/timeline.ts | 3 ++- src/server/api/endpoints/users/notes.ts | 3 ++- 9 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/prelude/array.ts (limited to 'src/server/api/endpoints/notes') diff --git a/src/client/app/desktop/views/pages/deck/deck.column.vue b/src/client/app/desktop/views/pages/deck/deck.column.vue index 239b1b0447..abb09775fb 100644 --- a/src/client/app/desktop/views/pages/deck/deck.column.vue +++ b/src/client/app/desktop/views/pages/deck/deck.column.vue @@ -28,6 +28,7 @@ import Vue from 'vue'; import Menu from '../../../../common/views/components/menu.vue'; import contextmenu from '../../../api/contextmenu'; +import { countIf } from '../../../../../../prelude/array'; export default Vue.extend({ props: { @@ -117,7 +118,7 @@ export default Vue.extend({ toggleActive() { if (!this.isStacked) return; const vms = this.$store.state.settings.deck.layout.find(ids => ids.indexOf(this.column.id) != -1).map(id => this.getColumnVm(id)); - if (this.active && vms.filter(vm => vm.$el.classList.contains('active')).length == 1) return; + if (this.active && countIf(vm => vm.$el.classList.contains('active'), vms) == 1) return; this.active = !this.active; }, diff --git a/src/games/reversi/core.ts b/src/games/reversi/core.ts index b610d46884..34eb03becb 100644 --- a/src/games/reversi/core.ts +++ b/src/games/reversi/core.ts @@ -1,3 +1,5 @@ +import { count } from "../../prelude/array"; + // MISSKEY REVERSI ENGINE /** @@ -101,14 +103,14 @@ export default class Reversi { * 黒石の数 */ public get blackCount() { - return this.board.filter(x => x === BLACK).length; + return count(BLACK, this.board); } /** * 白石の数 */ public get whiteCount() { - return this.board.filter(x => x === WHITE).length; + return count(BLACK, this.board); } /** diff --git a/src/prelude/array.ts b/src/prelude/array.ts new file mode 100644 index 0000000000..e944030a7f --- /dev/null +++ b/src/prelude/array.ts @@ -0,0 +1,7 @@ +export function countIf(f: (x: T) => boolean, xs: T[]): number { + return xs.filter(f).length; +} + +export function count(x: T, xs: T[]): number { + return countIf(y => x === y, xs); +} diff --git a/src/server/activitypub/outbox.ts b/src/server/activitypub/outbox.ts index cc7e55b5df..a5e762eea8 100644 --- a/src/server/activitypub/outbox.ts +++ b/src/server/activitypub/outbox.ts @@ -10,6 +10,7 @@ import { setResponseType } from '../activitypub'; import Note from '../../models/note'; import renderNote from '../../remote/activitypub/renderer/note'; +import { countIf } from '../../prelude/array'; export default async (ctx: Router.IRouterContext) => { const userId = new mongo.ObjectID(ctx.params.user); @@ -25,7 +26,7 @@ export default async (ctx: Router.IRouterContext) => { const page: boolean = ctx.request.query.page === 'true'; // Validate parameters - if (sinceIdErr || untilIdErr || pageErr || [sinceId, untilId].filter(x => x != null).length > 1) { + if (sinceIdErr || untilIdErr || pageErr || countIf(x => x != null, [sinceId, untilId]) > 1) { ctx.status = 400; return; } diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index e70fc5d76f..5d93cd78ec 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -4,6 +4,7 @@ import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; +import { countIf } from '../../../../prelude/array'; export const meta = { desc: { @@ -42,7 +43,7 @@ export default async (params: any, user: ILocalUser) => { if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index 16cec86797..0eb7b61830 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -5,6 +5,7 @@ import { getFriends } from '../../common/get-friends'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; +import { countIf } from '../../../../prelude/array'; export const meta = { desc: { @@ -86,7 +87,7 @@ export default async (params: any, user: ILocalUser) => { if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 2458a70556..39c385853d 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -4,6 +4,7 @@ import Mute from '../../../../models/mute'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; +import { countIf } from '../../../../prelude/array'; export const meta = { desc: { @@ -42,7 +43,7 @@ export default async (params: any, user: ILocalUser) => { if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 089e7a182a..5f3844987c 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -5,6 +5,7 @@ import { getFriends } from '../../common/get-friends'; import { pack } from '../../../../models/note'; import { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; +import { countIf } from '../../../../prelude/array'; export const meta = { desc: { @@ -86,7 +87,7 @@ export default async (params: any, user: ILocalUser) => { if (psErr) throw psErr; // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index 42c31189d6..1ab7786a18 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -3,6 +3,7 @@ import getHostLower from '../../common/get-host-lower'; import Note, { pack } from '../../../../models/note'; import User, { ILocalUser } from '../../../../models/user'; import getParams from '../../get-params'; +import { countIf } from '../../../../prelude/array'; export const meta = { desc: { @@ -110,7 +111,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => } // Check if only one of sinceId, untilId, sinceDate, untilDate specified - if ([ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate].filter(x => x != null).length > 1) { + if (countIf(x => x != null, [ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate]) > 1) { throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; } -- cgit v1.2.3-freya From e2c6227f4713b91d94355c69d619ac2d5d865c1b Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 6 Sep 2018 04:28:22 +0900 Subject: Improve local timeline API --- src/server/api/endpoints/notes/local-timeline.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/server/api/endpoints/notes') diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 2458a70556..ce84b4135a 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -23,6 +23,12 @@ export const meta = { } }), + fileType: $.arr($.str).optional.note({ + desc: { + 'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します' + } + }), + limit: $.num.optional.range(1, 100).note({ default: 10 }), @@ -84,6 +90,14 @@ export default async (params: any, user: ILocalUser) => { query.fileIds = { $exists: true, $ne: [] }; } + if (ps.fileType) { + query.fileIds = { $exists: true, $ne: [] }; + + query['_files.contentType'] = { + $in: ps.fileType + }; + } + if (ps.sinceId) { sort._id = 1; query._id = { -- cgit v1.2.3-freya From 00d79487cd89f3cae675ecc0392c47ba547b69a5 Mon Sep 17 00:00:00 2001 From: Aya Morisawa Date: Fri, 7 Sep 2018 00:02:55 +0900 Subject: Add erase function (#2641) --- src/client/app/common/scripts/streaming/stream-manager.ts | 3 ++- src/client/app/common/views/components/poll-editor.vue | 3 ++- src/client/app/desktop/views/components/post-form.vue | 3 ++- src/client/app/mios.ts | 3 ++- src/client/app/mobile/views/components/post-form.vue | 3 ++- src/client/app/store.ts | 7 ++++--- src/client/app/sw.js | 4 ++-- src/prelude/array.ts | 4 ++++ src/server/api/endpoints/hashtags/trend.ts | 4 ++-- src/server/api/endpoints/notes/search_by_tag.ts | 9 +++++---- src/services/note/create.ts | 7 ++++--- 11 files changed, 31 insertions(+), 19 deletions(-) (limited to 'src/server/api/endpoints/notes') diff --git a/src/client/app/common/scripts/streaming/stream-manager.ts b/src/client/app/common/scripts/streaming/stream-manager.ts index 568b8b0372..8dd06f67d3 100644 --- a/src/client/app/common/scripts/streaming/stream-manager.ts +++ b/src/client/app/common/scripts/streaming/stream-manager.ts @@ -1,6 +1,7 @@ import { EventEmitter } from 'eventemitter3'; import * as uuid from 'uuid'; import Connection from './stream'; +import { erase } from '../../../../../prelude/array'; /** * ストリーム接続を管理するクラス @@ -89,7 +90,7 @@ export default abstract class StreamManager extends EventE * @param userId use で発行したユーザーID */ public dispose(userId) { - this.users = this.users.filter(id => id != userId); + this.users = erase(userId, this.users); this._connection.user = `Managed (${ this.users.length })`; diff --git a/src/client/app/common/views/components/poll-editor.vue b/src/client/app/common/views/components/poll-editor.vue index 115c934c8b..30d9799fec 100644 --- a/src/client/app/common/views/components/poll-editor.vue +++ b/src/client/app/common/views/components/poll-editor.vue @@ -20,6 +20,7 @@