diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2019-04-08 23:05:41 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2019-04-08 23:05:41 +0900 |
| commit | 87d3a06dcd6a76120789c050dd6a0c7111bf7224 (patch) | |
| tree | ec0035b3284c30459033e97fbdc986b5cb5cf430 /src/server/api/endpoints/notes/hybrid-timeline.ts | |
| parent | Update CHANGELOG.md (diff) | |
| download | misskey-87d3a06dcd6a76120789c050dd6a0c7111bf7224.tar.gz misskey-87d3a06dcd6a76120789c050dd6a0c7111bf7224.tar.bz2 misskey-87d3a06dcd6a76120789c050dd6a0c7111bf7224.zip | |
revert rename
Diffstat (limited to 'src/server/api/endpoints/notes/hybrid-timeline.ts')
| -rw-r--r-- | src/server/api/endpoints/notes/hybrid-timeline.ts | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts new file mode 100644 index 0000000000..76f1682a95 --- /dev/null +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -0,0 +1,195 @@ +import $ from 'cafy'; +import { ID } from '../../../../misc/cafy-id'; +import define from '../../define'; +import fetchMeta from '../../../../misc/fetch-meta'; +import { ApiError } from '../../error'; +import { makePaginationQuery } from '../../common/make-pagination-query'; +import { Followings, Notes } from '../../../../models'; +import { Brackets } from 'typeorm'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query'; +import { generateMuteQuery } from '../../common/generate-mute-query'; +import { activeUsersChart } from '../../../../services/chart'; + +export const meta = { + desc: { + 'ja-JP': 'ソーシャルタイムラインを取得します。' + }, + + tags: ['notes'], + + params: { + limit: { + validator: $.optional.num.range(1, 100), + default: 10, + desc: { + 'ja-JP': '最大数' + } + }, + + sinceId: { + validator: $.optional.type(ID), + desc: { + 'ja-JP': '指定すると、その投稿を基点としてより新しい投稿を取得します' + } + }, + + untilId: { + validator: $.optional.type(ID), + desc: { + 'ja-JP': '指定すると、その投稿を基点としてより古い投稿を取得します' + } + }, + + sinceDate: { + validator: $.optional.num, + desc: { + 'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }, + + untilDate: { + validator: $.optional.num, + desc: { + 'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。' + } + }, + + includeMyRenotes: { + validator: $.optional.bool, + default: true, + desc: { + 'ja-JP': '自分の行ったRenoteを含めるかどうか' + } + }, + + includeRenotedMyNotes: { + validator: $.optional.bool, + default: true, + desc: { + 'ja-JP': 'Renoteされた自分の投稿を含めるかどうか' + } + }, + + includeLocalRenotes: { + validator: $.optional.bool, + default: true, + desc: { + 'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか' + } + }, + + withFiles: { + validator: $.optional.bool, + desc: { + 'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します' + } + }, + }, + + res: { + type: 'array', + items: { + type: 'Note', + }, + }, + + errors: { + stlDisabled: { + message: 'Hybrid timeline has been disabled.', + code: 'STL_DISABLED', + id: '620763f4-f621-4533-ab33-0577a1a3c342' + }, + } +}; + +export default define(meta, async (ps, user) => { + // TODO どっかにキャッシュ + const m = await fetchMeta(); + if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) { + throw new ApiError(meta.errors.stlDisabled); + } + + //#region Construct query + const followingQuery = Followings.createQueryBuilder('following') + .select('following.followeeId') + .where('following.followerId = :followerId', { followerId: user.id }); + + const query = makePaginationQuery(Notes.createQueryBuilder('note'), + ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) + .andWhere(new Brackets(qb => { + qb.where(`((note.userId IN (${ followingQuery.getQuery() })) OR (note.userId = :meId))`, { meId: user.id }) + .orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)'); + })) + .leftJoinAndSelect('note.user', 'user') + .setParameters(followingQuery.getParameters()); + + generateVisibilityQuery(query, user); + generateMuteQuery(query, user); + + /* TODO + // MongoDBではトップレベルで否定ができないため、De Morganの法則を利用してクエリします。 + // つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。 + // for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws + + if (ps.includeMyRenotes === false) { + query.$and.push({ + $or: [{ + userId: { $ne: user.id } + }, { + renoteId: null + }, { + text: { $ne: null } + }, { + fileIds: { $ne: [] } + }, { + poll: { $ne: null } + }] + }); + } + + if (ps.includeRenotedMyNotes === false) { + query.$and.push({ + $or: [{ + '_renote.userId': { $ne: user.id } + }, { + renoteId: null + }, { + text: { $ne: null } + }, { + fileIds: { $ne: [] } + }, { + poll: { $ne: null } + }] + }); + } + + if (ps.includeLocalRenotes === false) { + query.$and.push({ + $or: [{ + '_renote.user.host': { $ne: null } + }, { + renoteId: null + }, { + text: { $ne: null } + }, { + fileIds: { $ne: [] } + }, { + poll: { $ne: null } + }] + }); + } + */ + + if (ps.withFiles) { + query.andWhere('note.fileIds != \'{}\''); + } + //#endregion + + const timeline = await query.take(ps.limit).getMany(); + + if (user) { + activeUsersChart.update(user); + } + + return await Notes.packMany(timeline, user); +}); |