wip
This commit is contained in:
parent
a53edc96be
commit
fd0ce15b1b
1 changed files with 48 additions and 105 deletions
|
@ -3,7 +3,6 @@
|
|||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
import * as mongo from 'mongodb';
|
||||
import validate from '../../validator';
|
||||
import parse from '../../../common/text';
|
||||
import { Post, isValidText } from '../../models/post';
|
||||
|
@ -16,11 +15,6 @@ import notify from '../../common/notify';
|
|||
import event from '../../event';
|
||||
import config from '../../../conf';
|
||||
|
||||
/**
|
||||
* 添付できるファイルの数
|
||||
*/
|
||||
const maxMediaCount = 4;
|
||||
|
||||
function hasDuplicates(array) {
|
||||
return (new Set(array)).size !== array.length;
|
||||
}
|
||||
|
@ -41,37 +35,25 @@ module.exports = (params, user, app) =>
|
|||
if (textErr) return rej('invalid text');
|
||||
|
||||
// Get 'media_ids' parameter
|
||||
const [mediaIds, mediaIdsErr] = validate(params.media_ids, 'array', false, x => !hasDuplicates(x));
|
||||
const [mediaIds, mediaIdsErr] = validate(params.media_ids, 'array', false, [
|
||||
x => !hasDuplicates(x),
|
||||
x => x.length > 4 ? 'too many media' : true
|
||||
]);
|
||||
if (mediaIdsErr) return rej('invalid media_ids');
|
||||
|
||||
let files = [];
|
||||
if (mediaIds !== null) {
|
||||
if (mediaIds.length > maxMediaCount) {
|
||||
return rej('too many media');
|
||||
}
|
||||
|
||||
// Drop duplications
|
||||
medias = medias.filter((x, i, s) => s.indexOf(x) == i);
|
||||
|
||||
// Fetch files
|
||||
// forEach だと途中でエラーなどがあっても return できないので
|
||||
// 敢えて for を使っています。
|
||||
for (let i = 0; i < medias.length; i++) {
|
||||
const media = medias[i];
|
||||
|
||||
if (typeof media != 'string') {
|
||||
return rej('media id must be a string');
|
||||
}
|
||||
|
||||
// Validate id
|
||||
if (!mongo.ObjectID.isValid(media)) {
|
||||
return rej('incorrect media id');
|
||||
}
|
||||
for (let i = 0; i < mediaIds.length; i++) {
|
||||
const [mediaId, mediaIdErr] = validate(mediaIds[i], 'id', true);
|
||||
if (mediaIdErr) return rej('invalid media id');
|
||||
|
||||
// Fetch file
|
||||
// SELECT _id
|
||||
const entity = await DriveFile.findOne({
|
||||
_id: new mongo.ObjectID(media),
|
||||
_id: mediaId,
|
||||
user_id: user._id
|
||||
}, {
|
||||
_id: true
|
||||
|
@ -88,20 +70,14 @@ module.exports = (params, user, app) =>
|
|||
}
|
||||
|
||||
// Get 'repost_id' parameter
|
||||
let repost = params.repost_id;
|
||||
if (repost !== undefined && repost !== null) {
|
||||
if (typeof repost != 'string') {
|
||||
return rej('repost_id must be a string');
|
||||
}
|
||||
|
||||
// Validate id
|
||||
if (!mongo.ObjectID.isValid(repost)) {
|
||||
return rej('incorrect repost_id');
|
||||
}
|
||||
const [repostId, repostIdErr] = validate(params.repost_id, 'id');
|
||||
if (repostIdErr) return rej('invalid repost_id');
|
||||
|
||||
let repost = null;
|
||||
if (repostId !== null) {
|
||||
// Fetch repost to post
|
||||
repost = await Post.findOne({
|
||||
_id: new mongo.ObjectID(repost)
|
||||
_id: repostId
|
||||
});
|
||||
|
||||
if (repost == null) {
|
||||
|
@ -133,96 +109,63 @@ module.exports = (params, user, app) =>
|
|||
text === null && files === null) {
|
||||
return rej('二重Repostです(NEED TRANSLATE)');
|
||||
}
|
||||
} else {
|
||||
repost = null;
|
||||
}
|
||||
|
||||
// Get 'reply_to_id' parameter
|
||||
let replyTo = params.reply_to_id;
|
||||
if (replyTo !== undefined && replyTo !== null) {
|
||||
if (typeof replyTo != 'string') {
|
||||
return rej('reply_to_id must be a string');
|
||||
}
|
||||
|
||||
// Validate id
|
||||
if (!mongo.ObjectID.isValid(replyTo)) {
|
||||
return rej('incorrect reply_to_id');
|
||||
}
|
||||
// Get 'in_reply_to_post_id' parameter
|
||||
const [inReplyToPostId, inReplyToPostIdErr] = validate(params.reply_to_id, 'id');
|
||||
if (inReplyToPostIdErr) return rej('invalid in_reply_to_post_id');
|
||||
|
||||
let inReplyToPost = null;
|
||||
if (inReplyToPostId !== null) {
|
||||
// Fetch reply
|
||||
replyTo = await Post.findOne({
|
||||
_id: new mongo.ObjectID(replyTo)
|
||||
inReplyToPost = await Post.findOne({
|
||||
_id: inReplyToPostId
|
||||
});
|
||||
|
||||
if (replyTo === null) {
|
||||
return rej('reply to post is not found');
|
||||
if (inReplyToPost === null) {
|
||||
return rej('in reply to post is not found');
|
||||
}
|
||||
|
||||
// 返信対象が引用でないRepostだったらエラー
|
||||
if (replyTo.repost_id && !replyTo.text && !replyTo.media_ids) {
|
||||
if (inReplyToPost.repost_id && !inReplyToPost.text && !inReplyToPost.media_ids) {
|
||||
return rej('cannot reply to repost');
|
||||
}
|
||||
} else {
|
||||
replyTo = null;
|
||||
}
|
||||
|
||||
// Get 'poll' parameter
|
||||
let poll = params.poll;
|
||||
if (poll !== undefined && poll !== null) {
|
||||
// 選択肢が無かったらエラー
|
||||
if (poll.choices == null) {
|
||||
return rej('poll choices is required');
|
||||
}
|
||||
const [_poll, pollErr] = validate(params.poll, 'object');
|
||||
if (pollErr) return rej('invalid poll');
|
||||
|
||||
// 選択肢が配列でなかったらエラー
|
||||
if (!Array.isArray(poll.choices)) {
|
||||
return rej('poll choices must be an array');
|
||||
}
|
||||
|
||||
// 選択肢が空の配列でエラー
|
||||
if (poll.choices.length == 0) {
|
||||
return rej('poll choices is required');
|
||||
}
|
||||
|
||||
// Validate each choices
|
||||
const shouldReject = poll.choices.some(choice => {
|
||||
if (typeof choice !== 'string') return true;
|
||||
if (choice.trim().length === 0) return true;
|
||||
if (choice.trim().length > 100) return true;
|
||||
let poll = null;
|
||||
if (_poll !== null) {
|
||||
const [pollChoices, pollChoicesErr] = validate(params.poll, 'array', false, [
|
||||
choices => !hasDuplicates(choices),
|
||||
choices => {
|
||||
const shouldReject = choices.some(choice => {
|
||||
if (typeof choice != 'string') return true;
|
||||
if (choice.trim().length == 0) return true;
|
||||
if (choice.trim().length > 50) return true;
|
||||
});
|
||||
|
||||
if (shouldReject) {
|
||||
return rej('invalid poll choices');
|
||||
}
|
||||
|
||||
// Trim choices
|
||||
poll.choices = poll.choices.map(choice => choice.trim());
|
||||
|
||||
// Drop duplications
|
||||
poll.choices = poll.choices.filter((x, i, s) => s.indexOf(x) == i);
|
||||
|
||||
return shouldReject ? 'invalid poll choices' : true;
|
||||
},
|
||||
// 選択肢がひとつならエラー
|
||||
if (poll.choices.length == 1) {
|
||||
return rej('poll choices must be ひとつ以上');
|
||||
}
|
||||
|
||||
choices => choices.length == 1 ? 'poll choices must be ひとつ以上' : true,
|
||||
// 選択肢が多すぎてもエラー
|
||||
if (poll.choices.length > 10) {
|
||||
return rej('many poll choices');
|
||||
}
|
||||
choices => choices.length > 10 ? 'many poll choices' : true,
|
||||
]);
|
||||
if (pollChoicesErr) return rej('invalid poll choices');
|
||||
|
||||
// serialize
|
||||
poll.choices = poll.choices.map((choice, i) => ({
|
||||
_poll.choices = pollChoices.map((choice, i) => ({
|
||||
id: i, // IDを付与
|
||||
text: choice,
|
||||
text: choice.trim(),
|
||||
votes: 0
|
||||
}));
|
||||
} else {
|
||||
poll = null;
|
||||
|
||||
poll = _poll;
|
||||
}
|
||||
|
||||
// テキストが無いかつ添付ファイルが無いかつRepostも無いかつ投票も無かったらエラー
|
||||
if (text === null && files === null && repost === null && poll === null) {
|
||||
if (text === null && files === null && repost === null && pollChoices === null) {
|
||||
return rej('text, media_ids, repost_id or poll is required');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue