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