mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2024-11-25 15:35:12 +00:00
Refactoring, Clean up and bug fixes
This commit is contained in:
parent
b4b9e76c8d
commit
931bdc6aac
108 changed files with 1722 additions and 1539 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "10.36.0",
|
"version": "10.37.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -2250,9 +2250,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cafy": {
|
"cafy": {
|
||||||
"version": "11.3.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cafy/-/cafy-11.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/cafy/-/cafy-12.0.0.tgz",
|
||||||
"integrity": "sha512-7kqqF4I6seSNSAWihRfnM78wP/OwaZMrCNIUzu0+TC1pDGfF2uoVfMsAJ1oV1jZsZ2L2qlUSvo9zhSEIouS/xQ=="
|
"integrity": "sha512-HGsunRfyqFyG1/oh+Szw8GtVpj4pwehyqmp8sTO1QwDF3htjDP+vVBWzg7iOU2Y3Cm+h+UiEpf6DJ0p57RNmAg=="
|
||||||
},
|
},
|
||||||
"caller-path": {
|
"caller-path": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
@ -15830,7 +15830,7 @@
|
||||||
},
|
},
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||||
},
|
},
|
||||||
"ignore": {
|
"ignore": {
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bee-queue": "1.2.2",
|
"bee-queue": "1.2.2",
|
||||||
"bootstrap-vue": "2.0.0-rc.11",
|
"bootstrap-vue": "2.0.0-rc.11",
|
||||||
"cafy": "11.3.0",
|
"cafy": "12.0.0",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"chai-http": "4.2.0",
|
"chai-http": "4.2.0",
|
||||||
"chalk": "2.4.1",
|
"chalk": "2.4.1",
|
||||||
|
|
|
@ -4,23 +4,31 @@ import isObjectId from './is-objectid';
|
||||||
|
|
||||||
export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
|
export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
|
||||||
export const isNotAnId = (x: any) => !isAnId(x);
|
export const isNotAnId = (x: any) => !isAnId(x);
|
||||||
|
export const transform = (x: string | mongo.ObjectID): mongo.ObjectID => {
|
||||||
|
if (x == null) return null;
|
||||||
|
|
||||||
|
if (isAnId(x) && !isObjectId(x)) {
|
||||||
|
return new mongo.ObjectID(x);
|
||||||
|
} else {
|
||||||
|
return x as mongo.ObjectID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const transformMany = (xs: (string | mongo.ObjectID)[]): mongo.ObjectID[] => {
|
||||||
|
if (xs == null) return null;
|
||||||
|
|
||||||
|
return xs.map(x => transform(x));
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ObjectId = mongo.ObjectID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID
|
* ID
|
||||||
*/
|
*/
|
||||||
export default class ID extends Context<mongo.ObjectID> {
|
export default class ID extends Context<string> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.transform = v => {
|
this.push((v: any) => {
|
||||||
if (isAnId(v) && !isObjectId(v)) {
|
|
||||||
return new mongo.ObjectID(v);
|
|
||||||
} else {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.push(v => {
|
|
||||||
if (!isObjectId(v) && isNotAnId(v)) {
|
if (!isObjectId(v) && isNotAnId(v)) {
|
||||||
return new Error('must-be-an-id');
|
return new Error('must-be-an-id');
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ export async function getRelation(me: mongo.ObjectId, target: mongo.ObjectId) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isFollowing: following1 !== null,
|
isFollowing: following1 !== null,
|
||||||
isStalking: following1 && following1.stalk,
|
isStalking: following1 ? following1.stalk : false,
|
||||||
hasPendingFollowRequestFromYou: followReq1 !== null,
|
hasPendingFollowRequestFromYou: followReq1 !== null,
|
||||||
hasPendingFollowRequestToYou: followReq2 !== null,
|
hasPendingFollowRequestToYou: followReq2 !== null,
|
||||||
isFollowed: following2 !== null,
|
isFollowed: following2 !== null,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import * as Router from 'koa-router';
|
import * as Router from 'koa-router';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import $ from 'cafy'; import ID from '../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
|
||||||
import User from '../../models/user';
|
import User from '../../models/user';
|
||||||
import Following from '../../models/following';
|
import Following from '../../models/following';
|
||||||
import pack from '../../remote/activitypub/renderer';
|
import pack from '../../remote/activitypub/renderer';
|
||||||
|
@ -49,7 +49,7 @@ export default async (ctx: Router.IRouterContext) => {
|
||||||
// カーソルが指定されている場合
|
// カーソルが指定されている場合
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$lt: transform(cursor)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import * as Router from 'koa-router';
|
import * as Router from 'koa-router';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import $ from 'cafy'; import ID from '../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
|
||||||
import User from '../../models/user';
|
import User from '../../models/user';
|
||||||
import Following from '../../models/following';
|
import Following from '../../models/following';
|
||||||
import pack from '../../remote/activitypub/renderer';
|
import pack from '../../remote/activitypub/renderer';
|
||||||
|
@ -49,7 +49,7 @@ export default async (ctx: Router.IRouterContext) => {
|
||||||
// カーソルが指定されている場合
|
// カーソルが指定されている場合
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$lt: transform(cursor)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import * as Router from 'koa-router';
|
import * as Router from 'koa-router';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
import $ from 'cafy'; import ID from '../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
|
||||||
import User from '../../models/user';
|
import User from '../../models/user';
|
||||||
import pack from '../../remote/activitypub/renderer';
|
import pack from '../../remote/activitypub/renderer';
|
||||||
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
|
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
|
||||||
|
@ -61,11 +61,11 @@ export default async (ctx: Router.IRouterContext) => {
|
||||||
if (sinceId) {
|
if (sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: transform(sinceId)
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: transform(untilId)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
|
import { Context } from 'cafy';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as glob from 'glob';
|
import * as glob from 'glob';
|
||||||
|
|
||||||
export interface IEndpointMeta {
|
export interface IEndpointMeta {
|
||||||
stability?: 'deprecated' | 'experimental' | 'stable';
|
stability?: string; //'deprecated' | 'experimental' | 'stable';
|
||||||
|
|
||||||
desc?: any;
|
desc?: { [key: string]: string };
|
||||||
|
|
||||||
params?: any;
|
params?: {
|
||||||
|
[key: string]: {
|
||||||
|
validator: Context<any>;
|
||||||
|
transform?: any;
|
||||||
|
default?: any;
|
||||||
|
desc?: { [key: string]: string };
|
||||||
|
ref?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
res?: any;
|
res?: any;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
@ -13,12 +13,14 @@ export const meta = {
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーID',
|
'ja-JP': '対象のユーザーID',
|
||||||
'en-US': 'The user ID which you want to suspend'
|
'en-US': 'The user ID which you want to suspend'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
@ -13,12 +13,14 @@ export const meta = {
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーID',
|
'ja-JP': '対象のユーザーID',
|
||||||
'en-US': 'The user ID which you want to unsuspend'
|
'en-US': 'The user ID which you want to unsuspend'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
@ -13,12 +13,14 @@ export const meta = {
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーID',
|
'ja-JP': '対象のユーザーID',
|
||||||
'en-US': 'The user ID which you want to unverify'
|
'en-US': 'The user ID which you want to unverify'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,41 +11,47 @@ export const meta = {
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
broadcasts: $.arr($.obj()).optional.nullable.note({
|
broadcasts: {
|
||||||
|
validator: $.arr($.obj()).optional.nullable,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ブロードキャスト'
|
'ja-JP': 'ブロードキャスト'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
emojis: $.arr($.obj()).optional.note({
|
emojis: {
|
||||||
|
validator: $.arr($.obj()).optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'カスタム絵文字定義'
|
'ja-JP': 'カスタム絵文字定義'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
disableRegistration: $.bool.optional.nullable.note({
|
disableRegistration: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '招待制か否か'
|
'ja-JP': '招待制か否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
disableLocalTimeline: $.bool.optional.nullable.note({
|
disableLocalTimeline: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ローカルタイムライン(とソーシャルタイムライン)を無効にするか否か'
|
'ja-JP': 'ローカルタイムライン(とソーシャルタイムライン)を無効にするか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
hidedTags: $.arr($.str).optional.nullable.note({
|
hidedTags: {
|
||||||
|
validator: $.arr($.str).optional.nullable,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '統計などで無視するハッシュタグ'
|
'ja-JP': '統計などで無視するハッシュタグ'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
bannerUrl: $.str.optional.nullable.note({
|
bannerUrl: {
|
||||||
|
validator: $.str.optional.nullable,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'インスタンスのバナー画像URL'
|
'ja-JP': 'インスタンスのバナー画像URL'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
import User from '../../../../models/user';
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
@ -13,12 +13,14 @@ export const meta = {
|
||||||
requireAdmin: true,
|
requireAdmin: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーID',
|
'ja-JP': '対象のユーザーID',
|
||||||
'en-US': 'The user ID which you want to verify'
|
'en-US': 'The user ID which you want to verify'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
import Note from '../../../../models/note';
|
|
||||||
import Meta from '../../../../models/meta';
|
|
||||||
|
|
||||||
export default () => new Promise(async (res, rej) => {
|
|
||||||
const meta = await Meta.findOne({});
|
|
||||||
const hidedTags = meta ? (meta.hidedTags || []).map(t => t.toLowerCase()) : [];
|
|
||||||
|
|
||||||
const span = 1000 * 60 * 60 * 24 * 7; // 1週間
|
|
||||||
|
|
||||||
//#region 1. 指定期間の内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
|
||||||
const data = await Note.aggregate([{
|
|
||||||
$match: {
|
|
||||||
createdAt: {
|
|
||||||
$gt: new Date(Date.now() - span)
|
|
||||||
},
|
|
||||||
tagsLower: {
|
|
||||||
$exists: true,
|
|
||||||
$ne: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
$unwind: '$tagsLower'
|
|
||||||
}, {
|
|
||||||
$group: {
|
|
||||||
_id: { tag: '$tagsLower', userId: '$userId' }
|
|
||||||
}
|
|
||||||
}]) as Array<{
|
|
||||||
_id: {
|
|
||||||
tag: string;
|
|
||||||
userId: any;
|
|
||||||
}
|
|
||||||
}>;
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
if (data.length == 0) {
|
|
||||||
return res([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tags: Array<{
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}> = [];
|
|
||||||
|
|
||||||
// カウント
|
|
||||||
data.map(x => x._id).forEach(x => {
|
|
||||||
// ブラックリストに登録されているタグなら弾く
|
|
||||||
if (hidedTags.includes(x.tag)) return;
|
|
||||||
|
|
||||||
const i = tags.findIndex(tag => tag.name == x.tag);
|
|
||||||
if (i != -1) {
|
|
||||||
tags[i].count++;
|
|
||||||
} else {
|
|
||||||
tags.push({
|
|
||||||
name: x.tag,
|
|
||||||
count: 1
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// タグを人気順に並べ替え
|
|
||||||
tags = tags.sort((a, b) => b.count - a.count);
|
|
||||||
|
|
||||||
tags = tags.slice(0, 30);
|
|
||||||
|
|
||||||
res(tags);
|
|
||||||
});
|
|
|
@ -1,110 +0,0 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
|
||||||
import User from '../../../../../models/user';
|
|
||||||
import Note from '../../../../../models/note';
|
|
||||||
|
|
||||||
// TODO: likeやfollowも集計
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aggregate activity of a user
|
|
||||||
*/
|
|
||||||
export default (params: any) => new Promise(async (res, rej) => {
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Lookup user
|
|
||||||
const user = await User.findOne({
|
|
||||||
_id: userId
|
|
||||||
}, {
|
|
||||||
fields: {
|
|
||||||
_id: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (user === null) {
|
|
||||||
return rej('user not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const datas = await Note
|
|
||||||
.aggregate([
|
|
||||||
{ $match: { userId: user._id } },
|
|
||||||
{ $project: {
|
|
||||||
renoteId: '$renoteId',
|
|
||||||
replyId: '$replyId',
|
|
||||||
createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
|
|
||||||
}},
|
|
||||||
{ $project: {
|
|
||||||
date: {
|
|
||||||
year: { $year: '$createdAt' },
|
|
||||||
month: { $month: '$createdAt' },
|
|
||||||
day: { $dayOfMonth: '$createdAt' }
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
$cond: {
|
|
||||||
if: { $ne: ['$renoteId', null] },
|
|
||||||
then: 'renote',
|
|
||||||
else: {
|
|
||||||
$cond: {
|
|
||||||
if: { $ne: ['$replyId', null] },
|
|
||||||
then: 'reply',
|
|
||||||
else: 'note'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
},
|
|
||||||
{ $group: { _id: {
|
|
||||||
date: '$date',
|
|
||||||
type: '$type'
|
|
||||||
}, count: { $sum: 1 } } },
|
|
||||||
{ $group: {
|
|
||||||
_id: '$_id.date',
|
|
||||||
data: { $addToSet: {
|
|
||||||
type: '$_id.type',
|
|
||||||
count: '$count'
|
|
||||||
}}
|
|
||||||
} }
|
|
||||||
]);
|
|
||||||
|
|
||||||
datas.forEach((data: any) => {
|
|
||||||
data.date = data._id;
|
|
||||||
delete data._id;
|
|
||||||
|
|
||||||
data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
|
|
||||||
data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
|
|
||||||
data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
|
|
||||||
|
|
||||||
delete data.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const graph = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < limit; i++) {
|
|
||||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
|
||||||
|
|
||||||
const data = datas.filter((d: any) =>
|
|
||||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
graph.push(data);
|
|
||||||
} else {
|
|
||||||
graph.push({
|
|
||||||
date: {
|
|
||||||
year: day.getFullYear(),
|
|
||||||
month: day.getMonth() + 1, // In JavaScript, month is zero-based.
|
|
||||||
day: day.getDate()
|
|
||||||
},
|
|
||||||
notes: 0,
|
|
||||||
renotes: 0,
|
|
||||||
replies: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res(graph);
|
|
||||||
});
|
|
|
@ -1,104 +0,0 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
|
||||||
import User from '../../../../../models/user';
|
|
||||||
import Note from '../../../../../models/note';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aggregate note of a user
|
|
||||||
*/
|
|
||||||
export default (params: any) => new Promise(async (res, rej) => {
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Lookup user
|
|
||||||
const user = await User.findOne({
|
|
||||||
_id: userId
|
|
||||||
}, {
|
|
||||||
fields: {
|
|
||||||
_id: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (user === null) {
|
|
||||||
return rej('user not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const datas = await Note
|
|
||||||
.aggregate([
|
|
||||||
{ $match: { userId: user._id } },
|
|
||||||
{ $project: {
|
|
||||||
renoteId: '$renoteId',
|
|
||||||
replyId: '$replyId',
|
|
||||||
createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
|
|
||||||
}},
|
|
||||||
{ $project: {
|
|
||||||
date: {
|
|
||||||
year: { $year: '$createdAt' },
|
|
||||||
month: { $month: '$createdAt' },
|
|
||||||
day: { $dayOfMonth: '$createdAt' }
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
$cond: {
|
|
||||||
if: { $ne: ['$renoteId', null] },
|
|
||||||
then: 'renote',
|
|
||||||
else: {
|
|
||||||
$cond: {
|
|
||||||
if: { $ne: ['$replyId', null] },
|
|
||||||
then: 'reply',
|
|
||||||
else: 'note'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
},
|
|
||||||
{ $group: { _id: {
|
|
||||||
date: '$date',
|
|
||||||
type: '$type'
|
|
||||||
}, count: { $sum: 1 } } },
|
|
||||||
{ $group: {
|
|
||||||
_id: '$_id.date',
|
|
||||||
data: { $addToSet: {
|
|
||||||
type: '$_id.type',
|
|
||||||
count: '$count'
|
|
||||||
}}
|
|
||||||
} }
|
|
||||||
]);
|
|
||||||
|
|
||||||
datas.forEach((data: any) => {
|
|
||||||
data.date = data._id;
|
|
||||||
delete data._id;
|
|
||||||
|
|
||||||
data.notes = (data.data.filter((x: any) => x.type == 'note')[0] || { count: 0 }).count;
|
|
||||||
data.renotes = (data.data.filter((x: any) => x.type == 'renote')[0] || { count: 0 }).count;
|
|
||||||
data.replies = (data.data.filter((x: any) => x.type == 'reply')[0] || { count: 0 }).count;
|
|
||||||
|
|
||||||
delete data.data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const graph = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < 30; i++) {
|
|
||||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
|
||||||
|
|
||||||
const data = datas.filter((d: any) =>
|
|
||||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
graph.push(data);
|
|
||||||
} else {
|
|
||||||
graph.push({
|
|
||||||
date: {
|
|
||||||
year: day.getFullYear(),
|
|
||||||
month: day.getMonth() + 1, // In JavaScript, month is zero-based.
|
|
||||||
day: day.getDate()
|
|
||||||
},
|
|
||||||
notes: 0,
|
|
||||||
renotes: 0,
|
|
||||||
replies: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res(graph);
|
|
||||||
});
|
|
|
@ -1,74 +0,0 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
|
||||||
import User from '../../../../../models/user';
|
|
||||||
import Reaction from '../../../../../models/note-reaction';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aggregate reaction of a user
|
|
||||||
*/
|
|
||||||
export default (params: any) => new Promise(async (res, rej) => {
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Lookup user
|
|
||||||
const user = await User.findOne({
|
|
||||||
_id: userId
|
|
||||||
}, {
|
|
||||||
fields: {
|
|
||||||
_id: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (user === null) {
|
|
||||||
return rej('user not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const datas = await Reaction
|
|
||||||
.aggregate([
|
|
||||||
{ $match: { userId: user._id } },
|
|
||||||
{ $project: {
|
|
||||||
createdAt: { $add: ['$createdAt', 9 * 60 * 60 * 1000] } // Convert into JST
|
|
||||||
}},
|
|
||||||
{ $project: {
|
|
||||||
date: {
|
|
||||||
year: { $year: '$createdAt' },
|
|
||||||
month: { $month: '$createdAt' },
|
|
||||||
day: { $dayOfMonth: '$createdAt' }
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{ $group: {
|
|
||||||
_id: '$date',
|
|
||||||
count: { $sum: 1 }
|
|
||||||
}}
|
|
||||||
]);
|
|
||||||
|
|
||||||
datas.forEach((data: any) => {
|
|
||||||
data.date = data._id;
|
|
||||||
delete data._id;
|
|
||||||
});
|
|
||||||
|
|
||||||
const graph = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < 30; i++) {
|
|
||||||
const day = new Date(new Date().setDate(new Date().getDate() - i));
|
|
||||||
|
|
||||||
const data = datas.filter((d: any) =>
|
|
||||||
d.date.year == day.getFullYear() && d.date.month == day.getMonth() + 1 && d.date.day == day.getDate()
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
graph.push(data);
|
|
||||||
} else {
|
|
||||||
graph.push({
|
|
||||||
date: {
|
|
||||||
year: day.getFullYear(),
|
|
||||||
month: day.getMonth() + 1, // In JavaScript, month is zero-based.
|
|
||||||
day: day.getDate()
|
|
||||||
},
|
|
||||||
count: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res(graph);
|
|
||||||
});
|
|
|
@ -16,11 +16,12 @@ export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
uri: $.str.note({
|
uri: {
|
||||||
|
validator: $.str,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ActivityPubオブジェクトのURI'
|
'ja-JP': 'ActivityPubオブジェクトのURI'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import App, { pack, IApp } from '../../../../models/app';
|
import App, { pack, IApp } from '../../../../models/app';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
params: {
|
||||||
|
appId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Show an app
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||||
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
const isSecure = user != null && app == null;
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
// Get 'appId' parameter
|
|
||||||
const [appId, appIdErr] = $.type(ID).get(params.appId);
|
|
||||||
if (appIdErr) return rej('invalid appId param');
|
|
||||||
|
|
||||||
// Lookup app
|
// Lookup app
|
||||||
const ap = await App.findOne({ _id: appId });
|
const ap = await App.findOne({ _id: ps.appId });
|
||||||
|
|
||||||
if (ap === null) {
|
if (ap === null) {
|
||||||
return rej('app not found');
|
return rej('app not found');
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||||
import Blocking from '../../../../models/blocking';
|
import Blocking from '../../../../models/blocking';
|
||||||
|
@ -23,12 +23,14 @@ export const meta = {
|
||||||
kind: 'following-write',
|
kind: 'following-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||||
import Blocking from '../../../../models/blocking';
|
import Blocking from '../../../../models/blocking';
|
||||||
|
@ -23,12 +23,14 @@ export const meta = {
|
||||||
kind: 'following-write',
|
kind: 'following-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Blocking, { packMany } from '../../../../models/blocking';
|
import Blocking, { packMany } from '../../../../models/blocking';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
|
@ -14,15 +14,20 @@ export const meta = {
|
||||||
kind: 'following-read',
|
kind: 'following-read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30
|
default: 30
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,20 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,20 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,24 +8,27 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
tag: $.str.note({
|
tag: {
|
||||||
|
validator: $.str,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のハッシュタグ'
|
'ja-JP': '対象のハッシュタグ'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,20 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,20 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
import perUserDriveChart from '../../../../../chart/per-user-drive';
|
import perUserDriveChart from '../../../../../chart/per-user-drive';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -9,25 +9,29 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
import perUserFollowingChart from '../../../../../chart/per-user-following';
|
import perUserFollowingChart from '../../../../../chart/per-user-following';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -9,25 +9,29 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
import perUserNotesChart from '../../../../../chart/per-user-notes';
|
import perUserNotesChart from '../../../../../chart/per-user-notes';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -9,25 +9,29 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
import perUserReactionsChart from '../../../../../chart/per-user-reactions';
|
import perUserReactionsChart from '../../../../../chart/per-user-reactions';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -9,25 +9,29 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,20 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
span: $.str.or(['day', 'hour']).note({
|
span: {
|
||||||
|
validator: $.str.or(['day', 'hour']),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '集計のスパン (day または hour)'
|
'ja-JP': '集計のスパン (day または hour)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30,
|
default: 30,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import DriveFile, { packMany } from '../../../../models/drive-file';
|
import DriveFile, { packMany } from '../../../../models/drive-file';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,68 +11,75 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-read'
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
folderId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
default: null as any,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
type: {
|
||||||
|
validator: $.str.optional.match(/^[a-zA-Z\/\-\*]+$/)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async (params: any, user: ILocalUser) => {
|
export default async (params: any, user: ILocalUser) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) throw psErr;
|
||||||
if (limitErr) throw 'invalid limit param';
|
|
||||||
|
|
||||||
// Get 'sinceId' parameter
|
|
||||||
const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
|
|
||||||
if (sinceIdErr) throw 'invalid sinceId param';
|
|
||||||
|
|
||||||
// Get 'untilId' parameter
|
|
||||||
const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
|
|
||||||
if (untilIdErr) throw 'invalid untilId param';
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
throw 'cannot set sinceId and untilId';
|
throw 'cannot set sinceId and untilId';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'folderId' parameter
|
|
||||||
const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
|
|
||||||
if (folderIdErr) throw 'invalid folderId param';
|
|
||||||
|
|
||||||
// Get 'type' parameter
|
|
||||||
const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
|
|
||||||
if (typeErr) throw 'invalid type param';
|
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const sort = {
|
const sort = {
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
'metadata.userId': user._id,
|
'metadata.userId': user._id,
|
||||||
'metadata.folderId': folderId,
|
'metadata.folderId': ps.folderId,
|
||||||
'metadata.deletedAt': { $exists: false }
|
'metadata.deletedAt': { $exists: false }
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
if (ps.type) {
|
||||||
query.contentType = new RegExp(`^${type.replace(/\*/g, '.+?')}$`);
|
query.contentType = new RegExp(`^${ps.type.replace(/\*/g, '.+?')}$`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const files = await DriveFile
|
const files = await DriveFile
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
|
||||||
return await packMany(files);
|
return await packMany(files);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFile from '../../../../../models/drive-file';
|
import DriveFile from '../../../../../models/drive-file';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
@ -17,12 +17,14 @@ export const meta = {
|
||||||
kind: 'drive-read',
|
kind: 'drive-read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
fileId: $.type(ID).note({
|
fileId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のファイルID',
|
'ja-JP': '対象のファイルID',
|
||||||
'en-US': 'Target file ID'
|
'en-US': 'Target file ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,12 @@ export const meta = {
|
||||||
kind: 'drive-read',
|
kind: 'drive-read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
md5: $.str.note({
|
md5: {
|
||||||
|
validator: $.str,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルのMD5ハッシュ'
|
'ja-JP': 'ファイルのMD5ハッシュ'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import { validateFileName, pack } from '../../../../../models/drive-file';
|
import { validateFileName, pack } from '../../../../../models/drive-file';
|
||||||
import create from '../../../../../services/drive/add-file';
|
import create from '../../../../../services/drive/add-file';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
@ -24,27 +24,31 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
folderId: $.type(ID).optional.nullable.note({
|
folderId: {
|
||||||
default: null,
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'フォルダID'
|
'ja-JP': 'フォルダID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
isSensitive: $.bool.optional.note({
|
isSensitive: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: false,
|
default: false,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか',
|
'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか',
|
||||||
'en-US': 'Whether this media is NSFW'
|
'en-US': 'Whether this media is NSFW'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
force: $.bool.optional.note({
|
force: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: false,
|
default: false,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、同じハッシュを持つファイルが既にアップロードされていても強制的にファイルを作成します。',
|
'ja-JP': 'true にすると、同じハッシュを持つファイルが既にアップロードされていても強制的にファイルを作成します。',
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFile from '../../../../../models/drive-file';
|
import DriveFile from '../../../../../models/drive-file';
|
||||||
import del from '../../../../../services/drive/delete-file';
|
import del from '../../../../../services/drive/delete-file';
|
||||||
import { publishDriveStream } from '../../../../../stream';
|
import { publishDriveStream } from '../../../../../stream';
|
||||||
|
@ -18,12 +18,14 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
fileId: $.type(ID).note({
|
fileId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のファイルID',
|
'ja-JP': '対象のファイルID',
|
||||||
'en-US': 'Target file ID'
|
'en-US': 'Target file ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,39 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-read'
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
name: {
|
||||||
|
validator: $.str
|
||||||
|
},
|
||||||
|
|
||||||
|
folderId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
|
default: null as any,
|
||||||
|
desc: {
|
||||||
|
'ja-JP': 'フォルダID'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'name' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [name, nameErr] = $.str.get(params.name);
|
if (psErr) return rej(psErr);
|
||||||
if (nameErr) return rej('invalid name param');
|
|
||||||
|
|
||||||
// Get 'folderId' parameter
|
|
||||||
const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
|
|
||||||
if (folderIdErr) return rej('invalid folderId param');
|
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const files = await DriveFile
|
const files = await DriveFile
|
||||||
.find({
|
.find({
|
||||||
filename: name,
|
filename: name,
|
||||||
'metadata.userId': user._id,
|
'metadata.userId': user._id,
|
||||||
'metadata.folderId': folderId
|
'metadata.folderId': ps.folderId
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
res(await Promise.all(files.map(file => pack(file))));
|
||||||
res(await Promise.all(files.map(async file =>
|
|
||||||
await pack(file))));
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
@ -16,12 +16,14 @@ export const meta = {
|
||||||
kind: 'drive-read',
|
kind: 'drive-read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
fileId: $.type(ID).note({
|
fileId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のファイルID',
|
'ja-JP': '対象のファイルID',
|
||||||
'en-US': 'Target file ID'
|
'en-US': 'Target file ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder from '../../../../../models/drive-folder';
|
import DriveFolder from '../../../../../models/drive-folder';
|
||||||
import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
|
import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
|
||||||
import { publishDriveStream } from '../../../../../stream';
|
import { publishDriveStream } from '../../../../../stream';
|
||||||
|
@ -17,34 +17,40 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
fileId: $.type(ID).note({
|
fileId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のファイルID'
|
'ja-JP': '対象のファイルID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
folderId: $.type(ID).optional.nullable.note({
|
folderId: {
|
||||||
default: undefined,
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
|
default: undefined as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'フォルダID'
|
'ja-JP': 'フォルダID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
name: $.str.optional.pipe(validateFileName).note({
|
name: {
|
||||||
default: undefined,
|
validator: $.str.optional.pipe(validateFileName),
|
||||||
|
default: undefined as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイル名',
|
'ja-JP': 'ファイル名',
|
||||||
'en-US': 'Name of the file'
|
'en-US': 'Name of the file'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
isSensitive: $.bool.optional.note({
|
isSensitive: {
|
||||||
default: undefined,
|
validator: $.bool.optional,
|
||||||
|
default: undefined as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか',
|
'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか',
|
||||||
'en-US': 'Whether this media is NSFW'
|
'en-US': 'Whether this media is NSFW'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import { pack } from '../../../../../models/drive-file';
|
import { pack } from '../../../../../models/drive-file';
|
||||||
import uploadFromUrl from '../../../../../services/drive/upload-from-url';
|
import uploadFromUrl from '../../../../../services/drive/upload-from-url';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -16,21 +17,25 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-write'
|
kind: 'drive-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
url: {
|
||||||
|
// TODO: Validate this url
|
||||||
|
validator: $.str,
|
||||||
|
},
|
||||||
|
|
||||||
|
folderId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
default: null as any as any,
|
||||||
|
transform: transform
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a file from a URL
|
|
||||||
*/
|
|
||||||
export default async (params: any, user: ILocalUser): Promise<any> => {
|
export default async (params: any, user: ILocalUser): Promise<any> => {
|
||||||
// Get 'url' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
// TODO: Validate this url
|
if (psErr) throw psErr;
|
||||||
const [url, urlErr] = $.str.get(params.url);
|
|
||||||
if (urlErr) throw 'invalid url param';
|
|
||||||
|
|
||||||
// Get 'folderId' parameter
|
return pack(await uploadFromUrl(ps.url, user, ps.folderId));
|
||||||
const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
|
|
||||||
if (folderIdErr) throw 'invalid folderId param';
|
|
||||||
|
|
||||||
return pack(await uploadFromUrl(url, user, folderId));
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import DriveFolder, { pack } from '../../../../models/drive-folder';
|
import DriveFolder, { pack } from '../../../../models/drive-folder';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,58 +11,64 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-read'
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
folderId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
default: null as any,
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) return rej(psErr);
|
||||||
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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'folderId' parameter
|
|
||||||
const [folderId = null, folderIdErr] = $.type(ID).optional.nullable.get(params.folderId);
|
|
||||||
if (folderIdErr) return rej('invalid folderId param');
|
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const sort = {
|
const sort = {
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
const query = {
|
const query = {
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
parentId: folderId
|
parentId: ps.folderId
|
||||||
} as any;
|
} as any;
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const folders = await DriveFolder
|
const folders = await DriveFolder
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
res(await Promise.all(folders.map(folder => pack(folder))));
|
||||||
res(await Promise.all(folders.map(async folder =>
|
|
||||||
await pack(folder))));
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||||
import { publishDriveStream } from '../../../../../stream';
|
import { publishDriveStream } from '../../../../../stream';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
@ -17,20 +17,23 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
name: $.str.optional.pipe(isValidFolderName).note({
|
name: {
|
||||||
|
validator: $.str.optional.pipe(isValidFolderName),
|
||||||
default: 'Untitled',
|
default: 'Untitled',
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'フォルダ名',
|
'ja-JP': 'フォルダ名',
|
||||||
'en-US': 'Folder name'
|
'en-US': 'Folder name'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
parentId: $.type(ID).optional.nullable.note({
|
parentId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '親フォルダID',
|
'ja-JP': '親フォルダID',
|
||||||
'en-US': 'Parent folder ID'
|
'en-US': 'Parent folder ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder from '../../../../../models/drive-folder';
|
import DriveFolder from '../../../../../models/drive-folder';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
@ -18,12 +18,14 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
folderId: $.type(ID).note({
|
folderId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のフォルダID',
|
'ja-JP': '対象のフォルダID',
|
||||||
'en-US': 'Target folder ID'
|
'en-US': 'Target folder ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,39 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-read'
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
name: {
|
||||||
|
validator: $.str
|
||||||
|
},
|
||||||
|
|
||||||
|
parentId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
|
default: null as any,
|
||||||
|
desc: {
|
||||||
|
'ja-JP': 'フォルダID'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'name' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [name, nameErr] = $.str.get(params.name);
|
if (psErr) return rej(psErr);
|
||||||
if (nameErr) return rej('invalid name param');
|
|
||||||
|
|
||||||
// Get 'parentId' parameter
|
|
||||||
const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
|
|
||||||
if (parentIdErr) return rej('invalid parentId param');
|
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const folders = await DriveFolder
|
const folders = await DriveFolder
|
||||||
.find({
|
.find({
|
||||||
name: name,
|
name: name,
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
parentId: parentId
|
parentId: ps.parentId
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await Promise.all(folders.map(folder => pack(folder))));
|
res(await Promise.all(folders.map(folder => pack(folder))));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
@ -16,12 +16,14 @@ export const meta = {
|
||||||
kind: 'drive-read',
|
kind: 'drive-read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
folderId: $.type(ID).note({
|
folderId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のフォルダID',
|
'ja-JP': '対象のフォルダID',
|
||||||
'en-US': 'Target folder ID'
|
'en-US': 'Target folder ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||||
import { publishDriveStream } from '../../../../../stream';
|
import { publishDriveStream } from '../../../../../stream';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
@ -17,26 +17,31 @@ export const meta = {
|
||||||
kind: 'drive-write',
|
kind: 'drive-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
folderId: $.type(ID).note({
|
folderId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のフォルダID',
|
'ja-JP': '対象のフォルダID',
|
||||||
'en-US': 'Target folder ID'
|
'en-US': 'Target folder ID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
name: $.str.optional.pipe(isValidFolderName).note({
|
name: {
|
||||||
|
validator: $.str.optional.pipe(isValidFolderName),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'フォルダ名',
|
'ja-JP': 'フォルダ名',
|
||||||
'en-US': 'Folder name'
|
'en-US': 'Folder name'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
parentId: $.type(ID).optional.nullable.note({
|
parentId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '親フォルダID',
|
'ja-JP': '親フォルダID',
|
||||||
'en-US': 'Parent folder ID'
|
'en-US': 'Parent folder ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,44 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import DriveFile, { packMany } from '../../../../models/drive-file';
|
import DriveFile, { packMany } from '../../../../models/drive-file';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'drive-read'
|
kind: 'drive-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
type: {
|
||||||
|
validator: $.str.optional.match(/^[a-zA-Z\/\-\*]+$/)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) return rej(psErr);
|
||||||
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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'type' parameter
|
|
||||||
const [type, typeErr] = $.str.optional.match(/^[a-zA-Z\/\-\*]+$/).get(params.type);
|
|
||||||
if (typeErr) return rej('invalid type param');
|
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const sort = {
|
const sort = {
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
@ -40,28 +48,26 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
'metadata.deletedAt': { $exists: false }
|
'metadata.deletedAt': { $exists: false }
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
if (ps.type) {
|
||||||
query.contentType = new RegExp(`^${type.replace(/\*/g, '.+?')}$`);
|
query.contentType = new RegExp(`^${ps.type.replace(/\*/g, '.+?')}$`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const files = await DriveFile
|
const files = await DriveFile
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(files));
|
res(await packMany(files));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
|
@ -23,12 +23,14 @@ export const meta = {
|
||||||
kind: 'following-write',
|
kind: 'following-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
|
@ -23,12 +23,14 @@ export const meta = {
|
||||||
kind: 'following-write',
|
kind: 'following-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
userId: $.type(ID).note({
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象のユーザーのID',
|
'ja-JP': '対象のユーザーのID',
|
||||||
'en-US': 'Target user ID'
|
'en-US': 'Target user ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import acceptFollowRequest from '../../../../../services/following/requests/accept';
|
import acceptFollowRequest from '../../../../../services/following/requests/accept';
|
||||||
import User, { ILocalUser } from '../../../../../models/user';
|
import User, { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,17 +11,23 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-write'
|
kind: 'following-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [followerId, followerIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (followerIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch follower
|
// Fetch follower
|
||||||
const follower = await User.findOne({
|
const follower = await User.findOne({
|
||||||
_id: followerId
|
_id: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (follower === null) {
|
if (follower === null) {
|
||||||
|
@ -29,6 +36,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
|
|
||||||
await acceptFollowRequest(user, follower);
|
await acceptFollowRequest(user, follower);
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import cancelFollowRequest from '../../../../../services/following/requests/cancel';
|
import cancelFollowRequest from '../../../../../services/following/requests/cancel';
|
||||||
import User, { pack, ILocalUser } from '../../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,17 +11,23 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-write'
|
kind: 'following-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [followeeId, followeeIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (followeeIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch followee
|
// Fetch followee
|
||||||
const followee = await User.findOne({
|
const followee = await User.findOne({
|
||||||
_id: followeeId
|
_id: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (followee === null) {
|
if (followee === null) {
|
||||||
|
@ -33,6 +40,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
return rej(e);
|
return rej(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send response
|
|
||||||
res(await pack(followee._id, user));
|
res(await pack(followee._id, user));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//import $ from 'cafy'; import ID from '../../../../../cafy-id';
|
//import $ from 'cafy'; import ID, { transform } from '../../../../../cafy-id';
|
||||||
import FollowRequest, { pack } from '../../../../../models/follow-request';
|
import FollowRequest, { pack } from '../../../../../models/follow-request';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import rejectFollowRequest from '../../../../../services/following/requests/reject';
|
import rejectFollowRequest from '../../../../../services/following/requests/reject';
|
||||||
import User, { ILocalUser } from '../../../../../models/user';
|
import User, { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,17 +11,23 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-write'
|
kind: 'following-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [followerId, followerIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (followerIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch follower
|
// Fetch follower
|
||||||
const follower = await User.findOne({
|
const follower = await User.findOne({
|
||||||
_id: followerId
|
_id: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (follower === null) {
|
if (follower === null) {
|
||||||
|
@ -29,6 +36,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
|
|
||||||
await rejectFollowRequest(user, follower);
|
await rejectFollowRequest(user, follower);
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,20 +11,26 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-write'
|
kind: 'following-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
const follower = user;
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
// Get 'userId' parameter
|
const follower = user;
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch following
|
// Fetch following
|
||||||
const following = await Following.findOne({
|
const following = await Following.findOne({
|
||||||
followerId: follower._id,
|
followerId: follower._id,
|
||||||
followeeId: userId
|
followeeId: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (following === null) {
|
if (following === null) {
|
||||||
|
@ -37,7 +44,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
|
|
||||||
// TODO: イベント
|
// TODO: イベント
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,20 +11,26 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-write'
|
kind: 'following-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
const follower = user;
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
// Get 'userId' parameter
|
const follower = user;
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch following
|
// Fetch following
|
||||||
const following = await Following.findOne({
|
const following = await Following.findOne({
|
||||||
followerId: follower._id,
|
followerId: follower._id,
|
||||||
followeeId: userId
|
followeeId: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (following === null) {
|
if (following === null) {
|
||||||
|
@ -37,7 +44,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
|
|
||||||
// TODO: イベント
|
// TODO: イベント
|
||||||
|
|
|
@ -1,33 +1,42 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
|
import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
my: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'my' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [my = false, myErr] = $.bool.optional.get(params.my);
|
if (psErr) return rej(psErr);
|
||||||
if (myErr) return rej('invalid my 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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
const q: any = my ? {
|
const q: any = ps.my ? {
|
||||||
isStarted: true,
|
isStarted: true,
|
||||||
$or: [{
|
$or: [{
|
||||||
user1Id: user._id
|
user1Id: user._id
|
||||||
|
@ -42,21 +51,21 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
q._id = {
|
q._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
q._id = {
|
q._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch games
|
// Fetch games
|
||||||
const games = await ReversiGame.find(q, {
|
const games = await ReversiGame.find(q, {
|
||||||
sort,
|
sort: sort,
|
||||||
limit
|
limit: ps.limit
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reponse
|
// Reponse
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../../misc/cafy-id';
|
||||||
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
||||||
import Reversi from '../../../../../../games/reversi/core';
|
import Reversi from '../../../../../../games/reversi/core';
|
||||||
import { ILocalUser } from '../../../../../../models/user';
|
import { ILocalUser } from '../../../../../../models/user';
|
||||||
|
import getParams from '../../../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
params: {
|
||||||
|
gameId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'gameId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [gameId, gameIdErr] = $.type(ID).get(params.gameId);
|
if (psErr) return rej(psErr);
|
||||||
if (gameIdErr) return rej('invalid gameId param');
|
|
||||||
|
|
||||||
const game = await ReversiGame.findOne({ _id: gameId });
|
const game = await ReversiGame.findOne({ _id: ps.gameId });
|
||||||
|
|
||||||
if (game == null) {
|
if (game == null) {
|
||||||
return rej('game not found');
|
return rej('game not found');
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../../misc/cafy-id';
|
||||||
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
||||||
import { ILocalUser } from '../../../../../../models/user';
|
import { ILocalUser } from '../../../../../../models/user';
|
||||||
import getParams from '../../../../get-params';
|
import getParams from '../../../../get-params';
|
||||||
|
@ -12,11 +12,13 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
gameId: $.type(ID).note({
|
gameId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '投了したい対局'
|
'ja-JP': '投了したい対局'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,34 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching';
|
import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching';
|
||||||
import ReversiGame, { pack as packGame } from '../../../../../models/games/reversi/game';
|
import ReversiGame, { pack as packGame } from '../../../../../models/games/reversi/game';
|
||||||
import User, { ILocalUser } from '../../../../../models/user';
|
import User, { ILocalUser } from '../../../../../models/user';
|
||||||
import { publishMainStream, publishReversiStream } from '../../../../../stream';
|
import { publishMainStream, publishReversiStream } from '../../../../../stream';
|
||||||
import { eighteight } from '../../../../../games/reversi/maps';
|
import { eighteight } from '../../../../../games/reversi/maps';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true
|
requireCredential: true,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [childId, childIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (childIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Myself
|
// Myself
|
||||||
if (childId.equals(user._id)) {
|
if (ps.userId.equals(user._id)) {
|
||||||
return rej('invalid userId param');
|
return rej('invalid userId param');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find session
|
// Find session
|
||||||
const exist = await Matching.findOne({
|
const exist = await Matching.findOne({
|
||||||
parentId: childId,
|
parentId: ps.userId,
|
||||||
childId: user._id
|
childId: user._id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -63,7 +70,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
} else {
|
} else {
|
||||||
// Fetch child
|
// Fetch child
|
||||||
const child = await User.findOne({
|
const child = await User.findOne({
|
||||||
_id: childId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
|
|
@ -11,25 +11,28 @@ export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10,
|
default: 10,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数'
|
'ja-JP': '最大数'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
query: $.str.note({
|
query: {
|
||||||
|
validator: $.str,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'クエリ'
|
'ja-JP': 'クエリ'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
offset: $.num.optional.min(0).note({
|
offset: {
|
||||||
|
validator: $.num.optional.min(0),
|
||||||
default: 0,
|
default: 0,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'オフセット'
|
'ja-JP': 'オフセット'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Favorite, { packMany } from '../../../../models/favorite';
|
import Favorite, { packMany } from '../../../../models/favorite';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,24 +11,32 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'favorites-read'
|
kind: 'favorites-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) return rej(psErr);
|
||||||
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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,21 +48,23 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get favorites
|
// Get favorites
|
||||||
const favorites = await Favorite
|
const favorites = await Favorite
|
||||||
.find(query, { limit, sort });
|
.find(query, {
|
||||||
|
limit: ps.limit,
|
||||||
|
sort: sort
|
||||||
|
});
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(favorites, user));
|
res(await packMany(favorites, user));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,38 +1,56 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Notification from '../../../../models/notification';
|
import Notification from '../../../../models/notification';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { packMany } from '../../../../models/notification';
|
import { packMany } from '../../../../models/notification';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import { getFriendIds } from '../../common/get-friends';
|
||||||
import read from '../../common/read-notification';
|
import read from '../../common/read-notification';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '通知一覧を取得します。',
|
||||||
|
'en-US': 'Get notifications.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: true,
|
||||||
|
|
||||||
|
kind: 'account-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
following: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
|
||||||
|
markAsRead: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get notifications
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'following' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [following = false, followingError] =
|
if (psErr) return rej(psErr);
|
||||||
$.bool.optional.get(params.following);
|
|
||||||
if (followingError) return rej('invalid following param');
|
|
||||||
|
|
||||||
// Get 'markAsRead' parameter
|
|
||||||
const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
|
|
||||||
if (markAsReadErr) return rej('invalid markAsRead 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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +71,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (following) {
|
if (ps.following) {
|
||||||
// ID list of the user itself and other users who the user follows
|
// ID list of the user itself and other users who the user follows
|
||||||
const followingIds = await getFriendIds(user._id);
|
const followingIds = await getFriendIds(user._id);
|
||||||
|
|
||||||
|
@ -64,29 +82,27 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const notifications = await Notification
|
const notifications = await Notification
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(notifications));
|
res(await packMany(notifications));
|
||||||
|
|
||||||
// Mark all as read
|
// Mark all as read
|
||||||
if (notifications.length > 0 && markAsRead) {
|
if (notifications.length > 0 && ps.markAsRead) {
|
||||||
read(user._id, notifications);
|
read(user._id, notifications);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import { pack } from '../../../../models/user';
|
import { pack } from '../../../../models/user';
|
||||||
import { addPinned } from '../../../../services/i/pin';
|
import { addPinned } from '../../../../services/i/pin';
|
||||||
|
@ -16,12 +16,14 @@ export const meta = {
|
||||||
kind: 'account-write',
|
kind: 'account-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID'
|
'en-US': 'Target note ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,37 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Signin, { pack } from '../../../../models/signin';
|
import Signin, { pack } from '../../../../models/signin';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
secure: true
|
|
||||||
|
secure: true,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) return rej(psErr);
|
||||||
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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
// Check if both of sinceId and untilId is specified
|
||||||
if (sinceId && untilId) {
|
if (ps.sinceId && ps.untilId) {
|
||||||
return rej('cannot set sinceId and untilId');
|
return rej('cannot set sinceId and untilId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,25 +43,23 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const history = await Signin
|
const history = await Signin
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
// Serialize
|
||||||
res(await Promise.all(history.map(async record =>
|
res(await Promise.all(history.map(record => pack(record))));
|
||||||
await pack(record))));
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import { pack } from '../../../../models/user';
|
import { pack } from '../../../../models/user';
|
||||||
import { removePinned } from '../../../../services/i/pin';
|
import { removePinned } from '../../../../services/i/pin';
|
||||||
|
@ -16,12 +16,14 @@ export const meta = {
|
||||||
kind: 'account-write',
|
kind: 'account-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID'
|
'en-US': 'Target note ID'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user';
|
import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack, ILocalUser } from '../../../../models/user';
|
||||||
import { publishMainStream } from '../../../../stream';
|
import { publishMainStream } from '../../../../stream';
|
||||||
import DriveFile from '../../../../models/drive-file';
|
import DriveFile from '../../../../models/drive-file';
|
||||||
|
@ -19,83 +19,99 @@ export const meta = {
|
||||||
kind: 'account-write',
|
kind: 'account-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
name: $.str.optional.nullable.pipe(isValidName).note({
|
name: {
|
||||||
|
validator: $.str.optional.nullable.pipe(isValidName),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '名前(ハンドルネームやニックネーム)'
|
'ja-JP': '名前(ハンドルネームやニックネーム)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
description: $.str.optional.nullable.pipe(isValidDescription).note({
|
description: {
|
||||||
|
validator: $.str.optional.nullable.pipe(isValidDescription),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アカウントの説明や自己紹介'
|
'ja-JP': 'アカウントの説明や自己紹介'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
location: $.str.optional.nullable.pipe(isValidLocation).note({
|
location: {
|
||||||
|
validator: $.str.optional.nullable.pipe(isValidLocation),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '住んでいる地域、所在'
|
'ja-JP': '住んでいる地域、所在'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
birthday: $.str.optional.nullable.pipe(isValidBirthday).note({
|
birthday: {
|
||||||
|
validator: $.str.optional.nullable.pipe(isValidBirthday),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '誕生日 (YYYY-MM-DD形式)'
|
'ja-JP': '誕生日 (YYYY-MM-DD形式)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
avatarId: $.type(ID).optional.nullable.note({
|
avatarId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アイコンに設定する画像のドライブファイルID'
|
'ja-JP': 'アイコンに設定する画像のドライブファイルID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
bannerId: $.type(ID).optional.nullable.note({
|
bannerId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'バナーに設定する画像のドライブファイルID'
|
'ja-JP': 'バナーに設定する画像のドライブファイルID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
wallpaperId: $.type(ID).optional.nullable.note({
|
wallpaperId: {
|
||||||
|
validator: $.type(ID).optional.nullable,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '壁紙に設定する画像のドライブファイルID'
|
'ja-JP': '壁紙に設定する画像のドライブファイルID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
isLocked: $.bool.optional.note({
|
isLocked: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '鍵アカウントか否か'
|
'ja-JP': '鍵アカウントか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
carefulBot: $.bool.optional.note({
|
carefulBot: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Botからのフォローを承認制にするか'
|
'ja-JP': 'Botからのフォローを承認制にするか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
isBot: $.bool.optional.note({
|
isBot: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Botか否か'
|
'ja-JP': 'Botか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
isCat: $.bool.optional.note({
|
isCat: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '猫か否か'
|
'ja-JP': '猫か否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
autoWatch: $.bool.optional.note({
|
autoWatch: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '投稿の自動ウォッチをするか否か'
|
'ja-JP': '投稿の自動ウォッチをするか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
alwaysMarkNsfw: $.bool.optional.note({
|
alwaysMarkNsfw: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アップロードするメディアをデフォルトで「閲覧注意」として設定するか'
|
'ja-JP': 'アップロードするメディアをデフォルトで「閲覧注意」として設定するか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Message from '../../../../models/messaging-message';
|
import Message from '../../../../models/messaging-message';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import { pack } from '../../../../models/messaging-message';
|
import { pack } from '../../../../models/messaging-message';
|
||||||
import read from '../../common/read-messaging-message';
|
import read from '../../common/read-messaging-message';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -12,17 +13,48 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'messaging-read'
|
kind: 'messaging-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
markAsRead: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (recipientIdErr) return rej('invalid userId param');
|
|
||||||
|
// Check if both of sinceId and untilId is specified
|
||||||
|
if (ps.sinceId && ps.untilId) {
|
||||||
|
return rej('cannot set sinceId and untilId');
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch recipient
|
// Fetch recipient
|
||||||
const recipient = await User.findOne({
|
const recipient = await User.findOne({
|
||||||
_id: recipientId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
@ -33,27 +65,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
return rej('user not found');
|
return rej('user not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'markAsRead' parameter
|
|
||||||
const [markAsRead = true, markAsReadErr] = $.bool.optional.get(params.markAsRead);
|
|
||||||
if (markAsReadErr) return rej('invalid markAsRead 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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
|
||||||
if (sinceId && untilId) {
|
|
||||||
return rej('cannot set sinceId and untilId');
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
$or: [{
|
$or: [{
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
|
@ -68,36 +79,33 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: -1
|
_id: -1
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sinceId) {
|
if (ps.sinceId) {
|
||||||
sort._id = 1;
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$gt: sinceId
|
$gt: ps.sinceId
|
||||||
};
|
};
|
||||||
} else if (untilId) {
|
} else if (ps.untilId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: untilId
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const messages = await Message
|
const messages = await Message
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit,
|
limit: ps.limit,
|
||||||
sort: sort
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// Serialize
|
res(await Promise.all(messages.map(message => pack(message, user, {
|
||||||
res(await Promise.all(messages.map(async message =>
|
populateRecipient: false
|
||||||
await pack(message, user, {
|
}))));
|
||||||
populateRecipient: false
|
|
||||||
}))));
|
|
||||||
|
|
||||||
if (messages.length === 0) {
|
if (messages.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark all as read
|
// Mark all as read
|
||||||
if (markAsRead) {
|
if (ps.markAsRead) {
|
||||||
read(user._id, recipient._id, messages);
|
read(user._id, recipient._id, messages);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Message from '../../../../../models/messaging-message';
|
import Message from '../../../../../models/messaging-message';
|
||||||
import { isValidText } from '../../../../../models/messaging-message';
|
import { isValidText } from '../../../../../models/messaging-message';
|
||||||
import History from '../../../../../models/messaging-history';
|
import History from '../../../../../models/messaging-history';
|
||||||
|
@ -9,6 +9,7 @@ import { pack } from '../../../../../models/messaging-message';
|
||||||
import { publishMainStream } from '../../../../../stream';
|
import { publishMainStream } from '../../../../../stream';
|
||||||
import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../stream';
|
import { publishMessagingStream, publishMessagingIndexStream } from '../../../../../stream';
|
||||||
import pushSw from '../../../../../push-sw';
|
import pushSw from '../../../../../push-sw';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -18,22 +19,37 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'messaging-write'
|
kind: 'messaging-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
text: {
|
||||||
|
validator: $.str.optional.pipe(isValidText)
|
||||||
|
},
|
||||||
|
|
||||||
|
fileId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (recipientIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Myself
|
// Myself
|
||||||
if (recipientId.equals(user._id)) {
|
if (ps.userId.equals(user._id)) {
|
||||||
return rej('cannot send message to myself');
|
return rej('cannot send message to myself');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch recipient
|
// Fetch recipient
|
||||||
const recipient = await User.findOne({
|
const recipient = await User.findOne({
|
||||||
_id: recipientId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
@ -44,18 +60,10 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
return rej('user not found');
|
return rej('user not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'text' parameter
|
|
||||||
const [text, textErr] = $.str.optional.pipe(isValidText).get(params.text);
|
|
||||||
if (textErr) return rej('invalid text');
|
|
||||||
|
|
||||||
// Get 'fileId' parameter
|
|
||||||
const [fileId, fileIdErr] = $.type(ID).optional.get(params.fileId);
|
|
||||||
if (fileIdErr) return rej('invalid fileId param');
|
|
||||||
|
|
||||||
let file = null;
|
let file = null;
|
||||||
if (fileId !== undefined) {
|
if (ps.fileId != null) {
|
||||||
file = await DriveFile.findOne({
|
file = await DriveFile.findOne({
|
||||||
_id: fileId,
|
_id: ps.fileId,
|
||||||
'metadata.userId': user._id
|
'metadata.userId': user._id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,7 +73,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
}
|
}
|
||||||
|
|
||||||
// テキストが無いかつ添付ファイルも無かったらエラー
|
// テキストが無いかつ添付ファイルも無かったらエラー
|
||||||
if (text === undefined && file === null) {
|
if (ps.text == null && file == null) {
|
||||||
return rej('text or file is required');
|
return rej('text or file is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +82,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
fileId: file ? file._id : undefined,
|
fileId: file ? file._id : undefined,
|
||||||
recipientId: recipient._id,
|
recipientId: recipient._id,
|
||||||
text: text ? text.trim() : undefined,
|
text: ps.text ? ps.text.trim() : undefined,
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
isRead: false
|
isRead: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Message from '../../../../../models/messaging-message';
|
import Message from '../../../../../models/messaging-message';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import read from '../../../common/read-messaging-message';
|
import read from '../../../common/read-messaging-message';
|
||||||
|
@ -15,12 +15,14 @@ export const meta = {
|
||||||
kind: 'messaging-write',
|
kind: 'messaging-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
messageId: $.type(ID).note({
|
messageId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '既読にするメッセージのID',
|
'ja-JP': '既読にするメッセージのID',
|
||||||
'en-US': 'The ID of a message that you want to mark as read'
|
'en-US': 'The ID of a message that you want to mark as read'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,24 +11,30 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'account/write'
|
kind: 'account/write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
const muter = user;
|
const muter = user;
|
||||||
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// 自分自身
|
// 自分自身
|
||||||
if (user._id.equals(userId)) {
|
if (user._id.equals(ps.userId)) {
|
||||||
return rej('mutee is yourself');
|
return rej('mutee is yourself');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mutee
|
// Get mutee
|
||||||
const mutee = await User.findOne({
|
const mutee = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
data: false,
|
data: false,
|
||||||
|
@ -56,6 +63,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
muteeId: mutee._id,
|
muteeId: mutee._id,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,24 +11,30 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'account/write'
|
kind: 'account/write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
const muter = user;
|
const muter = user;
|
||||||
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Check if the mutee is yourself
|
// Check if the mutee is yourself
|
||||||
if (user._id.equals(userId)) {
|
if (user._id.equals(ps.userId)) {
|
||||||
return rej('mutee is yourself');
|
return rej('mutee is yourself');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mutee
|
// Get mutee
|
||||||
const mutee = await User.findOne({
|
const mutee = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
data: false,
|
data: false,
|
||||||
|
@ -54,6 +61,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
_id: exist._id
|
_id: exist._id
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Mute, { packMany } from '../../../../models/mute';
|
import Mute, { packMany } from '../../../../models/mute';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
|
@ -14,15 +14,20 @@ export const meta = {
|
||||||
kind: 'account/read',
|
kind: 'account/read',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 30
|
default: 30
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../misc/cafy-id';
|
||||||
import Note, { packMany } from '../../../models/note';
|
import Note, { packMany } from '../../../models/note';
|
||||||
import getParams from '../get-params';
|
import getParams from '../get-params';
|
||||||
|
|
||||||
|
@ -8,49 +8,62 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
local: $.bool.optional.note({
|
local: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ローカルの投稿に限定するか否か'
|
'ja-JP': 'ローカルの投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
reply: $.bool.optional.note({
|
reply: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '返信に限定するか否か'
|
'ja-JP': '返信に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
renote: $.bool.optional.note({
|
renote: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteに限定するか否か'
|
'ja-JP': 'Renoteに限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
media: $.bool.optional.note({
|
media: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
poll: $.bool.optional.note({
|
poll: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アンケートが添付された投稿に限定するか否か'
|
'ja-JP': 'アンケートが添付された投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({}),
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({}),
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,41 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note, { packMany, INote } from '../../../../models/note';
|
import Note, { packMany, INote } from '../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定した投稿の文脈を取得します。',
|
||||||
|
'en-US': 'Show conversation of a note.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
offset: {
|
||||||
|
validator: $.num.optional.min(0),
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Show conversation of a note
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'noteId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
if (psErr) return rej(psErr);
|
||||||
if (noteIdErr) return rej('invalid noteId param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'offset' parameter
|
|
||||||
const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
|
|
||||||
if (offsetErr) return rej('invalid offset param');
|
|
||||||
|
|
||||||
// Lookup note
|
// Lookup note
|
||||||
const note = await Note.findOne({
|
const note = await Note.findOne({
|
||||||
_id: noteId
|
_id: ps.noteId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (note === null) {
|
if (note === null) {
|
||||||
|
@ -34,11 +49,11 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
i++;
|
i++;
|
||||||
const p = await Note.findOne({ _id: id });
|
const p = await Note.findOne({ _id: id });
|
||||||
|
|
||||||
if (i > offset) {
|
if (i > ps.offset) {
|
||||||
conversation.push(p);
|
conversation.push(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversation.length == limit) {
|
if (conversation.length == ps.limit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +66,5 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
await get(note.replyId);
|
await get(note.replyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(conversation, user));
|
res(await packMany(conversation, user));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform, transformMany } from '../../../../misc/cafy-id';
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
|
import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
|
||||||
import User, { ILocalUser, IUser } from '../../../../models/user';
|
import User, { ILocalUser, IUser } from '../../../../models/user';
|
||||||
|
@ -24,84 +24,106 @@ export const meta = {
|
||||||
kind: 'note-write',
|
kind: 'note-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({
|
visibility: {
|
||||||
|
validator: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']),
|
||||||
default: 'public',
|
default: 'public',
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '投稿の公開範囲'
|
'ja-JP': '投稿の公開範囲'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
visibleUserIds: $.arr($.type(ID)).optional.unique().min(1).note({
|
visibleUserIds: {
|
||||||
|
validator: $.arr($.type(ID)).optional.unique().min(1),
|
||||||
|
transform: transformMany,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー'
|
'ja-JP': '(投稿の公開範囲が specified の場合)投稿を閲覧できるユーザー'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
text: $.str.optional.nullable.pipe(isValidText).note({
|
text: {
|
||||||
default: null,
|
validator: $.str.optional.nullable.pipe(isValidText),
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '投稿内容'
|
'ja-JP': '投稿内容'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
cw: $.str.optional.nullable.pipe(isValidCw).note({
|
cw: {
|
||||||
|
validator: $.str.optional.nullable.pipe(isValidCw),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。'
|
'ja-JP': 'コンテンツの警告。このパラメータを指定すると設定したテキストで投稿のコンテンツを隠す事が出来ます。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
viaMobile: $.bool.optional.note({
|
viaMobile: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: false,
|
default: false,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'モバイルデバイスからの投稿か否か。'
|
'ja-JP': 'モバイルデバイスからの投稿か否か。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
geo: $.obj({
|
geo: {
|
||||||
coordinates: $.arr().length(2)
|
validator: $.obj({
|
||||||
.item(0, $.num.range(-180, 180))
|
coordinates: $.arr().length(2)
|
||||||
.item(1, $.num.range(-90, 90)),
|
.item(0, $.num.range(-180, 180))
|
||||||
altitude: $.num.nullable,
|
.item(1, $.num.range(-90, 90)),
|
||||||
accuracy: $.num.nullable,
|
altitude: $.num.nullable,
|
||||||
altitudeAccuracy: $.num.nullable,
|
accuracy: $.num.nullable,
|
||||||
heading: $.num.nullable.range(0, 360),
|
altitudeAccuracy: $.num.nullable,
|
||||||
speed: $.num.nullable
|
heading: $.num.nullable.range(0, 360),
|
||||||
}).optional.nullable.strict().note({
|
speed: $.num.nullable
|
||||||
|
}).optional.nullable.strict(),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '位置情報'
|
'ja-JP': '位置情報'
|
||||||
},
|
},
|
||||||
ref: 'geo'
|
ref: 'geo'
|
||||||
}),
|
},
|
||||||
|
|
||||||
fileIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
|
fileIds: {
|
||||||
|
validator: $.arr($.type(ID)).optional.unique().range(1, 4),
|
||||||
|
transform: transformMany,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '添付するファイル'
|
'ja-JP': '添付するファイル'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
|
mediaIds: {
|
||||||
|
validator: $.arr($.type(ID)).optional.unique().range(1, 4),
|
||||||
|
transform: transformMany,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '添付するファイル (このパラメータは廃止予定です。代わりに fileIds を使ってください。)'
|
'ja-JP': '添付するファイル (このパラメータは廃止予定です。代わりに fileIds を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
renoteId: $.type(ID).optional.note({
|
replyId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '返信対象'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renoteId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renote対象'
|
'ja-JP': 'Renote対象'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
poll: $.obj({
|
poll: {
|
||||||
choices: $.arr($.str)
|
validator: $.obj({
|
||||||
.unique()
|
choices: $.arr($.str)
|
||||||
.range(2, 10)
|
.unique()
|
||||||
.each(c => c.length > 0 && c.length < 50)
|
.range(2, 10)
|
||||||
}).optional.strict().note({
|
.each(c => c.length > 0 && c.length < 50)
|
||||||
|
}).optional.strict(),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アンケート'
|
'ja-JP': 'アンケート'
|
||||||
},
|
},
|
||||||
ref: 'poll'
|
ref: 'poll'
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
res: {
|
res: {
|
||||||
|
@ -117,15 +139,12 @@ export const meta = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a note
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
|
||||||
const [ps, psErr] = getParams(meta, params);
|
const [ps, psErr] = getParams(meta, params);
|
||||||
if (psErr) return rej(psErr);
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
let visibleUsers: IUser[] = [];
|
let visibleUsers: IUser[] = [];
|
||||||
if (ps.visibleUserIds !== undefined) {
|
if (ps.visibleUserIds) {
|
||||||
visibleUsers = await Promise.all(ps.visibleUserIds.map(id => User.findOne({
|
visibleUsers = await Promise.all(ps.visibleUserIds.map(id => User.findOne({
|
||||||
_id: id
|
_id: id
|
||||||
})));
|
})));
|
||||||
|
@ -145,7 +164,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
}
|
}
|
||||||
|
|
||||||
let renote: INote = null;
|
let renote: INote = null;
|
||||||
if (ps.renoteId !== undefined) {
|
if (ps.renoteId != null) {
|
||||||
// Fetch renote to note
|
// Fetch renote to note
|
||||||
renote = await Note.findOne({
|
renote = await Note.findOne({
|
||||||
_id: ps.renoteId
|
_id: ps.renoteId
|
||||||
|
@ -158,15 +177,11 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'replyId' parameter
|
|
||||||
const [replyId, replyIdErr] = $.type(ID).optional.get(params.replyId);
|
|
||||||
if (replyIdErr) return rej('invalid replyId');
|
|
||||||
|
|
||||||
let reply: INote = null;
|
let reply: INote = null;
|
||||||
if (replyId !== undefined) {
|
if (ps.replyId != null) {
|
||||||
// Fetch reply
|
// Fetch reply
|
||||||
reply = await Note.findOne({
|
reply = await Note.findOne({
|
||||||
_id: replyId
|
_id: ps.replyId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (reply === null) {
|
if (reply === null) {
|
||||||
|
@ -188,7 +203,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
}
|
}
|
||||||
|
|
||||||
// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
|
// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
|
||||||
if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) {
|
if ((ps.text == null) && files === null && renote === null && ps.poll == null) {
|
||||||
return rej('text, fileIds, renoteId or poll is required');
|
return rej('text, fileIds, renoteId or poll is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import deleteNote from '../../../../services/note/delete';
|
import deleteNote from '../../../../services/note/delete';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
|
@ -17,12 +17,14 @@ export const meta = {
|
||||||
kind: 'note-write',
|
kind: 'note-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID.'
|
'en-US': 'Target note ID.'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Favorite from '../../../../../models/favorite';
|
import Favorite from '../../../../../models/favorite';
|
||||||
import Note from '../../../../../models/note';
|
import Note from '../../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
@ -17,12 +17,14 @@ export const meta = {
|
||||||
kind: 'favorite-write',
|
kind: 'favorite-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID.'
|
'en-US': 'Target note ID.'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Favorite from '../../../../../models/favorite';
|
import Favorite from '../../../../../models/favorite';
|
||||||
import Note from '../../../../../models/note';
|
import Note from '../../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
@ -17,12 +17,14 @@ export const meta = {
|
||||||
kind: 'favorite-write',
|
kind: 'favorite-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID.'
|
'en-US': 'Target note ID.'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,13 @@ export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 30).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 30),
|
||||||
default: 10,
|
default: 10,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数'
|
'ja-JP': '最大数'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { packMany } from '../../../../models/note';
|
import { packMany } from '../../../../models/note';
|
||||||
|
@ -12,29 +12,42 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
mediaOnly: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({}),
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({}),
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({}),
|
sinceDate: {
|
||||||
|
validator: $.num.optional
|
||||||
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({}),
|
untilDate: {
|
||||||
|
validator: $.num.optional
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { getFriends } from '../../common/get-friends';
|
import { getFriends } from '../../common/get-friends';
|
||||||
|
@ -13,69 +13,81 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10,
|
default: 10,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数'
|
'ja-JP': '最大数'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({
|
sinceDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({
|
untilDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeMyRenotes: $.bool.optional.note({
|
includeMyRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeRenotedMyNotes: $.bool.optional.note({
|
includeRenotedMyNotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeLocalRenotes: $.bool.optional.note({
|
includeLocalRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
mediaOnly: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { packMany } from '../../../../models/note';
|
import { packMany } from '../../../../models/note';
|
||||||
|
@ -12,42 +12,57 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
mediaOnly: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
fileType: $.arr($.str).optional.note({
|
fileType: {
|
||||||
|
validator: $.arr($.str).optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します'
|
'ja-JP': '指定された種類のファイルが添付された投稿のみを取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
excludeNsfw: $.bool.optional.note({
|
excludeNsfw: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: false,
|
default: false,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、NSFW指定されたファイルを除外します(fileTypeが指定されている場合のみ有効)'
|
'ja-JP': 'true にすると、NSFW指定されたファイルを除外します(fileTypeが指定されている場合のみ有効)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({}),
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({}),
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({}),
|
sinceDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({}),
|
untilDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import { getFriendIds } from '../../common/get-friends';
|
||||||
import { packMany } from '../../../../models/note';
|
import { packMany } from '../../../../models/note';
|
||||||
|
@ -15,22 +15,29 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
following: $.bool.optional.note({
|
following: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: false
|
default: false
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
visibility: $.str.optional.note({
|
visibility: {
|
||||||
}),
|
validator: $.str.optional,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Vote from '../../../../../models/poll-vote';
|
import Vote from '../../../../../models/poll-vote';
|
||||||
import Note from '../../../../../models/note';
|
import Note from '../../../../../models/note';
|
||||||
import Watching from '../../../../../models/note-watching';
|
import Watching from '../../../../../models/note-watching';
|
||||||
|
@ -6,6 +6,7 @@ import watch from '../../../../../services/note/watch';
|
||||||
import { publishNoteStream } from '../../../../../stream';
|
import { publishNoteStream } from '../../../../../stream';
|
||||||
import notify from '../../../../../notify';
|
import notify from '../../../../../notify';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -15,17 +16,27 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'vote-write'
|
kind: 'vote-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
choice: {
|
||||||
|
validator: $.num
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'noteId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
if (psErr) return rej(psErr);
|
||||||
if (noteIdErr) return rej('invalid noteId param');
|
|
||||||
|
|
||||||
// Get votee
|
// Get votee
|
||||||
const note = await Note.findOne({
|
const note = await Note.findOne({
|
||||||
_id: noteId
|
_id: ps.noteId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (note === null) {
|
if (note === null) {
|
||||||
|
@ -36,12 +47,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
return rej('poll not found');
|
return rej('poll not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'choice' parameter
|
if (!note.poll.choices.some(x => x.id == ps.choice)) return rej('invalid choice param');
|
||||||
const [choice, choiceError] =
|
|
||||||
$.num
|
|
||||||
.pipe(c => note.poll.choices.some(x => x.id == c))
|
|
||||||
.get(params.choice);
|
|
||||||
if (choiceError) return rej('invalid choice param');
|
|
||||||
|
|
||||||
// if already voted
|
// if already voted
|
||||||
const exist = await Vote.findOne({
|
const exist = await Vote.findOne({
|
||||||
|
@ -58,14 +64,14 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
noteId: note._id,
|
noteId: note._id,
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
choice: choice
|
choice: ps.choice
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
res();
|
res();
|
||||||
|
|
||||||
const inc: any = {};
|
const inc: any = {};
|
||||||
inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == choice)}.votes`] = 1;
|
inc[`poll.choices.${note.poll.choices.findIndex(c => c.id == ps.choice)}.votes`] = 1;
|
||||||
|
|
||||||
// Increment votes count
|
// Increment votes count
|
||||||
await Note.update({ _id: note._id }, {
|
await Note.update({ _id: note._id }, {
|
||||||
|
@ -73,14 +79,14 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
});
|
});
|
||||||
|
|
||||||
publishNoteStream(note._id, 'pollVoted', {
|
publishNoteStream(note._id, 'pollVoted', {
|
||||||
choice: choice,
|
choice: ps.choice,
|
||||||
userId: user._id.toHexString()
|
userId: user._id.toHexString()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Notify
|
// Notify
|
||||||
notify(note.userId, user._id, 'poll_vote', {
|
notify(note.userId, user._id, 'poll_vote', {
|
||||||
noteId: note._id,
|
noteId: note._id,
|
||||||
choice: choice
|
choice: ps.choice
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch watchers
|
// Fetch watchers
|
||||||
|
@ -99,7 +105,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
watchers.forEach(watcher => {
|
watchers.forEach(watcher => {
|
||||||
notify(watcher.userId, user._id, 'poll_vote', {
|
notify(watcher.userId, user._id, 'poll_vote', {
|
||||||
noteId: note._id,
|
noteId: note._id,
|
||||||
choice: choice
|
choice: ps.choice
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Reaction, { pack } from '../../../../models/note-reaction';
|
import Reaction, { pack } from '../../../../models/note-reaction';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
@ -13,26 +13,34 @@ export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'The ID of the target note'
|
'en-US': 'The ID of the target note'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
|
|
||||||
offset: $.num.optional.note({
|
offset: {
|
||||||
|
validator: $.num.optional,
|
||||||
default: 0
|
default: 0
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
}),
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Note from '../../../../../models/note';
|
import Note from '../../../../../models/note';
|
||||||
import create from '../../../../../services/note/reaction/create';
|
import create from '../../../../../services/note/reaction/create';
|
||||||
import { validateReaction } from '../../../../../models/note-reaction';
|
import { validateReaction } from '../../../../../models/note-reaction';
|
||||||
|
@ -18,17 +18,20 @@ export const meta = {
|
||||||
kind: 'reaction-write',
|
kind: 'reaction-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿'
|
'ja-JP': '対象の投稿'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
reaction: $.str.pipe(validateReaction.ok).note({
|
reaction: {
|
||||||
|
validator: $.str.pipe(validateReaction.ok),
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'リアクションの種類'
|
'ja-JP': 'リアクションの種類'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import Reaction from '../../../../../models/note-reaction';
|
import Reaction from '../../../../../models/note-reaction';
|
||||||
import Note from '../../../../../models/note';
|
import Note from '../../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -11,17 +12,23 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'reaction-write'
|
kind: 'reaction-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'noteId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
if (psErr) return rej(psErr);
|
||||||
if (noteIdErr) return rej('invalid noteId param');
|
|
||||||
|
|
||||||
// Fetch unreactee
|
// Fetch unreactee
|
||||||
const note = await Note.findOne({
|
const note = await Note.findOne({
|
||||||
_id: noteId
|
_id: ps.noteId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (note === null) {
|
if (note === null) {
|
||||||
|
@ -48,7 +55,6 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send response
|
|
||||||
res();
|
res();
|
||||||
|
|
||||||
const dec: any = {};
|
const dec: any = {};
|
||||||
|
|
81
src/server/api/endpoints/notes/renotes.ts
Normal file
81
src/server/api/endpoints/notes/renotes.ts
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
|
import Note, { packMany } from '../../../../models/note';
|
||||||
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定した投稿のRenote一覧を取得します。',
|
||||||
|
'en-US': 'Show a renotes of a note.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
|
const [ps, psErr] = getParams(meta, params);
|
||||||
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
|
// Check if both of sinceId and untilId is specified
|
||||||
|
if (ps.sinceId && ps.untilId) {
|
||||||
|
return rej('cannot set sinceId and untilId');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup note
|
||||||
|
const note = await Note.findOne({
|
||||||
|
_id: ps.noteId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (note === null) {
|
||||||
|
return rej('note not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const sort = {
|
||||||
|
_id: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
renoteId: note._id
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
if (ps.sinceId) {
|
||||||
|
sort._id = 1;
|
||||||
|
query._id = {
|
||||||
|
$gt: ps.sinceId
|
||||||
|
};
|
||||||
|
} else if (ps.untilId) {
|
||||||
|
query._id = {
|
||||||
|
$lt: ps.untilId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const renotes = await Note
|
||||||
|
.find(query, {
|
||||||
|
limit: ps.limit,
|
||||||
|
sort: sort
|
||||||
|
});
|
||||||
|
|
||||||
|
res(await packMany(renotes, user));
|
||||||
|
});
|
|
@ -1,34 +1,48 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note, { packMany } from '../../../../models/note';
|
import Note, { packMany } from '../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定した投稿への返信を取得します。',
|
||||||
|
'en-US': 'Get replies of a note.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
offset: {
|
||||||
|
validator: $.num.optional.min(0),
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get replies of a note
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'noteId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
if (psErr) return rej(psErr);
|
||||||
if (noteIdErr) return rej('invalid noteId param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'offset' parameter
|
|
||||||
const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset);
|
|
||||||
if (offsetErr) return rej('invalid offset param');
|
|
||||||
|
|
||||||
// Lookup note
|
// Lookup note
|
||||||
const note = await Note.findOne({
|
const note = await Note.findOne({
|
||||||
_id: noteId
|
_id: ps.noteId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (note === null) {
|
if (note === null) {
|
||||||
return rej('note not found');
|
return rej('note not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const ids = (note._replyIds || []).slice(offset, offset + limit);
|
const ids = (note._replyIds || []).slice(ps.offset, ps.offset + ps.limit);
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(ids, user));
|
res(await packMany(ids, user));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
|
||||||
import Note, { packMany } from '../../../../models/note';
|
|
||||||
import { ILocalUser } from '../../../../models/user';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a renotes of a note
|
|
||||||
*/
|
|
||||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
|
||||||
// Get 'noteId' parameter
|
|
||||||
const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
|
|
||||||
if (noteIdErr) return rej('invalid noteId 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');
|
|
||||||
|
|
||||||
// Check if both of sinceId and untilId is specified
|
|
||||||
if (sinceId && untilId) {
|
|
||||||
return rej('cannot set sinceId and untilId');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup note
|
|
||||||
const note = await Note.findOne({
|
|
||||||
_id: noteId
|
|
||||||
});
|
|
||||||
|
|
||||||
if (note === null) {
|
|
||||||
return rej('note not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const sort = {
|
|
||||||
_id: -1
|
|
||||||
};
|
|
||||||
const query = {
|
|
||||||
renoteId: note._id
|
|
||||||
} as any;
|
|
||||||
if (sinceId) {
|
|
||||||
sort._id = 1;
|
|
||||||
query._id = {
|
|
||||||
$gt: sinceId
|
|
||||||
};
|
|
||||||
} else if (untilId) {
|
|
||||||
query._id = {
|
|
||||||
$lt: untilId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue query
|
|
||||||
const renotes = await Note
|
|
||||||
.find(query, {
|
|
||||||
limit: limit,
|
|
||||||
sort: sort
|
|
||||||
});
|
|
||||||
|
|
||||||
// Serialize
|
|
||||||
res(await packMany(renotes, user));
|
|
||||||
});
|
|
|
@ -1,11 +1,10 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import { getFriendIds } from '../../common/get-friends';
|
||||||
import { packMany } from '../../../../models/note';
|
import { packMany } from '../../../../models/note';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
import { erase } from '../../../../prelude/array';
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -13,99 +12,94 @@ export const meta = {
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
tag: $.str.optional.note({
|
tag: {
|
||||||
|
validator: $.str.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'タグ'
|
'ja-JP': 'タグ'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
query: $.arr($.arr($.str)).optional.note({
|
query: {
|
||||||
|
validator: $.arr($.arr($.str)).optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'クエリ'
|
'ja-JP': 'クエリ'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeUserIds: $.arr($.type(ID)).optional.note({
|
following: {
|
||||||
default: []
|
validator: $.bool.optional.nullable,
|
||||||
}),
|
default: null as any
|
||||||
|
},
|
||||||
|
|
||||||
excludeUserIds: $.arr($.type(ID)).optional.note({
|
mute: {
|
||||||
default: []
|
validator: $.str.optional,
|
||||||
}),
|
|
||||||
|
|
||||||
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'
|
default: 'mute_all'
|
||||||
}),
|
},
|
||||||
|
|
||||||
reply: $.bool.optional.nullable.note({
|
|
||||||
default: null,
|
|
||||||
|
|
||||||
|
reply: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '返信に限定するか否か'
|
'ja-JP': '返信に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
renote: $.bool.optional.nullable.note({
|
|
||||||
default: null,
|
|
||||||
|
|
||||||
|
renote: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteに限定するか否か'
|
'ja-JP': 'Renoteに限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
media: $.bool.optional.nullable.note({
|
|
||||||
default: null,
|
|
||||||
|
|
||||||
|
media: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'ファイルが添付された投稿に限定するか否か (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
poll: $.bool.optional.nullable.note({
|
|
||||||
default: null,
|
|
||||||
|
|
||||||
|
poll: {
|
||||||
|
validator: $.bool.optional.nullable,
|
||||||
|
default: null as any,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'アンケートが添付された投稿に限定するか否か'
|
'ja-JP': 'アンケートが添付された投稿に限定するか否か'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({
|
sinceDate: {
|
||||||
}),
|
validator: $.num.optional,
|
||||||
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({
|
untilDate: {
|
||||||
}),
|
validator: $.num.optional,
|
||||||
|
},
|
||||||
|
|
||||||
offset: $.num.optional.min(0).note({
|
offset: {
|
||||||
|
validator: $.num.optional.min(0),
|
||||||
default: 0
|
default: 0
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 30).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 30),
|
||||||
default: 10
|
default: 10
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,28 +107,6 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
const [ps, psErr] = getParams(meta, params);
|
const [ps, psErr] = getParams(meta, params);
|
||||||
if (psErr) return rej(psErr);
|
if (psErr) return rej(psErr);
|
||||||
|
|
||||||
if (ps.includeUserUsernames != null) {
|
|
||||||
const ids = erase(null, await Promise.all(ps.includeUserUsernames.map(async (username) => {
|
|
||||||
const _user = await User.findOne({
|
|
||||||
usernameLower: username.toLowerCase()
|
|
||||||
});
|
|
||||||
return _user ? _user._id : null;
|
|
||||||
})));
|
|
||||||
|
|
||||||
ids.forEach(id => ps.includeUserIds.push(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ps.excludeUserUsernames != null) {
|
|
||||||
const ids = erase(null, await Promise.all(ps.excludeUserUsernames.map(async (username) => {
|
|
||||||
const _user = await User.findOne({
|
|
||||||
usernameLower: username.toLowerCase()
|
|
||||||
});
|
|
||||||
return _user ? _user._id : null;
|
|
||||||
})));
|
|
||||||
|
|
||||||
ids.forEach(id => ps.excludeUserIds.push(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
const q: any = {
|
const q: any = {
|
||||||
$and: [ps.tag ? {
|
$and: [ps.tag ? {
|
||||||
tagsLower: ps.tag.toLowerCase()
|
tagsLower: ps.tag.toLowerCase()
|
||||||
|
@ -150,20 +122,6 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
|
|
||||||
const push = (x: any) => q.$and.push(x);
|
const push = (x: any) => q.$and.push(x);
|
||||||
|
|
||||||
if (ps.includeUserIds && ps.includeUserIds.length != 0) {
|
|
||||||
push({
|
|
||||||
userId: {
|
|
||||||
$in: ps.includeUserIds
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (ps.excludeUserIds && ps.excludeUserIds.length != 0) {
|
|
||||||
push({
|
|
||||||
userId: {
|
|
||||||
$nin: ps.excludeUserIds
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ps.following != null && me != null) {
|
if (ps.following != null && me != null) {
|
||||||
const ids = await getFriendIds(me._id, false);
|
const ids = await getFriendIds(me._id, false);
|
||||||
push({
|
push({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note, { pack } from '../../../../models/note';
|
import Note, { pack } from '../../../../models/note';
|
||||||
import { ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import getParams from '../../get-params';
|
import getParams from '../../get-params';
|
||||||
|
@ -14,12 +14,14 @@ export const meta = {
|
||||||
requireCredential: false,
|
requireCredential: false,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
noteId: $.type(ID).note({
|
noteId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象の投稿のID',
|
'ja-JP': '対象の投稿のID',
|
||||||
'en-US': 'Target note ID.'
|
'en-US': 'Target note ID.'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { getFriends } from '../../common/get-friends';
|
import { getFriends } from '../../common/get-friends';
|
||||||
|
@ -16,69 +16,81 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10,
|
default: 10,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数'
|
'ja-JP': '最大数'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({
|
sinceDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({
|
untilDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeMyRenotes: $.bool.optional.note({
|
includeMyRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeRenotedMyNotes: $.bool.optional.note({
|
includeRenotedMyNotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeLocalRenotes: $.bool.optional.note({
|
includeLocalRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
mediaOnly: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute from '../../../../models/mute';
|
||||||
import { packMany } from '../../../../models/note';
|
import { packMany } from '../../../../models/note';
|
||||||
|
@ -15,75 +15,89 @@ export const meta = {
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
listId: $.type(ID).note({
|
listId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'リストのID'
|
'ja-JP': 'リストのID'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
limit: $.num.optional.range(1, 100).note({
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
default: 10,
|
default: 10,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '最大数'
|
'ja-JP': '最大数'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceId: $.type(ID).optional.note({
|
sinceId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより新しい投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilId: $.type(ID).optional.note({
|
untilId: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
'ja-JP': '指定すると、この投稿を基点としてより古い投稿を取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
sinceDate: $.num.optional.note({
|
sinceDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
untilDate: $.num.optional.note({
|
untilDate: {
|
||||||
|
validator: $.num.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
'ja-JP': '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeMyRenotes: $.bool.optional.note({
|
includeMyRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
'ja-JP': '自分の行ったRenoteを含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeRenotedMyNotes: $.bool.optional.note({
|
includeRenotedMyNotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
'ja-JP': 'Renoteされた自分の投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
includeLocalRenotes: $.bool.optional.note({
|
includeLocalRenotes: {
|
||||||
|
validator: $.bool.optional,
|
||||||
default: true,
|
default: true,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
'ja-JP': 'Renoteされたローカルの投稿を含めるかどうか'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
withFiles: $.bool.optional.note({
|
withFiles: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
mediaOnly: {
|
||||||
|
validator: $.bool.optional,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
'ja-JP': 'true にすると、ファイルが添付された投稿だけ取得します (このパラメータは廃止予定です。代わりに withFiles を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,49 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
import { pack } from '../../../../models/user';
|
import { pack } from '../../../../models/user';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import { getFriendIds } from '../../common/get-friends';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定したユーザーのフォロワー一覧を取得します。',
|
||||||
|
'en-US': 'Get followers of a user.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
cursor: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
default: null as any,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
iknow: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get followers of a user
|
|
||||||
*/
|
|
||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Get 'iknow' parameter
|
|
||||||
const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
|
|
||||||
if (iknowErr) return rej('invalid iknow param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'cursor' parameter
|
|
||||||
const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
|
|
||||||
if (cursorErr) return rej('invalid cursor param');
|
|
||||||
|
|
||||||
// Lookup user
|
// Lookup user
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
@ -43,7 +60,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
// ログインしていてかつ iknow フラグがあるとき
|
// ログインしていてかつ iknow フラグがあるとき
|
||||||
if (me && iknow) {
|
if (me && ps.iknow) {
|
||||||
// Get my friends
|
// Get my friends
|
||||||
const myFriends = await getFriendIds(me._id);
|
const myFriends = await getFriendIds(me._id);
|
||||||
|
|
||||||
|
@ -53,29 +70,27 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
// カーソルが指定されている場合
|
// カーソルが指定されている場合
|
||||||
if (cursor) {
|
if (ps.cursor) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$lt: ps.cursor
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get followers
|
// Get followers
|
||||||
const following = await Following
|
const following = await Following
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit + 1,
|
limit: ps.limit + 1,
|
||||||
sort: { _id: -1 }
|
sort: { _id: -1 }
|
||||||
});
|
});
|
||||||
|
|
||||||
// 「次のページ」があるかどうか
|
// 「次のページ」があるかどうか
|
||||||
const inStock = following.length === limit + 1;
|
const inStock = following.length === ps.limit + 1;
|
||||||
if (inStock) {
|
if (inStock) {
|
||||||
following.pop();
|
following.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize
|
|
||||||
const users = await Promise.all(following.map(f => pack(f.followerId, me, { detail: true })));
|
const users = await Promise.all(following.map(f => pack(f.followerId, me, { detail: true })));
|
||||||
|
|
||||||
// Response
|
|
||||||
res({
|
res({
|
||||||
users: users,
|
users: users,
|
||||||
next: inStock ? following[following.length - 1]._id : null,
|
next: inStock ? following[following.length - 1]._id : null,
|
||||||
|
|
|
@ -1,32 +1,49 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import User, { ILocalUser } from '../../../../models/user';
|
import User, { ILocalUser } from '../../../../models/user';
|
||||||
import Following from '../../../../models/following';
|
import Following from '../../../../models/following';
|
||||||
import { pack } from '../../../../models/user';
|
import { pack } from '../../../../models/user';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import { getFriendIds } from '../../common/get-friends';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定したユーザーのフォロー一覧を取得します。',
|
||||||
|
'en-US': 'Get following users of a user.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
cursor: {
|
||||||
|
validator: $.type(ID).optional,
|
||||||
|
default: null as any,
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
iknow: {
|
||||||
|
validator: $.bool.optional,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get following users of a user
|
|
||||||
*/
|
|
||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Get 'iknow' parameter
|
|
||||||
const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
|
|
||||||
if (iknowErr) return rej('invalid iknow param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'cursor' parameter
|
|
||||||
const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
|
|
||||||
if (cursorErr) return rej('invalid cursor param');
|
|
||||||
|
|
||||||
// Lookup user
|
// Lookup user
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
@ -43,7 +60,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
// ログインしていてかつ iknow フラグがあるとき
|
// ログインしていてかつ iknow フラグがあるとき
|
||||||
if (me && iknow) {
|
if (me && ps.iknow) {
|
||||||
// Get my friends
|
// Get my friends
|
||||||
const myFriends = await getFriendIds(me._id);
|
const myFriends = await getFriendIds(me._id);
|
||||||
|
|
||||||
|
@ -53,29 +70,27 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
// カーソルが指定されている場合
|
// カーソルが指定されている場合
|
||||||
if (cursor) {
|
if (ps.cursor) {
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$lt: ps.cursor
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get followers
|
// Get followers
|
||||||
const following = await Following
|
const following = await Following
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit + 1,
|
limit: ps.limit + 1,
|
||||||
sort: { _id: -1 }
|
sort: { _id: -1 }
|
||||||
});
|
});
|
||||||
|
|
||||||
// 「次のページ」があるかどうか
|
// 「次のページ」があるかどうか
|
||||||
const inStock = following.length === limit + 1;
|
const inStock = following.length === ps.limit + 1;
|
||||||
if (inStock) {
|
if (inStock) {
|
||||||
following.pop();
|
following.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize
|
|
||||||
const users = await Promise.all(following.map(f => pack(f.followeeId, me, { detail: true })));
|
const users = await Promise.all(following.map(f => pack(f.followeeId, me, { detail: true })));
|
||||||
|
|
||||||
// Response
|
|
||||||
res({
|
res({
|
||||||
users: users,
|
users: users,
|
||||||
next: inStock ? following[following.length - 1]._id : null,
|
next: inStock ? following[following.length - 1]._id : null,
|
||||||
|
|
|
@ -1,19 +1,31 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
import User, { pack, ILocalUser } from '../../../../models/user';
|
import User, { pack, ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
requireCredential: false,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.num.optional.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'userId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
if (psErr) return rej(psErr);
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Lookup user
|
// Lookup user
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
}, {
|
}, {
|
||||||
fields: {
|
fields: {
|
||||||
_id: true
|
_id: true
|
||||||
|
@ -83,7 +95,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
|
const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
|
||||||
|
|
||||||
// Extract top replied users
|
// Extract top replied users
|
||||||
const topRepliedUsers = repliedUsersSorted.slice(0, limit);
|
const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit);
|
||||||
|
|
||||||
// Make replies object (includes weights)
|
// Make replies object (includes weights)
|
||||||
const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
|
const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
|
||||||
|
@ -91,6 +103,5 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
weight: repliedUsers[user] / peak
|
weight: repliedUsers[user] / peak
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// Response
|
|
||||||
res(repliesObj);
|
res(repliesObj);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import UserList from '../../../../../models/user-list';
|
import UserList from '../../../../../models/user-list';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
@ -15,12 +15,14 @@ export const meta = {
|
||||||
kind: 'account-write',
|
kind: 'account-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
listId: $.type(ID).note({
|
listId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '対象となるユーザーリストのID',
|
'ja-JP': '対象となるユーザーリストのID',
|
||||||
'en-US': 'ID of target user list'
|
'en-US': 'ID of target user list'
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||||
import UserList from '../../../../../models/user-list';
|
import UserList from '../../../../../models/user-list';
|
||||||
import User, { pack as packUser, isRemoteUser, getGhost, ILocalUser } from '../../../../../models/user';
|
import User, { pack as packUser, isRemoteUser, getGhost, ILocalUser } from '../../../../../models/user';
|
||||||
import { publishUserListStream } from '../../../../../stream';
|
import { publishUserListStream } from '../../../../../stream';
|
||||||
import ap from '../../../../../remote/activitypub/renderer';
|
import ap from '../../../../../remote/activitypub/renderer';
|
||||||
import renderFollow from '../../../../../remote/activitypub/renderer/follow';
|
import renderFollow from '../../../../../remote/activitypub/renderer/follow';
|
||||||
import { deliver } from '../../../../../queue';
|
import { deliver } from '../../../../../queue';
|
||||||
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -14,20 +15,28 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'account-write'
|
kind: 'account-write',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
listId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a user to a user list
|
|
||||||
*/
|
|
||||||
export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'listId' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [listId, listIdErr] = $.type(ID).get(params.listId);
|
if (psErr) return rej(psErr);
|
||||||
if (listIdErr) return rej('invalid listId param');
|
|
||||||
|
|
||||||
// Fetch the list
|
// Fetch the list
|
||||||
const userList = await UserList.findOne({
|
const userList = await UserList.findOne({
|
||||||
_id: listId,
|
_id: ps.listId,
|
||||||
userId: me._id,
|
userId: me._id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,13 +44,9 @@ export default async (params: any, me: ILocalUser) => new Promise(async (res, re
|
||||||
return rej('list not found');
|
return rej('list not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'userId' parameter
|
|
||||||
const [userId, userIdErr] = $.type(ID).get(params.userId);
|
|
||||||
if (userIdErr) return rej('invalid userId param');
|
|
||||||
|
|
||||||
// Fetch the user
|
// Fetch the user
|
||||||
const user = await User.findOne({
|
const user = await User.findOne({
|
||||||
_id: userId
|
_id: ps.userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue