From b4340b1d91a6fc1679c3cb891ea800e1b491109c Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 31 Oct 2017 22:09:09 +0900 Subject: wip --- src/api/endpoints/posts/create.ts | 47 ++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 805dba7f83..42a55f850e 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -4,9 +4,9 @@ import $ from 'cafy'; import deepEqual = require('deep-equal'); import parse from '../../common/text'; -import Post from '../../models/post'; -import { isValidText } from '../../models/post'; +import { default as Post, IPost, isValidText } from '../../models/post'; import { default as User, IUser } from '../../models/user'; +import { default as Channel, IChannel } from '../../models/channel'; import Following from '../../models/following'; import DriveFile from '../../models/drive-file'; import Watching from '../../models/post-watching'; @@ -62,7 +62,8 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const [repostId, repostIdErr] = $(params.repost_id).optional.id().$; if (repostIdErr) return rej('invalid repost_id'); - let repost = null; + let repost: IPost = null; + let isQuote = false; if (repostId !== undefined) { // Fetch repost to post repost = await Post.findOne({ @@ -84,18 +85,20 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } }); + isQuote = text != null || files != null; + // 直近と同じRepost対象かつ引用じゃなかったらエラー if (latestPost && latestPost.repost_id && latestPost.repost_id.equals(repost._id) && - text === undefined && files === null) { + !isQuote) { return rej('cannot repost same post that already reposted in your latest post'); } // 直近がRepost対象かつ引用じゃなかったらエラー if (latestPost && latestPost._id.equals(repost._id) && - text === undefined && files === null) { + !isQuote) { return rej('cannot repost your latest post'); } } @@ -104,7 +107,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const [inReplyToPostId, inReplyToPostIdErr] = $(params.reply_to_id).optional.id().$; if (inReplyToPostIdErr) return rej('invalid in_reply_to_post_id'); - let inReplyToPost = null; + let inReplyToPost: IPost = null; if (inReplyToPostId !== undefined) { // Fetch reply inReplyToPost = await Post.findOne({ @@ -121,6 +124,37 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } + // Get 'channel_id' parameter + const [channelId, channelIdErr] = $(params.channel_id).optional.id().$; + if (channelIdErr) return rej('invalid channel_id'); + + let channel: IChannel = null; + if (channelId !== undefined) { + // Fetch channel + channel = await Channel.findOne({ + _id: channelId + }); + + if (channel === null) { + return rej('channel not found'); + } + + // 返信対象の投稿がこのチャンネルじゃなかったらダメ + if (inReplyToPost && !channelId.equals(inReplyToPost.channel_id)) { + return rej('チャンネル内部からチャンネル外部の投稿に返信することはできません'); + } + + // Repost対象の投稿がこのチャンネルじゃなかったらダメ + if (repost && !channelId.equals(repost.channel_id)) { + return rej('チャンネル内部からチャンネル外部の投稿をRepostすることはできません'); + } + + // 引用ではないRepostはダメ + if (repost && !isQuote) { + return rej('チャンネル内部では引用ではないRepostをすることはできません'); + } + } + // Get 'poll' parameter const [poll, pollErr] = $(params.poll).optional.strict.object() .have('choices', $().array('string') @@ -164,6 +198,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // 投稿を作成 const post = await Post.insert({ created_at: new Date(), + channel_id: channel ? channel._id : undefined, media_ids: files ? files.map(file => file._id) : undefined, reply_to_id: inReplyToPost ? inReplyToPost._id : undefined, repost_id: repost ? repost._id : undefined, -- cgit v1.2.3-freya From 30a4e839a687bed7ed839e3c17f6781bb4b76499 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 31 Oct 2017 22:14:12 +0900 Subject: Fix indent --- src/api/endpoints/posts/create.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 42a55f850e..e0a02fa4a0 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -186,11 +186,11 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { repost: user.latest_post.repost_id ? user.latest_post.repost_id.toString() : null, media_ids: (user.latest_post.media_ids || []).map(id => id.toString()) }, { - text: text, - reply: inReplyToPost ? inReplyToPost._id.toString() : null, - repost: repost ? repost._id.toString() : null, - media_ids: (files || []).map(file => file._id.toString()) - })) { + text: text, + reply: inReplyToPost ? inReplyToPost._id.toString() : null, + repost: repost ? repost._id.toString() : null, + media_ids: (files || []).map(file => file._id.toString()) + })) { return rej('duplicate'); } } -- cgit v1.2.3-freya From 71c3e11708dad327924bdcb95193d44c2b11a907 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 01:38:19 +0900 Subject: wip --- src/api/endpoints/channels/create.ts | 3 ++- src/api/endpoints/posts/create.ts | 17 +++++++++++++++ src/api/models/channel.ts | 1 + src/api/serializers/post.ts | 8 ++++++- src/web/app/desktop/tags/pages/channel.tag | 35 +++++++++++++++++++++++++----- src/web/app/desktop/tags/timeline.tag | 4 ++++ src/web/app/mobile/tags/timeline.tag | 4 ++++ 7 files changed, 65 insertions(+), 7 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts index 74b089dfc3..e0c0e0192a 100644 --- a/src/api/endpoints/channels/create.ts +++ b/src/api/endpoints/channels/create.ts @@ -21,7 +21,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { const channel = await Channel.insert({ created_at: new Date(), user_id: user._id, - title: title + title: title, + index: 0 }); // Response diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index e0a02fa4a0..183cabf135 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -153,6 +153,16 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { if (repost && !isQuote) { return rej('チャンネル内部では引用ではないRepostをすることはできません'); } + } else { + // 返信対象の投稿がチャンネルへの投稿だったらダメ + if (inReplyToPost && inReplyToPost.channel_id != null) { + return rej('チャンネル外部からチャンネル内部の投稿に返信することはできません'); + } + + // Repost対象の投稿がチャンネルへの投稿だったらダメ + if (repost && repost.channel_id != null) { + return rej('チャンネル外部からチャンネル内部の投稿をRepostすることはできません'); + } } // Get 'poll' parameter @@ -199,6 +209,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const post = await Post.insert({ created_at: new Date(), channel_id: channel ? channel._id : undefined, + index: channel ? channel.index + 1 : undefined, media_ids: files ? files.map(file => file._id) : undefined, reply_to_id: inReplyToPost ? inReplyToPost._id : undefined, repost_id: repost ? repost._id : undefined, @@ -217,6 +228,12 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // ----------------------------------------------------------- // Post processes + Channel.update({ _id: channel._id }, { + $inc: { + index: 1 + } + }); + User.update({ _id: user._id }, { $set: { latest_post: post diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts index 79edb71367..c80e84dbc8 100644 --- a/src/api/models/channel.ts +++ b/src/api/models/channel.ts @@ -10,4 +10,5 @@ export type IChannel = { created_at: Date; title: string; user_id: mongo.ObjectID; + index: number; }; diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts index df917a8595..7d40df2d6a 100644 --- a/src/api/serializers/post.ts +++ b/src/api/serializers/post.ts @@ -8,6 +8,7 @@ import Reaction from '../models/post-reaction'; import { IUser } from '../models/user'; import Vote from '../models/poll-vote'; import serializeApp from './app'; +import serializeChannel from './channel'; import serializeUser from './user'; import serializeDriveFile from './drive-file'; import parse from '../common/text'; @@ -76,8 +77,13 @@ const self = ( _post.app = await serializeApp(_post.app_id); } + // Populate channel + if (_post.channel_id) { + _post.channel = await serializeChannel(_post.channel_id); + } + + // Populate media if (_post.media_ids) { - // Populate media _post.media = await Promise.all(_post.media_ids.map(async fileId => await serializeDriveFile(fileId) )); diff --git a/src/web/app/desktop/tags/pages/channel.tag b/src/web/app/desktop/tags/pages/channel.tag index 8a3034f40c..ebd26f07b8 100644 --- a/src/web/app/desktop/tags/pages/channel.tag +++ b/src/web/app/desktop/tags/pages/channel.tag @@ -2,8 +2,9 @@

{ parent.channel.title }

- - + +
+
@@ -57,9 +60,13 @@
- { post.user.name } + { post.index }: + { post.user.name } + + ID:{ post.user.username }
+ >>{ post.reply_to.index } { post.text }
-

{ reply.user.name }への返信: (or キャンセル)

+

>>{ reply.index } ({ reply.user.name }): [x]

+
+ +
    +
  1. { name }
  2. +
+ + +
diff --git a/src/web/app/ch/tags/index.js b/src/web/app/ch/tags/index.js new file mode 100644 index 0000000000..1e99ccd43e --- /dev/null +++ b/src/web/app/ch/tags/index.js @@ -0,0 +1,2 @@ +require('./index.tag'); +require('./channel.tag'); diff --git a/src/web/app/ch/tags/index.tag b/src/web/app/ch/tags/index.tag new file mode 100644 index 0000000000..1c0a037c2d --- /dev/null +++ b/src/web/app/ch/tags/index.tag @@ -0,0 +1,24 @@ + + + + + diff --git a/src/web/app/common/scripts/channel-stream.js b/src/web/app/common/scripts/channel-stream.js index 38e7d91132..17944dbe45 100644 --- a/src/web/app/common/scripts/channel-stream.js +++ b/src/web/app/common/scripts/channel-stream.js @@ -6,8 +6,10 @@ import Stream from './stream'; * Channel stream connection */ class Connection extends Stream { - constructor() { - super('channel'); + constructor(channelId) { + super('channel', { + channel: channelId + }); } } diff --git a/src/web/app/common/scripts/config.js b/src/web/app/common/scripts/config.js index 75a7abba29..c5015622f0 100644 --- a/src/web/app/common/scripts/config.js +++ b/src/web/app/common/scripts/config.js @@ -6,6 +6,7 @@ const host = isRoot ? Url.host : Url.host.substring(Url.host.indexOf('.') + 1, U const scheme = Url.protocol; const url = `${scheme}//${host}`; const apiUrl = `${scheme}//api.${host}`; +const chUrl = `${scheme}//ch.${host}`; const devUrl = `${scheme}//dev.${host}`; const aboutUrl = `${scheme}//about.${host}`; const statsUrl = `${scheme}//stats.${host}`; @@ -16,6 +17,7 @@ export default { scheme, url, apiUrl, + chUrl, devUrl, aboutUrl, statsUrl, diff --git a/src/web/app/desktop/router.js b/src/web/app/desktop/router.js index df67bb7b7c..977e3fa9a6 100644 --- a/src/web/app/desktop/router.js +++ b/src/web/app/desktop/router.js @@ -10,8 +10,6 @@ export default me => { route('/', index); route('/selectdrive', selectDrive); route('/i>mentions', mentions); - route('/channel', channels); - route('/channel/:channel', channel); route('/post::post', post); route('/search::query', search); route('/:user', user.bind(null, 'home')); @@ -57,16 +55,6 @@ export default me => { mount(el); } - function channel(ctx) { - const el = document.createElement('mk-channel-page'); - el.setAttribute('id', ctx.params.channel); - mount(el); - } - - function channels() { - mount(document.createElement('mk-channels-page')); - } - function selectDrive() { mount(document.createElement('mk-selectdrive-page')); } diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js index 0b92d8c236..37fdfe37e4 100644 --- a/src/web/app/desktop/tags/index.js +++ b/src/web/app/desktop/tags/index.js @@ -61,8 +61,6 @@ require('./pages/user.tag'); require('./pages/post.tag'); require('./pages/search.tag'); require('./pages/not-found.tag'); -require('./pages/channel.tag'); -require('./pages/channels.tag'); require('./pages/selectdrive.tag'); require('./autocomplete-suggestion.tag'); require('./progress-dialog.tag'); diff --git a/src/web/app/desktop/tags/pages/channel.tag b/src/web/app/desktop/tags/pages/channel.tag deleted file mode 100644 index a14c0648c4..0000000000 --- a/src/web/app/desktop/tags/pages/channel.tag +++ /dev/null @@ -1,184 +0,0 @@ - - -
-

{ parent.channel.title }

- - - -
- -
-
- - -
- - -
- { post.index }: - { post.user.name } - - ID:{ post.user.username } -
-
- >>{ post.reply_to.index } - { post.text } -
- - { - -
-
- - -
- - -

>>{ reply.index } ({ reply.user.name }): [x]

- - -
- -
    -
  1. { name }
  2. -
- - -
diff --git a/src/web/app/desktop/tags/pages/channels.tag b/src/web/app/desktop/tags/pages/channels.tag deleted file mode 100644 index 220f1ca50e..0000000000 --- a/src/web/app/desktop/tags/pages/channels.tag +++ /dev/null @@ -1,28 +0,0 @@ - - -
- -
-
- - -
diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag index 17b2c66dc8..64b64f902f 100644 --- a/src/web/app/desktop/tags/timeline.tag +++ b/src/web/app/desktop/tags/timeline.tag @@ -112,7 +112,7 @@
-

{ p.channel.title }:

+

{ p.channel.title }:

diff --git a/src/web/app/desktop/tags/ui.tag b/src/web/app/desktop/tags/ui.tag index 7527358dce..3123c34f4f 100644 --- a/src/web/app/desktop/tags/ui.tag +++ b/src/web/app/desktop/tags/ui.tag @@ -335,10 +335,10 @@ -
  • - +
  • + -

    %i18n:desktop.tags.mk-ui-header-nav.channels%

    +

    %i18n:desktop.tags.mk-ui-header-nav.ch%

  • diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag index b26a5cb108..ad18521df6 100644 --- a/src/web/app/mobile/tags/timeline.tag +++ b/src/web/app/mobile/tags/timeline.tag @@ -164,7 +164,7 @@
    -

    { p.channel.title }:

    +

    { p.channel.title }:

    diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index fb8cbcdbd2..b2d96f6b8b 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -231,10 +231,11 @@
  • %i18n:mobile.tags.mk-ui-nav.messaging%
    • %i18n:mobile.tags.mk-ui-nav.settings%
    • diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts index 5199285d55..066df18157 100644 --- a/webpack/webpack.config.ts +++ b/webpack/webpack.config.ts @@ -16,6 +16,7 @@ module.exports = langs.map(([lang, locale]) => { const entry = { desktop: './src/web/app/desktop/script.js', mobile: './src/web/app/mobile/script.js', + ch: './src/web/app/ch/script.js', stats: './src/web/app/stats/script.js', status: './src/web/app/status/script.js', dev: './src/web/app/dev/script.js', -- cgit v1.2.3-freya From c5d5f7cef39eec27db34ac9ff2cb6db25bbab206 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 04:28:53 +0900 Subject: Fix bug --- src/api/endpoints/posts/create.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 34265dcbc3..2e9f1d90fb 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -228,11 +228,13 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // ----------------------------------------------------------- // Post processes - Channel.update({ _id: channel._id }, { - $inc: { - index: 1 - } - }); + if (channel) { + Channel.update({ _id: channel._id }, { + $inc: { + index: 1 + } + }); + } User.update({ _id: user._id }, { $set: { -- cgit v1.2.3-freya From b60ed8f20cec2cbaa0d233f0c882b9f3f49a74f6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 04:32:18 +0900 Subject: Refactor --- src/api/endpoints/posts/create.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 2e9f1d90fb..43b503b981 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -228,13 +228,6 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // ----------------------------------------------------------- // Post processes - if (channel) { - Channel.update({ _id: channel._id }, { - $inc: { - index: 1 - } - }); - } User.update({ _id: user._id }, { $set: { @@ -260,8 +253,15 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // Publish event to myself's stream event(user._id, 'post', postObj); - // Publish event to channel if (channel) { + // Increment channel index(posts count) + Channel.update({ _id: channel._id }, { + $inc: { + index: 1 + } + }); + + // Publish event to channel publishChannelStream(channel._id, 'post', postObj); } -- cgit v1.2.3-freya From 47cabbad92e2c2d6cbeb5de6afc5ec689e8ff79d Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 05:02:06 +0900 Subject: Oops --- src/api/endpoints/posts/create.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 43b503b981..2bb1a7af17 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -228,7 +228,6 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // ----------------------------------------------------------- // Post processes - User.update({ _id: user._id }, { $set: { latest_post: post -- cgit v1.2.3-freya From 60a7640eb1547dc61997ba5db1eb2c28bdec33a0 Mon Sep 17 00:00:00 2001 From: こぴなたみぽ Date: Wed, 1 Nov 2017 10:22:40 +0900 Subject: RENAME: reply_to -> reply --- src/api/endpoints/aggregation/posts.ts | 4 ++-- src/api/endpoints/aggregation/posts/reply.ts | 2 +- src/api/endpoints/aggregation/users/activity.ts | 4 ++-- src/api/endpoints/aggregation/users/post.ts | 4 ++-- src/api/endpoints/posts.ts | 2 +- src/api/endpoints/posts/context.ts | 8 ++++---- src/api/endpoints/posts/create.ts | 10 +++++----- src/api/endpoints/posts/replies.ts | 2 +- src/api/endpoints/posts/trend.ts | 2 +- src/api/endpoints/users/get_frequently_replied_users.ts | 6 +++--- src/api/endpoints/users/posts.ts | 2 +- src/api/models/post.ts | 2 +- src/api/serializers/post.ts | 4 ++-- src/common/get-post-summary.ts | 6 +++--- src/docs/api/entities/post.pug | 10 +++++----- src/web/app/ch/tags/channel.tag | 4 ++-- src/web/app/desktop/tags/post-detail.tag | 8 ++++---- src/web/app/desktop/tags/post-form.tag | 2 +- src/web/app/desktop/tags/sub-post-content.tag | 2 +- src/web/app/desktop/tags/timeline.tag | 6 +++--- src/web/app/mobile/tags/post-detail.tag | 8 ++++---- src/web/app/mobile/tags/post-form.tag | 2 +- src/web/app/mobile/tags/sub-post-content.tag | 2 +- src/web/app/mobile/tags/timeline.tag | 6 +++--- test/api.js | 12 ++++++------ 25 files changed, 60 insertions(+), 60 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/aggregation/posts.ts b/src/api/endpoints/aggregation/posts.ts index 48ee225129..9d8bccbdb2 100644 --- a/src/api/endpoints/aggregation/posts.ts +++ b/src/api/endpoints/aggregation/posts.ts @@ -19,7 +19,7 @@ module.exports = params => new Promise(async (res, rej) => { .aggregate([ { $project: { repost_id: '$repost_id', - reply_to_id: '$reply_to_id', + reply_id: '$reply_id', created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST }}, { $project: { @@ -34,7 +34,7 @@ module.exports = params => new Promise(async (res, rej) => { then: 'repost', else: { $cond: { - if: { $ne: ['$reply_to_id', null] }, + if: { $ne: ['$reply_id', null] }, then: 'reply', else: 'post' } diff --git a/src/api/endpoints/aggregation/posts/reply.ts b/src/api/endpoints/aggregation/posts/reply.ts index 02a60c8969..b114c34e1e 100644 --- a/src/api/endpoints/aggregation/posts/reply.ts +++ b/src/api/endpoints/aggregation/posts/reply.ts @@ -26,7 +26,7 @@ module.exports = (params) => new Promise(async (res, rej) => { const datas = await Post .aggregate([ - { $match: { reply_to: post._id } }, + { $match: { reply: post._id } }, { $project: { created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST }}, diff --git a/src/api/endpoints/aggregation/users/activity.ts b/src/api/endpoints/aggregation/users/activity.ts index 5a3e78c441..102a71d7cb 100644 --- a/src/api/endpoints/aggregation/users/activity.ts +++ b/src/api/endpoints/aggregation/users/activity.ts @@ -40,7 +40,7 @@ module.exports = (params) => new Promise(async (res, rej) => { { $match: { user_id: user._id } }, { $project: { repost_id: '$repost_id', - reply_to_id: '$reply_to_id', + reply_id: '$reply_id', created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST }}, { $project: { @@ -55,7 +55,7 @@ module.exports = (params) => new Promise(async (res, rej) => { then: 'repost', else: { $cond: { - if: { $ne: ['$reply_to_id', null] }, + if: { $ne: ['$reply_id', null] }, then: 'reply', else: 'post' } diff --git a/src/api/endpoints/aggregation/users/post.ts b/src/api/endpoints/aggregation/users/post.ts index c964815a0c..c6a75eee39 100644 --- a/src/api/endpoints/aggregation/users/post.ts +++ b/src/api/endpoints/aggregation/users/post.ts @@ -34,7 +34,7 @@ module.exports = (params) => new Promise(async (res, rej) => { { $match: { user_id: user._id } }, { $project: { repost_id: '$repost_id', - reply_to_id: '$reply_to_id', + reply_id: '$reply_id', created_at: { $add: ['$created_at', 9 * 60 * 60 * 1000] } // Convert into JST }}, { $project: { @@ -49,7 +49,7 @@ module.exports = (params) => new Promise(async (res, rej) => { then: 'repost', else: { $cond: { - if: { $ne: ['$reply_to_id', null] }, + if: { $ne: ['$reply_id', null] }, then: 'reply', else: 'post' } diff --git a/src/api/endpoints/posts.ts b/src/api/endpoints/posts.ts index 23b9bd0b66..f6efcc108d 100644 --- a/src/api/endpoints/posts.ts +++ b/src/api/endpoints/posts.ts @@ -62,7 +62,7 @@ module.exports = (params) => new Promise(async (res, rej) => { } if (reply != undefined) { - query.reply_to_id = reply ? { $exists: true, $ne: null } : null; + query.reply_id = reply ? { $exists: true, $ne: null } : null; } if (repost != undefined) { diff --git a/src/api/endpoints/posts/context.ts b/src/api/endpoints/posts/context.ts index cd5f15f481..bad59a6bee 100644 --- a/src/api/endpoints/posts/context.ts +++ b/src/api/endpoints/posts/context.ts @@ -49,13 +49,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { return; } - if (p.reply_to_id) { - await get(p.reply_to_id); + if (p.reply_id) { + await get(p.reply_id); } } - if (post.reply_to_id) { - await get(post.reply_to_id); + if (post.reply_id) { + await get(post.reply_id); } // Serialize diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 2bb1a7af17..3b9e0d8997 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -103,9 +103,9 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } - // Get 'in_reply_to_post_id' parameter - const [inReplyToPostId, inReplyToPostIdErr] = $(params.reply_to_id).optional.id().$; - if (inReplyToPostIdErr) return rej('invalid in_reply_to_post_id'); + // Get 'in_reply_post_id' parameter + const [inReplyToPostId, inReplyToPostIdErr] = $(params.reply_id).optional.id().$; + if (inReplyToPostIdErr) return rej('invalid in_reply_post_id'); let inReplyToPost: IPost = null; if (inReplyToPostId !== undefined) { @@ -192,7 +192,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { if (user.latest_post) { if (deepEqual({ text: user.latest_post.text, - reply: user.latest_post.reply_to_id ? user.latest_post.reply_to_id.toString() : null, + reply: user.latest_post.reply_id ? user.latest_post.reply_id.toString() : null, repost: user.latest_post.repost_id ? user.latest_post.repost_id.toString() : null, media_ids: (user.latest_post.media_ids || []).map(id => id.toString()) }, { @@ -211,7 +211,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { channel_id: channel ? channel._id : undefined, index: channel ? channel.index + 1 : undefined, media_ids: files ? files.map(file => file._id) : undefined, - reply_to_id: inReplyToPost ? inReplyToPost._id : undefined, + reply_id: inReplyToPost ? inReplyToPost._id : undefined, repost_id: repost ? repost._id : undefined, poll: poll, text: text, diff --git a/src/api/endpoints/posts/replies.ts b/src/api/endpoints/posts/replies.ts index 89f4d99841..3fd6a46769 100644 --- a/src/api/endpoints/posts/replies.ts +++ b/src/api/endpoints/posts/replies.ts @@ -40,7 +40,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Issue query const replies = await Post - .find({ reply_to_id: post._id }, { + .find({ reply_id: post._id }, { limit: limit, skip: offset, sort: { diff --git a/src/api/endpoints/posts/trend.ts b/src/api/endpoints/posts/trend.ts index 3277206d26..64a195dff1 100644 --- a/src/api/endpoints/posts/trend.ts +++ b/src/api/endpoints/posts/trend.ts @@ -48,7 +48,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { } as any; if (reply != undefined) { - query.reply_to_id = reply ? { $exists: true, $ne: null } : null; + query.reply_id = reply ? { $exists: true, $ne: null } : null; } if (repost != undefined) { diff --git a/src/api/endpoints/users/get_frequently_replied_users.ts b/src/api/endpoints/users/get_frequently_replied_users.ts index 2e0e2e40a7..bb0f3b4cea 100644 --- a/src/api/endpoints/users/get_frequently_replied_users.ts +++ b/src/api/endpoints/users/get_frequently_replied_users.ts @@ -27,7 +27,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Fetch recent posts const recentPosts = await Post.find({ user_id: user._id, - reply_to_id: { + reply_id: { $exists: true, $ne: null } @@ -38,7 +38,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { limit: 1000, fields: { _id: false, - reply_to_id: true + reply_id: true } }); @@ -49,7 +49,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { const replyTargetPosts = await Post.find({ _id: { - $in: recentPosts.map(p => p.reply_to_id) + $in: recentPosts.map(p => p.reply_id) }, user_id: { $ne: user._id diff --git a/src/api/endpoints/users/posts.ts b/src/api/endpoints/users/posts.ts index e37b660773..d8204b8b80 100644 --- a/src/api/endpoints/users/posts.ts +++ b/src/api/endpoints/users/posts.ts @@ -85,7 +85,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => { } if (!includeReplies) { - query.reply_to_id = null; + query.reply_id = null; } if (withMedia) { diff --git a/src/api/models/post.ts b/src/api/models/post.ts index fe07dcb0b1..7584ce182d 100644 --- a/src/api/models/post.ts +++ b/src/api/models/post.ts @@ -13,7 +13,7 @@ export type IPost = { channel_id: mongo.ObjectID; created_at: Date; media_ids: mongo.ObjectID[]; - reply_to_id: mongo.ObjectID; + reply_id: mongo.ObjectID; repost_id: mongo.ObjectID; poll: {}; // todo text: string; diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts index 7d40df2d6a..7c3690ef79 100644 --- a/src/api/serializers/post.ts +++ b/src/api/serializers/post.ts @@ -123,9 +123,9 @@ const self = ( }); _post.next = next ? next._id : null; - if (_post.reply_to_id) { + if (_post.reply_id) { // Populate reply to post - _post.reply_to = await self(_post.reply_to_id, meId, { + _post.reply = await self(_post.reply_id, meId, { detail: false }); } diff --git a/src/common/get-post-summary.ts b/src/common/get-post-summary.ts index ac15077b28..6e8f65708e 100644 --- a/src/common/get-post-summary.ts +++ b/src/common/get-post-summary.ts @@ -22,9 +22,9 @@ const summarize = (post: any): string => { } // 返信のとき - if (post.reply_to_id) { - if (post.reply_to) { - summary += ` RE: ${summarize(post.reply_to)}`; + if (post.reply_id) { + if (post.reply) { + summary += ` RE: ${summarize(post.reply)}`; } else { summary += ' RE: ...'; } diff --git a/src/docs/api/entities/post.pug b/src/docs/api/entities/post.pug index e505d3fcb6..954f172717 100644 --- a/src/docs/api/entities/post.pug +++ b/src/docs/api/entities/post.pug @@ -52,11 +52,11 @@ block content td Number td 返信数 tr.optional - td reply_to + td reply td: a(href='./post', target='_blank') Post td 返信先の投稿 tr.nullable - td reply_to_id + td reply_id td ID td 返信先の投稿のID tr.optional @@ -90,7 +90,7 @@ block content { "created_at": "2016-12-10T00:28:50.114Z", "media_ids": null, - "reply_to_id": "584a16b15860fc52320137e3", + "reply_id": "584a16b15860fc52320137e3", "repost_id": null, "text": "小日向美穂だぞ!", "user_id": "5848bf7764e572683f4402f8", @@ -117,10 +117,10 @@ block content "is_following": true, "is_followed": true }, - "reply_to": { + "reply": { "created_at": "2016-12-09T02:28:01.563Z", "media_ids": null, - "reply_to_id": "5849d35e547e4249be329884", + "reply_id": "5849d35e547e4249be329884", "repost_id": null, "text": "アイコン小日向美穂?", "user_id": "57d01a501fdf2d07be417afe", diff --git a/src/web/app/ch/tags/channel.tag b/src/web/app/ch/tags/channel.tag index 8657652fb0..f1eea6b9bc 100644 --- a/src/web/app/ch/tags/channel.tag +++ b/src/web/app/ch/tags/channel.tag @@ -96,7 +96,7 @@ ID:{ post.user.username }
      - >>{ post.reply_to.index } + >>{ post.reply.index } { post.text }
      @@ -208,7 +208,7 @@ this.api('posts/create', { text: this.refs.text.value == '' ? undefined : this.refs.text.value, media_ids: files, - reply_to_id: this.reply ? this.reply.id : undefined, + reply_id: this.reply ? this.reply.id : undefined, channel_id: this.channel.id }).then(data => { this.clear(); diff --git a/src/web/app/desktop/tags/post-detail.tag b/src/web/app/desktop/tags/post-detail.tag index 58343482d0..ce7f81e32c 100644 --- a/src/web/app/desktop/tags/post-detail.tag +++ b/src/web/app/desktop/tags/post-detail.tag @@ -1,6 +1,6 @@
      - @@ -9,8 +9,8 @@
      -
      - +
      +

      @@ -329,7 +329,7 @@ // Fetch context this.api('posts/context', { - post_id: this.p.reply_to_id + post_id: this.p.reply_id }).then(context => { this.update({ contextFetching: false, diff --git a/src/web/app/desktop/tags/post-form.tag b/src/web/app/desktop/tags/post-form.tag index 6a363d67cd..5041078bee 100644 --- a/src/web/app/desktop/tags/post-form.tag +++ b/src/web/app/desktop/tags/post-form.tag @@ -475,7 +475,7 @@ this.api('posts/create', { text: this.refs.text.value == '' ? undefined : this.refs.text.value, media_ids: files, - reply_to_id: this.inReplyToPost ? this.inReplyToPost.id : undefined, + reply_id: this.inReplyToPost ? this.inReplyToPost.id : undefined, repost_id: this.repost ? this.repost.id : undefined, poll: this.poll ? this.refs.poll.get() : undefined }).then(data => { diff --git a/src/web/app/desktop/tags/sub-post-content.tag b/src/web/app/desktop/tags/sub-post-content.tag index 02cb5251b2..c75ae2911c 100644 --- a/src/web/app/desktop/tags/sub-post-content.tag +++ b/src/web/app/desktop/tags/sub-post-content.tag @@ -1,6 +1,6 @@

      - + diff --git a/src/web/app/desktop/tags/timeline.tag b/src/web/app/desktop/tags/timeline.tag index 64b64f902f..44f3d5d8ec 100644 --- a/src/web/app/desktop/tags/timeline.tag +++ b/src/web/app/desktop/tags/timeline.tag @@ -82,8 +82,8 @@ -
      - +
      +

      @@ -113,7 +113,7 @@

      { p.channel.title }:

      - +

      diff --git a/src/web/app/mobile/tags/post-detail.tag b/src/web/app/mobile/tags/post-detail.tag index ed275749ec..8a32101036 100644 --- a/src/web/app/mobile/tags/post-detail.tag +++ b/src/web/app/mobile/tags/post-detail.tag @@ -1,5 +1,5 @@ - @@ -8,8 +8,8 @@
      -
      - +
      +

      @@ -348,7 +348,7 @@ // Fetch context this.api('posts/context', { - post_id: this.p.reply_to_id + post_id: this.p.reply_id }).then(context => { this.update({ contextFetching: false, diff --git a/src/web/app/mobile/tags/post-form.tag b/src/web/app/mobile/tags/post-form.tag index cf267de94a..d7d382c9e2 100644 --- a/src/web/app/mobile/tags/post-form.tag +++ b/src/web/app/mobile/tags/post-form.tag @@ -267,7 +267,7 @@ this.api('posts/create', { text: this.refs.text.value == '' ? undefined : this.refs.text.value, media_ids: files, - reply_to_id: opts.reply ? opts.reply.id : undefined, + reply_id: opts.reply ? opts.reply.id : undefined, poll: this.poll ? this.refs.poll.get() : undefined }).then(data => { this.trigger('post'); diff --git a/src/web/app/mobile/tags/sub-post-content.tag b/src/web/app/mobile/tags/sub-post-content.tag index 97e0ecec03..e32e245185 100644 --- a/src/web/app/mobile/tags/sub-post-content.tag +++ b/src/web/app/mobile/tags/sub-post-content.tag @@ -1,5 +1,5 @@ -

      +
      ({ post.media.length }個のメディア) diff --git a/src/web/app/mobile/tags/timeline.tag b/src/web/app/mobile/tags/timeline.tag index ad18521df6..f9ec2cca60 100644 --- a/src/web/app/mobile/tags/timeline.tag +++ b/src/web/app/mobile/tags/timeline.tag @@ -137,8 +137,8 @@ -
      - +
      +

      @@ -165,7 +165,7 @@

      { p.channel.title }:

      - +

      diff --git a/test/api.js b/test/api.js index 1e731b5549..b43eb7ff62 100644 --- a/test/api.js +++ b/test/api.js @@ -277,15 +277,15 @@ describe('API', () => { const me = await insertSakurako(); const post = { text: 'さく', - reply_to_id: himaPost._id.toString() + reply_id: himaPost._id.toString() }; const res = await request('/posts/create', post, me); res.should.have.status(200); res.body.should.be.a('object'); res.body.should.have.property('text').eql(post.text); - res.body.should.have.property('reply_to_id').eql(post.reply_to_id); - res.body.should.have.property('reply_to'); - res.body.reply_to.should.have.property('text').eql(himaPost.text); + res.body.should.have.property('reply_id').eql(post.reply_id); + res.body.should.have.property('reply'); + res.body.reply.should.have.property('text').eql(himaPost.text); })); it('repostできる', async(async () => { @@ -350,7 +350,7 @@ describe('API', () => { const me = await insertSakurako(); const post = { text: 'さく', - reply_to_id: '000000000000000000000000' + reply_id: '000000000000000000000000' }; const res = await request('/posts/create', post, me); res.should.have.status(400); @@ -369,7 +369,7 @@ describe('API', () => { const me = await insertSakurako(); const post = { text: 'さく', - reply_to_id: 'kyoppie' + reply_id: 'kyoppie' }; const res = await request('/posts/create', post, me); res.should.have.status(400); -- cgit v1.2.3-freya From 23282c2414693b948cbdabe9261b52c00b31ca68 Mon Sep 17 00:00:00 2001 From: こぴなたみぽ Date: Wed, 1 Nov 2017 10:45:01 +0900 Subject: Refactor --- src/api/endpoints/posts/create.ts | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 3b9e0d8997..e1138c3edc 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -103,23 +103,23 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } - // Get 'in_reply_post_id' parameter - const [inReplyToPostId, inReplyToPostIdErr] = $(params.reply_id).optional.id().$; - if (inReplyToPostIdErr) return rej('invalid in_reply_post_id'); + // Get 'reply_id' parameter + const [replyId, replyIdErr] = $(params.reply_id).optional.id().$; + if (replyIdErr) return rej('invalid reply_id'); - let inReplyToPost: IPost = null; - if (inReplyToPostId !== undefined) { + let reply: IPost = null; + if (replyId !== undefined) { // Fetch reply - inReplyToPost = await Post.findOne({ - _id: inReplyToPostId + reply = await Post.findOne({ + _id: replyId }); - if (inReplyToPost === null) { + if (reply === null) { return rej('in reply to post is not found'); } // 返信対象が引用でないRepostだったらエラー - if (inReplyToPost.repost_id && !inReplyToPost.text && !inReplyToPost.media_ids) { + if (reply.repost_id && !reply.text && !reply.media_ids) { return rej('cannot reply to repost'); } } @@ -140,7 +140,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } // 返信対象の投稿がこのチャンネルじゃなかったらダメ - if (inReplyToPost && !channelId.equals(inReplyToPost.channel_id)) { + if (reply && !channelId.equals(reply.channel_id)) { return rej('チャンネル内部からチャンネル外部の投稿に返信することはできません'); } @@ -155,7 +155,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } else { // 返信対象の投稿がチャンネルへの投稿だったらダメ - if (inReplyToPost && inReplyToPost.channel_id != null) { + if (reply && reply.channel_id != null) { return rej('チャンネル外部からチャンネル内部の投稿に返信することはできません'); } @@ -197,7 +197,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { media_ids: (user.latest_post.media_ids || []).map(id => id.toString()) }, { text: text, - reply: inReplyToPost ? inReplyToPost._id.toString() : null, + reply: reply ? reply._id.toString() : null, repost: repost ? repost._id.toString() : null, media_ids: (files || []).map(file => file._id.toString()) })) { @@ -211,7 +211,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { channel_id: channel ? channel._id : undefined, index: channel ? channel.index + 1 : undefined, media_ids: files ? files.map(file => file._id) : undefined, - reply_id: inReplyToPost ? inReplyToPost._id : undefined, + reply_id: reply ? reply._id : undefined, repost_id: repost ? repost._id : undefined, poll: poll, text: text, @@ -287,23 +287,23 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { }); // If has in reply to post - if (inReplyToPost) { + if (reply) { // Increment replies count - Post.update({ _id: inReplyToPost._id }, { + Post.update({ _id: reply._id }, { $inc: { replies_count: 1 } }); // 自分自身へのリプライでない限りは通知を作成 - notify(inReplyToPost.user_id, user._id, 'reply', { + notify(reply.user_id, user._id, 'reply', { post_id: post._id }); // Fetch watchers Watching .find({ - post_id: inReplyToPost._id, + post_id: reply._id, user_id: { $ne: user._id }, // 削除されたドキュメントは除く deleted_at: { $exists: false } @@ -323,10 +323,10 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // この投稿をWatchする // TODO: ユーザーが「返信したときに自動でWatchする」設定を // オフにしていた場合はしない - watch(user._id, inReplyToPost); + watch(user._id, reply); // Add mention - addMention(inReplyToPost.user_id, 'reply'); + addMention(reply.user_id, 'reply'); } // If it is repost @@ -427,7 +427,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { if (mentionee == null) return; // 既に言及されたユーザーに対する返信や引用repostの場合も無視 - if (inReplyToPost && inReplyToPost.user_id.equals(mentionee._id)) return; + if (reply && reply.user_id.equals(mentionee._id)) return; if (repost && repost.user_id.equals(mentionee._id)) return; // Add mention -- cgit v1.2.3-freya From bbd3b6da079c43e62a76e3b1e24ffd422e42c883 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 12:34:12 +0900 Subject: wip --- src/api/endpoints/posts/timeline.ts | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 314e992344..5fe8200010 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -42,6 +42,12 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { const query = { user_id: { $in: followingIds + }, + // TODO + channel_id: { + $or: [{ + $exists: false + }, null] } } as any; if (sinceId) { -- cgit v1.2.3-freya From 5f968f3f259db5110c395e9f29a59463137b30c5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 12:44:53 +0900 Subject: Fix bug --- src/api/endpoints/posts/timeline.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index 5fe8200010..fe096442b4 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -44,11 +44,13 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { $in: followingIds }, // TODO - channel_id: { - $or: [{ + $or: [{ + channel_id: { $exists: false - }, null] - } + } + }, { + channel_id: null + }] } as any; if (sinceId) { sort._id = 1; -- cgit v1.2.3-freya From c5b6dabd07e33ae7972300caf260b690d27db8cd Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 13:20:55 +0900 Subject: wip --- src/api/endpoints/posts/create.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index e1138c3edc..360b5df0d9 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -264,20 +264,23 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { publishChannelStream(channel._id, 'post', postObj); } - // Fetch all followers - const followers = await Following - .find({ - followee_id: user._id, - // 削除されたドキュメントは除く - deleted_at: { $exists: false } - }, { - follower_id: true, - _id: false - }); + // TODO + if (!channel) { + // Fetch all followers + const followers = await Following + .find({ + followee_id: user._id, + // 削除されたドキュメントは除く + deleted_at: { $exists: false } + }, { + follower_id: true, + _id: false + }); - // Publish event to followers stream - followers.forEach(following => - event(following.follower_id, 'post', postObj)); + // Publish event to followers stream + followers.forEach(following => + event(following.follower_id, 'post', postObj)); + } // Increment my posts count User.update({ _id: user._id }, { -- cgit v1.2.3-freya From 3cbb3ff81fc12feeedc779dc5ff00733c67f9133 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 13:39:05 +0900 Subject: wip --- src/api/endpoints/posts/create.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index 360b5df0d9..b3fbdf6fa2 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -249,8 +249,11 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } - // Publish event to myself's stream - event(user._id, 'post', postObj); + // TODO + if (!channel) { + // Publish event to myself's stream + event(user._id, 'post', postObj); + } if (channel) { // Increment channel index(posts count) -- cgit v1.2.3-freya From d6b03c43eb818a5e13a8ad1ec69697e4600c5c2c Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 19:33:08 +0900 Subject: Implement Channel Watching --- src/api/endpoints.ts | 8 +++++ src/api/endpoints/channels/create.ts | 11 ++++++- src/api/endpoints/channels/unwatch.ts | 60 +++++++++++++++++++++++++++++++++++ src/api/endpoints/channels/watch.ts | 58 +++++++++++++++++++++++++++++++++ src/api/endpoints/posts/create.ts | 43 +++++++++++++++---------- src/api/endpoints/posts/timeline.ts | 37 +++++++++++++++------ src/api/models/channel-watching.ts | 3 ++ src/api/serializers/channel.ts | 22 +++++++++++++ src/web/app/ch/tags/channel.tag | 27 ++++++++++++++++ 9 files changed, 243 insertions(+), 26 deletions(-) create mode 100644 src/api/endpoints/channels/unwatch.ts create mode 100644 src/api/endpoints/channels/watch.ts create mode 100644 src/api/models/channel-watching.ts (limited to 'src/api/endpoints/posts') diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index c4dacad857..afefce39e5 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -490,6 +490,14 @@ const endpoints: Endpoint[] = [ { name: 'channels/posts' }, + { + name: 'channels/watch', + withCredential: true + }, + { + name: 'channels/unwatch', + withCredential: true + }, { name: 'channels' }, diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts index e0c0e0192a..a8d7c29dc1 100644 --- a/src/api/endpoints/channels/create.ts +++ b/src/api/endpoints/channels/create.ts @@ -3,6 +3,7 @@ */ import $ from 'cafy'; import Channel from '../../models/channel'; +import Watching from '../../models/channel-watching'; import serialize from '../../serializers/channel'; /** @@ -22,9 +23,17 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { created_at: new Date(), user_id: user._id, title: title, - index: 0 + index: 0, + watching_count: 1 }); // Response res(await serialize(channel)); + + // Create Watching + await Watching.insert({ + created_at: new Date(), + user_id: user._id, + channel_id: channel._id + }); }); diff --git a/src/api/endpoints/channels/unwatch.ts b/src/api/endpoints/channels/unwatch.ts new file mode 100644 index 0000000000..19d3be118a --- /dev/null +++ b/src/api/endpoints/channels/unwatch.ts @@ -0,0 +1,60 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import Channel from '../../models/channel'; +import Watching from '../../models/channel-watching'; + +/** + * Unwatch a channel + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + // Get 'channel_id' parameter + const [channelId, channelIdErr] = $(params.channel_id).id().$; + if (channelIdErr) return rej('invalid channel_id param'); + + //#region Fetch channel + const channel = await Channel.findOne({ + _id: channelId + }); + + if (channel === null) { + return rej('channel not found'); + } + //#endregion + + //#region Check whether not watching + const exist = await Watching.findOne({ + user_id: user._id, + channel_id: channel._id, + deleted_at: { $exists: false } + }); + + if (exist === null) { + return rej('already not watching'); + } + //#endregion + + // Delete watching + await Watching.update({ + _id: exist._id + }, { + $set: { + deleted_at: new Date() + } + }); + + // Send response + res(); + + // Decrement watching count + Channel.update(channel._id, { + $inc: { + watching_count: -1 + } + }); +}); diff --git a/src/api/endpoints/channels/watch.ts b/src/api/endpoints/channels/watch.ts new file mode 100644 index 0000000000..030e0dd411 --- /dev/null +++ b/src/api/endpoints/channels/watch.ts @@ -0,0 +1,58 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import Channel from '../../models/channel'; +import Watching from '../../models/channel-watching'; + +/** + * Watch a channel + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + // Get 'channel_id' parameter + const [channelId, channelIdErr] = $(params.channel_id).id().$; + if (channelIdErr) return rej('invalid channel_id param'); + + //#region Fetch channel + const channel = await Channel.findOne({ + _id: channelId + }); + + if (channel === null) { + return rej('channel not found'); + } + //#endregion + + //#region Check whether already watching + const exist = await Watching.findOne({ + user_id: user._id, + channel_id: channel._id, + deleted_at: { $exists: false } + }); + + if (exist !== null) { + return rej('already watching'); + } + //#endregion + + // Create Watching + await Watching.insert({ + created_at: new Date(), + user_id: user._id, + channel_id: channel._id + }); + + // Send response + res(); + + // Increment watching count + Channel.update(channel._id, { + $inc: { + watching_count: 1 + } + }); +}); diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index b3fbdf6fa2..2326f7baf1 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -10,6 +10,7 @@ import { default as Channel, IChannel } from '../../models/channel'; import Following from '../../models/following'; import DriveFile from '../../models/drive-file'; import Watching from '../../models/post-watching'; +import ChannelWatching from '../../models/channel-watching'; import serialize from '../../serializers/post'; import notify from '../../common/notify'; import watch from '../../common/watch-post'; @@ -249,26 +250,11 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { } } - // TODO + // タイムラインへの投稿 if (!channel) { // Publish event to myself's stream event(user._id, 'post', postObj); - } - if (channel) { - // Increment channel index(posts count) - Channel.update({ _id: channel._id }, { - $inc: { - index: 1 - } - }); - - // Publish event to channel - publishChannelStream(channel._id, 'post', postObj); - } - - // TODO - if (!channel) { // Fetch all followers const followers = await Following .find({ @@ -285,6 +271,31 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { event(following.follower_id, 'post', postObj)); } + // チャンネルへの投稿 + if (channel) { + // Increment channel index(posts count) + Channel.update({ _id: channel._id }, { + $inc: { + index: 1 + } + }); + + // Publish event to channel + publishChannelStream(channel._id, 'post', postObj); + + // Get channel watchers + const watches = await ChannelWatching.find({ + channel_id: channel._id, + // 削除されたドキュメントは除く + deleted_at: { $exists: false } + }); + + // チャンネルの視聴者(のタイムライン)に配信 + watches.forEach(w => { + event(w.user_id, 'post', postObj); + }); + } + // Increment my posts count User.update({ _id: user._id }, { $inc: { diff --git a/src/api/endpoints/posts/timeline.ts b/src/api/endpoints/posts/timeline.ts index fe096442b4..aa5aff5ba5 100644 --- a/src/api/endpoints/posts/timeline.ts +++ b/src/api/endpoints/posts/timeline.ts @@ -3,6 +3,7 @@ */ import $ from 'cafy'; import Post from '../../models/post'; +import ChannelWatching from '../../models/channel-watching'; import getFriends from '../../common/get-friends'; import serialize from '../../serializers/post'; @@ -32,26 +33,43 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { return rej('cannot set since_id and max_id'); } - // ID list of the user $self and other users who the user follows + // ID list of the user itself and other users who the user follows const followingIds = await getFriends(user._id); - // Construct query + // Watchしているチャンネルを取得 + const watches = await ChannelWatching.find({ + user_id: user._id, + // 削除されたドキュメントは除く + deleted_at: { $exists: false } + }); + + //#region Construct query const sort = { _id: -1 }; + const query = { - user_id: { - $in: followingIds - }, - // TODO $or: [{ + // フォローしている人のタイムラインへの投稿 + user_id: { + $in: followingIds + }, + // 「タイムラインへの」投稿に限定するためにチャンネルが指定されていないもののみに限る + $or: [{ + channel_id: { + $exists: false + } + }, { + channel_id: null + }] + }, { + // Watchしているチャンネルへの投稿 channel_id: { - $exists: false + $in: watches.map(w => w.channel_id) } - }, { - channel_id: null }] } as any; + if (sinceId) { sort._id = 1; query._id = { @@ -62,6 +80,7 @@ module.exports = (params, user, app) => new Promise(async (res, rej) => { $lt: maxId }; } + //#endregion // Issue query const timeline = await Post diff --git a/src/api/models/channel-watching.ts b/src/api/models/channel-watching.ts new file mode 100644 index 0000000000..6184ae408d --- /dev/null +++ b/src/api/models/channel-watching.ts @@ -0,0 +1,3 @@ +import db from '../../db/mongodb'; + +export default db.get('channel_watching') as any; // fuck type definition diff --git a/src/api/serializers/channel.ts b/src/api/serializers/channel.ts index d4e16d6be3..3cba39aa16 100644 --- a/src/api/serializers/channel.ts +++ b/src/api/serializers/channel.ts @@ -5,6 +5,7 @@ import * as mongo from 'mongodb'; import deepcopy = require('deepcopy'); import { IUser } from '../models/user'; import { default as Channel, IChannel } from '../models/channel'; +import Watching from '../models/channel-watching'; /** * Serialize a channel @@ -40,5 +41,26 @@ export default ( // Remove needless properties delete _channel.user_id; + // Me + const meId: mongo.ObjectID = me + ? mongo.ObjectID.prototype.isPrototypeOf(me) + ? me as mongo.ObjectID + : typeof me === 'string' + ? new mongo.ObjectID(me) + : (me as IUser)._id + : null; + + if (me) { + //#region Watchしているかどうか + const watch = await Watching.findOne({ + user_id: meId, + channel_id: _channel.id, + deleted_at: { $exists: false } + }); + + _channel.is_watching = watch !== null; + //#endregion + } + resolve(_channel); }); diff --git a/src/web/app/ch/tags/channel.tag b/src/web/app/ch/tags/channel.tag index ad254c98e5..57cedf10d4 100644 --- a/src/web/app/ch/tags/channel.tag +++ b/src/web/app/ch/tags/channel.tag @@ -4,6 +4,11 @@

      { channel.title }

      +
      +

      このチャンネルをウォッチしています ウォッチ解除

      +

      このチャンネルをウォッチする

      +
      +