良い感じに
This commit is contained in:
parent
2b31b6a6b0
commit
1e4a86da8e
6 changed files with 106 additions and 672 deletions
|
@ -1,6 +1,6 @@
|
||||||
import * as Koa from 'koa';
|
import * as Koa from 'koa';
|
||||||
|
|
||||||
import { Endpoint } from './endpoints';
|
import Endpoint from './endpoint';
|
||||||
import authenticate from './authenticate';
|
import authenticate from './authenticate';
|
||||||
import call from './call';
|
import call from './call';
|
||||||
import { IUser } from '../../models/user';
|
import { IUser } from '../../models/user';
|
||||||
|
|
|
@ -1,44 +1,66 @@
|
||||||
import endpoints, { Endpoint } from './endpoints';
|
import * as path from 'path';
|
||||||
|
import * as glob from 'glob';
|
||||||
|
|
||||||
|
import Endpoint from './endpoint';
|
||||||
import limitter from './limitter';
|
import limitter from './limitter';
|
||||||
import { IUser } from '../../models/user';
|
import { IUser } from '../../models/user';
|
||||||
import { IApp } from '../../models/app';
|
import { IApp } from '../../models/app';
|
||||||
|
|
||||||
|
const files = glob.sync('**/*.js', {
|
||||||
|
cwd: path.resolve(__dirname + '/endpoints/')
|
||||||
|
});
|
||||||
|
|
||||||
|
const endpoints: Array<{
|
||||||
|
exec: any,
|
||||||
|
meta: Endpoint
|
||||||
|
}> = files.map(f => {
|
||||||
|
const ep = require('./endpoints/' + f);
|
||||||
|
|
||||||
|
ep.meta = ep.meta || {};
|
||||||
|
ep.meta.name = f.replace('.js', '');
|
||||||
|
|
||||||
|
return {
|
||||||
|
exec: ep.default,
|
||||||
|
meta: ep.meta
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => {
|
export default (endpoint: string | Endpoint, user: IUser, app: IApp, data: any, file?: any) => new Promise<any>(async (ok, rej) => {
|
||||||
const isSecure = user != null && app == null;
|
const isSecure = user != null && app == null;
|
||||||
|
|
||||||
const epName = typeof endpoint === 'string' ? endpoint : endpoint.name;
|
const epName = typeof endpoint === 'string' ? endpoint : endpoint.name;
|
||||||
const ep = endpoints.find(e => e.name === epName);
|
const ep = endpoints.find(e => e.meta.name === epName);
|
||||||
|
|
||||||
if (ep.secure && !isSecure) {
|
if (ep.meta.secure && !isSecure) {
|
||||||
return rej('ACCESS_DENIED');
|
return rej('ACCESS_DENIED');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ep.withCredential && user == null) {
|
if (ep.meta.requireCredential && user == null) {
|
||||||
return rej('SIGNIN_REQUIRED');
|
return rej('SIGNIN_REQUIRED');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ep.withCredential && user.isSuspended) {
|
if (ep.meta.requireCredential && user.isSuspended) {
|
||||||
return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED');
|
return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app && ep.kind) {
|
if (app && ep.meta.kind) {
|
||||||
if (!app.permission.some(p => p === ep.kind)) {
|
if (!app.permission.some(p => p === ep.meta.kind)) {
|
||||||
return rej('PERMISSION_DENIED');
|
return rej('PERMISSION_DENIED');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ep.withCredential && ep.limit) {
|
if (ep.meta.requireCredential && ep.meta.limit) {
|
||||||
try {
|
try {
|
||||||
await limitter(ep, user); // Rate limit
|
await limitter(ep.meta, user); // Rate limit
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// drop request if limit exceeded
|
// drop request if limit exceeded
|
||||||
return rej('RATE_LIMIT_EXCEEDED');
|
return rej('RATE_LIMIT_EXCEEDED');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let exec = require(`${__dirname}/endpoints/${ep.name}`).default;
|
let exec = ep.exec;
|
||||||
|
|
||||||
if (ep.withFile && file) {
|
if (ep.meta.withFile && file) {
|
||||||
exec = exec.bind(null, file);
|
exec = exec.bind(null, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
60
src/server/api/endpoint.ts
Normal file
60
src/server/api/endpoint.ts
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
export default interface IEndpoint {
|
||||||
|
/**
|
||||||
|
* エンドポイント名
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このエンドポイントにリクエストするのにユーザー情報が必須か否か
|
||||||
|
* 省略した場合は false として解釈されます。
|
||||||
|
*/
|
||||||
|
requireCredential?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* エンドポイントのリミテーションに関するやつ
|
||||||
|
* 省略した場合はリミテーションは無いものとして解釈されます。
|
||||||
|
* また、withCredential が false の場合はリミテーションを行うことはできません。
|
||||||
|
*/
|
||||||
|
limit?: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 複数のエンドポイントでリミットを共有したい場合に指定するキー
|
||||||
|
*/
|
||||||
|
key?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* リミットを適用する期間(ms)
|
||||||
|
* このプロパティを設定する場合、max プロパティも設定する必要があります。
|
||||||
|
*/
|
||||||
|
duration?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* durationで指定した期間内にいくつまでリクエストできるのか
|
||||||
|
* このプロパティを設定する場合、duration プロパティも設定する必要があります。
|
||||||
|
*/
|
||||||
|
max?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最低でもどれくらいの間隔を開けてリクエストしなければならないか(ms)
|
||||||
|
*/
|
||||||
|
minInterval?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ファイルの添付を必要とするか否か
|
||||||
|
* 省略した場合は false として解釈されます。
|
||||||
|
*/
|
||||||
|
withFile?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* サードパーティアプリからはリクエストすることができないか否か
|
||||||
|
* 省略した場合は false として解釈されます。
|
||||||
|
*/
|
||||||
|
secure?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* エンドポイントの種類
|
||||||
|
* パーミッションの実現に利用されます。
|
||||||
|
*/
|
||||||
|
kind?: string;
|
||||||
|
}
|
|
@ -1,659 +0,0 @@
|
||||||
const ms = require('ms');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* エンドポイントを表します。
|
|
||||||
*/
|
|
||||||
export type Endpoint = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* エンドポイント名
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* このエンドポイントにリクエストするのにユーザー情報が必須か否か
|
|
||||||
* 省略した場合は false として解釈されます。
|
|
||||||
*/
|
|
||||||
withCredential?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* エンドポイントのリミテーションに関するやつ
|
|
||||||
* 省略した場合はリミテーションは無いものとして解釈されます。
|
|
||||||
* また、withCredential が false の場合はリミテーションを行うことはできません。
|
|
||||||
*/
|
|
||||||
limit?: {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 複数のエンドポイントでリミットを共有したい場合に指定するキー
|
|
||||||
*/
|
|
||||||
key?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* リミットを適用する期間(ms)
|
|
||||||
* このプロパティを設定する場合、max プロパティも設定する必要があります。
|
|
||||||
*/
|
|
||||||
duration?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* durationで指定した期間内にいくつまでリクエストできるのか
|
|
||||||
* このプロパティを設定する場合、duration プロパティも設定する必要があります。
|
|
||||||
*/
|
|
||||||
max?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最低でもどれくらいの間隔を開けてリクエストしなければならないか(ms)
|
|
||||||
*/
|
|
||||||
minInterval?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ファイルの添付を必要とするか否か
|
|
||||||
* 省略した場合は false として解釈されます。
|
|
||||||
*/
|
|
||||||
withFile?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* サードパーティアプリからはリクエストすることができないか否か
|
|
||||||
* 省略した場合は false として解釈されます。
|
|
||||||
*/
|
|
||||||
secure?: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* エンドポイントの種類
|
|
||||||
* パーミッションの実現に利用されます。
|
|
||||||
*/
|
|
||||||
kind?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const endpoints: Endpoint[] = [
|
|
||||||
{
|
|
||||||
name: 'meta'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'stats'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'username/available'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'my/apps',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'app/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1day'),
|
|
||||||
max: 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'app/show'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'app/name_id/available'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth/session/generate'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth/session/show'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth/session/userkey'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth/accept',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'auth/deny',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/notes',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users/activity',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users/note',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users/followers'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users/following'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/users/reaction'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/notes/renote'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/notes/reply'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/notes/reaction'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'aggregation/notes/reactions'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'sw/register',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'i',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/2fa/register',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/2fa/unregister',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/2fa/done',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/update',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1day'),
|
|
||||||
max: 50
|
|
||||||
},
|
|
||||||
kind: 'account-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/update_home',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/update_mobile_home',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/update_widget',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/change_password',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/regenerate_token',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/update_client_setting',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/pin',
|
|
||||||
kind: 'account-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/appdata/get',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/appdata/set',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/signin_history',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'i/authorized_apps',
|
|
||||||
withCredential: true,
|
|
||||||
secure: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'i/notifications',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'notification-read'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'i/favorites',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'favorites-read'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'games/reversi/match',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'games/reversi/match/cancel',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'games/reversi/invitations',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'games/reversi/games',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'games/reversi/games/show'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'mute/create',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account/write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'mute/delete',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account/write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'mute/list',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account/read'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'notifications/delete',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'notification-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notifications/delete_all',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'notification-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notifications/mark_as_read_all',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'notification-write'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'drive',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/stream',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
withFile: true,
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/upload_from_url',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 10
|
|
||||||
},
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/show',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/find',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/delete',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/files/update',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/folders',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/folders/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 50
|
|
||||||
},
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/folders/show',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/folders/find',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'drive/folders/update',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'drive-write'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'users'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/show'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/search_by_username'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/notes'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/following'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/followers'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/recommendation',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/get_frequently_replied_users'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'users/lists/show',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/lists/create',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/lists/push',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'users/lists/list',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'account-read'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'following/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/delete',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/requests/accept',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/requests/reject',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/requests/cancel',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/requests/list',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'following-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/stalk',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'following/unstalk',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'following-write'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'notes'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/show'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/replies'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/conversation'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 300,
|
|
||||||
minInterval: ms('1second')
|
|
||||||
},
|
|
||||||
kind: 'note-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/delete',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'note-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/renotes'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/search'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/search_by_tag'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/timeline',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/local-timeline',
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/hybrid-timeline',
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/global-timeline',
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/user-list-timeline',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/mentions',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('10minutes'),
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/trend',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/categorize',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/reactions',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/reactions/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 300
|
|
||||||
},
|
|
||||||
kind: 'reaction-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/reactions/delete',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'reaction-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/favorites/create',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'favorite-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/favorites/delete',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'favorite-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/polls/vote',
|
|
||||||
withCredential: true,
|
|
||||||
limit: {
|
|
||||||
duration: ms('1hour'),
|
|
||||||
max: 100
|
|
||||||
},
|
|
||||||
kind: 'vote-write'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'notes/polls/recommendation',
|
|
||||||
withCredential: true
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'hashtags/trend'
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'messaging/history',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'messaging-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'messaging/messages',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'messaging-read'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'messaging/messages/create',
|
|
||||||
withCredential: true,
|
|
||||||
kind: 'messaging-write'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export default endpoints;
|
|
|
@ -1,4 +1,5 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
||||||
|
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';
|
||||||
import DriveFile, { IDriveFile } from '../../../../models/drive-file';
|
import DriveFile, { IDriveFile } from '../../../../models/drive-file';
|
||||||
|
@ -13,6 +14,16 @@ export const meta = {
|
||||||
ja: '投稿します。'
|
ja: '投稿します。'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
requireCredential: true,
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
duration: ms('1hour'),
|
||||||
|
max: 300,
|
||||||
|
minInterval: ms('1second')
|
||||||
|
},
|
||||||
|
|
||||||
|
kind: 'note-write',
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({
|
visibility: $.str.optional.or(['public', 'home', 'followers', 'specified', 'private']).note({
|
||||||
default: 'public',
|
default: 'public',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as Limiter from 'ratelimiter';
|
import * as Limiter from 'ratelimiter';
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import limiterDB from '../../db/redis';
|
import limiterDB from '../../db/redis';
|
||||||
import { Endpoint } from './endpoints';
|
import Endpoint from './endpoint';
|
||||||
import getAcct from '../../misc/acct/render';
|
import getAcct from '../../misc/acct/render';
|
||||||
import { IUser } from '../../models/user';
|
import { IUser } from '../../models/user';
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue